Secure Weaviate with cnspec
Scan Weaviate vector databases and their role-based access control against security best practices with cnspec.
Scan your Weaviate vector databases to find security risks before they become incidents. cnspec evaluates anonymous access, OIDC configuration, role-based access control and the permissions each role grants, users and their assignments, collection multi-tenancy and replication, enabled modules, and cluster node health.
cnspec inventories the server through read-only requests to the REST API. It never reads your vectors.
Weaviate has no published CIS benchmark. The resources target the security-relevant configuration surface: anonymous access, authentication and OIDC, RBAC least-privilege, multi-tenancy isolation, and replication.
If you're new to cnspec, start with the Quickstart. For an overview of every database cnspec can scan, see the database scanning overview.
Prerequisites
To scan Weaviate with cnspec, you must have:
- cnspec installed on your workstation
- Network access to the REST API (port 8080 by default)
- A Weaviate API key, ideally mapped to the built-in
viewerrole
Authenticate
cnspec authenticates with a Weaviate API key, sent as a bearer token:
cnspec shell weaviate weaviate.contoso.com --api-key API_KEYUse --ask-api-key to be prompted rather than passing the key as a flag. For a server behind a private CA:
cnspec shell weaviate weaviate.contoso.com --scheme https --api-key API_KEY --tls-ca ca.pemPrefer a least-privileged API key for auditing. The built-in viewer role reads everything below. A more restricted key still resolves the server metadata, and the roles, users, and node collections it cannot read come back empty rather than failing the scan.
Where the server allows anonymous access, the API key can be omitted entirely, which is itself the first thing worth checking.
Connection options
| Option | Description |
|---|---|
--host | Server hostname or IP address (also accepted as the positional argument) |
--port | REST API port (default 8080) |
--scheme | http (default) or https |
--api-key | API key to authenticate with, or --ask-api-key to be prompted |
--tls-ca | Path to a CA certificate to verify an https server with a private CA |
--tls-insecure | Skip TLS certificate verification (testing only) |
--discover | auto (default), all, collections, instance, or none |
Verify with a quick Weaviate check
cnspec shell weaviate weaviate.contoso.com --api-key API_KEYcnspec> weaviate.instance { version rbacEnabled anonymousAccessEnabled oidcEnabled }
weaviate.instance: {
version: "1.38.9"
rbacEnabled: true
anonymousAccessEnabled: false
oidcEnabled: false
}If cnspec connects and shows the version, you're ready to scan.
Scan Weaviate
By default cnspec discovers each collection as its own weaviate-collection asset alongside the server asset:
cnspec scan weaviate weaviate.contoso.com --api-key API_KEYTo scan the server only:
cnspec scan weaviate weaviate.contoso.com --api-key API_KEY --discover noneWhen a scan completes, cnspec prints a summary of all the checks it ran, grouped by policy, along with a risk score from 0 (no risk) to 100 (highest risk). Failed checks include remediation guidance to help you fix issues. To learn more about reading scan results, read Understand cnspec Results.
Mondoo doesn't yet ship an out-of-the-box Weaviate policy, so use the checks below as a starting point and create your own policies to meet your specific requirements.
Explore and test checks interactively
cnspec shell weaviate weaviate.contoso.com --api-key API_KEYList collections
cnspec> weaviate.instance.collections { name vectorizer vectorIndexType replicationFactor multiTenancyEnabled }List custom roles
cnspec> weaviate.instance.roles.where(isBuiltin == false) { name assignedUsers }Inspect what a role permits
cnspec> weaviate.instance.roles.where(name == "articleReader").first { permissions { action collection } assignedUsers }
weaviate.instance.roles.where.first: {
permissions: [
0: { action: "read_data" collection: "Article" }
1: { action: "read_collections" collection: "Article" }
]
assignedUsers: [
0: "viewer-user"
]
}List users
cnspec> weaviate.instance.users { userId userType active roles { name } }List enabled modules and nodes
cnspec> weaviate.instance { modules nodes { name status shardCount objectCount } }Example security checks
Ensure anonymous access is disabled
Anonymous access means anyone who can reach the port can query the vectors:
cnspec> weaviate.instance.anonymousAccessEnabled == false
[ok] value: trueEnsure role-based access control is enabled
Without RBAC, every authenticated caller holds the same access:
cnspec> weaviate.instance.rbacEnabled == true
[ok] value: trueEnsure OIDC is configured
OIDC moves authentication to your identity provider, so accounts follow joiners and leavers:
cnspec> weaviate.instance.oidcEnabled == true
[ok] value: trueEnsure no custom role reaches every collection
A * collection scope grants the action across everything, including collections created later:
cnspec> weaviate.instance.roles.where(isBuiltin == false).all(permissions.none(collection == "*"))
[ok] value: trueEnsure no custom role can manage roles
manage_roles lets the holder grant itself anything else:
cnspec> weaviate.instance.roles.where(isBuiltin == false).all(permissions.none(action == "manage_roles"))
[ok] value: trueEnsure the root role is held narrowly
cnspec> weaviate.instance.roles.where(name == "root") { assignedUsers }Ensure multi-tenant collections do not create tenants on demand
autoTenantCreation materializes a tenant on first use, so a caller naming an unknown tenant gets a working one rather than an error:
cnspec> weaviate.instance.collections.where(multiTenancyEnabled).none(autoTenantCreation == true)
[ok] value: trueEnsure collections are replicated
A replicationFactor of 1 means a single node loss takes the collection with it:
cnspec> weaviate.instance.collections.all(replicationFactor > 1)
[ok] value: trueEnsure every user is accounted for
cnspec> weaviate.instance.users.where(active == false) { userId userType }Ensure all nodes are healthy
cnspec> weaviate.instance.nodes.all(status == "HEALTHY")
[ok] value: trueReview collections that send data to an external vectorizer
A vectorizer module other than none sends object text to whatever service backs it, which may be outside your boundary:
cnspec> weaviate.instance.collections.where(vectorizer != "none") { name vectorizer modules }Learn more
- Weaviate Resource Pack Reference: every Weaviate resource and field cnspec can query
- Write Effective MQL: guide to authoring checks and queries