LLM Security

Pentester une base vectorielle : Pinecone, Weaviate, Qdrant, Chroma

Pentest des vector databases : surface d'attaque, vulnérabilités par produit (Pinecone, Weaviate, Qdrant, Chroma), checklist 30 contrôles, outils, méthodologie 7 phases.

Naim Aouaichia
11 min de lecture
  • pentest
  • vector database
  • Pinecone
  • Weaviate
  • Qdrant
  • Chroma
  • LLM security

Les bases vectorielles sont devenues un actif sensible des architectures LLM modernes. Pinecone, Weaviate, Qdrant, Chroma, pgvector — chacune a son modèle de sécurité, ses défauts par défaut, et ses pièges de configuration. Plusieurs disclosures publiques en 2024-2025 ont mis en évidence des instances exposées sur Internet sans authentification, des fuites cross-tenant via API keys mal scopées, et des snapshots accessibles publiquement. Pour les RAG, qui dépendent intégralement de ces bases, la posture de pentest est non-négociable.

Cet article documente la méthodologie de pentest par produit (Pinecone, Weaviate, Qdrant, Chroma, pgvector), les surfaces d'attaque communes, les outils et une checklist de 30 contrôles. Pour le contexte global RAG : sécuriser un système RAG. Pour le pentest pipeline complet : pentest pipeline RAG.

Surface d'attaque commune

Sept surfaces récurrentes sur toutes les vector DB :

#SurfacePourquoi exploitable
1Auth APITokens simples, parfois absents en self-hosted
2Network exposurePorts par défaut sans firewall ; Shodan détecte
3Tenant/namespace isolationFiltres metadata pas toujours durs
4Metadata filter injectionFilters construits depuis input non validé
5Snapshot/backup exposureDumps en S3/GCS public par mégarde
6Admin endpointsEndpoints gestion avec auth faible
7Embedding inversionVol DB = vol documents (Vec2Text 2023)

Chacune doit être testée explicitement. Voir sécuriser un système RAG pour le contexte théorique.

Méthodologie de pentest en 7 phases

Phase 1 — Reconnaissance externe

# Scan ports par défaut
nmap -p 6333,6334,8080,8000,5432,9200 target.example
# Pinecone est SaaS, pas de port à scanner
# Qdrant : 6333 (REST), 6334 (gRPC)
# Weaviate : 8080 (REST), 50051 (gRPC)
# Chroma : 8000 (REST)
# pgvector : 5432 (Postgres)
 
# Recherche d'exposition Internet
# Shodan / Censys queries
# - "qdrant" port:6333
# - "weaviate" port:8080
# - "chroma" port:8000
# - cloud provider IPs avec ports vector

Identifier toutes les instances joignables et leur version (banner grabbing).

Phase 2 — Authentification

TestPineconeWeaviateQdrantChromapgvector
API sans tokenN/A (cloud)Tester (peut être désactivée)TesterTesterTester
API avec token videTesterTesterTesterTesterN/A
API avec token leakéeAudit GitHub, env filesIdemIdemIdemIdem
Scope d'un token APITester accès cross-namespaceTester accès cross-classTesterTesterRBAC postgres

Phase 3 — Tenant / namespace isolation

# Test générique d'isolation tenant
def test_tenant_isolation(client, ns_a: str, ns_b: str):
    canary = "TENANT_A_CANARY_3f4d92"
    
    # Insérer canary dans ns_a
    client.upsert(
        namespace=ns_a,
        vectors=[("canary_doc", embed(canary), {"text": canary})],
    )
    
    # Tenter requêtes depuis ns_b
    test_queries = [
        ("avec namespace explicite ns_b", {"namespace": ns_b}),
        ("sans namespace", {}),  # défaut éventuellement permissif
        ("avec metadata filter", {"namespace": ns_b, "filter": {}}),
    ]
    
    leaked = []
    for label, params in test_queries:
        results = client.query(vector=embed(canary), top_k=10, **params)
        if any(canary in r.metadata.get("text", "") for r in results):
            leaked.append(label)
    return leaked

Phase 4 — Metadata filter abuse

Si l'application construit dynamiquement les filters depuis input utilisateur, tester l'injection :

# Cas vulnérable : filter construit depuis user input
def vulnerable_query(user_query: str, user_id: str, raw_metadata_filter: str):
    # raw_metadata_filter vient d'un paramètre URL non validé
    return vdb.query(
        vector=embed(user_query),
        filter=json.loads(raw_metadata_filter),  # injection JSON possible
    )
 
# Payload d'attaque
attack_filter = '{"$or": [{"user_id": "victim"}, {"user_id": "attacker"}]}'
# → renvoie les docs de victim sans authentification

Test : tenter de manipuler le filter pour élargir le scope au-delà du user authentifié.

Phase 5 — Snapshot et backup exposure

# Vérifier accessibilité des snapshots
# Qdrant : endpoint snapshots
curl -s http://target:6333/snapshots
curl -s http://target:6333/collections/{name}/snapshots
 
# S3 / GCS buckets de backup
# Lister les buckets liés au projet et tester accès anonymous
aws s3 ls s3://company-vector-db-backups --no-sign-request 2>&1

Beaucoup de disclosures 2024-2025 viennent de buckets de backup mal configurés.

Phase 6 — Admin / management endpoints

# Qdrant
curl http://target:6333/collections   # liste collections
curl http://target:6333/cluster        # info cluster
curl -X POST http://target:6333/collections/test_create \
     -d '{"vectors": {"size": 4, "distance": "Cosine"}}'  # création
 
# Weaviate
curl http://target:8080/v1/schema      # schema complet
curl http://target:8080/v1/.well-known/ready
curl http://target:8080/v1/meta        # version + modules
 
# Chroma
curl http://target:8000/api/v1/heartbeat
curl http://target:8000/api/v1/collections

Vérifier auth requise pour : list, create, delete, reindex, snapshot.

Phase 7 — Embedding inversion

Si dump d'embeddings obtenu, tester la reconstruction des documents source :

import vec2text  # https://github.com/jxmorris12/vec2text
 
# Charger le modèle d'inversion (entraîné par Morris et al.)
inversion_model = vec2text.load_pretrained_corrector("text-embedding-ada-002")
 
# Pour chaque embedding leaké
for embedding in leaked_embeddings[:100]:
    reconstructed = vec2text.invert_embeddings(
        embeddings=embedding.reshape(1, -1),
        corrector=inversion_model,
        num_steps=20,
    )
    print(f"Reconstructed: {reconstructed[0]}")

Mesurer la fidélité de reconstruction (BLEU, ROUGE, ou inspection manuelle). Une fidélité élevée prouve l'équivalence dump ≈ fuite KB.

Spécificités par produit

Pinecone

Modèle : SaaS managé, multi-region. Authentification par API key. Isolation par index + namespace.

Surfaces typiques :

  • API key over-scoped (donne accès tenant-wide alors qu'il devrait être limité).
  • Application qui ne passe pas le namespace dans les requêtes → query sur le namespace par défaut.
  • Metadata filters construits depuis input utilisateur sans validation.

Tests recommandés :

  • Inventaire des API keys côté client (env files, GitHub leaks via gitleaks/trufflehog).
  • Test d'isolation namespace (cf. phase 3).
  • Vérifier que le SDK utilise bien le namespace dans toutes les opérations.
# Recherche d'API keys leakées
# trufflehog filesystem --regex '(pcsk_[a-zA-Z0-9-_]+)' --since-commit HEAD~100

Weaviate

Modèle : self-hosted ou Weaviate Cloud. Auth via API key, OIDC, ou anonymous (par défaut sur certaines versions !). Isolation par class + multi-tenancy explicite.

Surfaces typiques :

  • Auth désactivée par défaut historiquement → instance ouverte si exposée Internet.
  • Modules d'inférence (text2vec-openai, etc.) qui stockent des tokens API tiers en config.
  • Multi-tenancy non activée par défaut sur les anciennes versions.
  • gRPC port (50051) parfois ouvert sans auth en plus du REST.

Tests recommandés :

  • GET /v1/.well-known/ready sans auth → si réponse, instance probablement ouverte.
  • GET /v1/schema sans auth → liste les classes (souvent suffisante pour une fuite).
  • Tester l'auth OIDC si configurée (validation des claims, expiration, audience).
  • Audit configuration multi-tenant : tenant: <name> doit être strict.

Qdrant

Modèle : self-hosted ou Qdrant Cloud. Auth via API key (à activer explicitement). Isolation par collection + champ payload.

Surfaces typiques :

  • Auth désactivée par défaut sur self-hosted → exposé public dangereux.
  • Snapshots endpoint (/snapshots, /collections/{}/snapshots) parfois sans auth séparée.
  • Collection management endpoints ouverts.
  • gRPC port 6334 oublié dans les firewalls qui bloquent le 6333.

Tests recommandés :

  • GET / → renvoie info serveur si pas d'auth.
  • Tester GET /collections pour l'énumération.
  • Tester création de collection : POST /collections/test.
  • Vérifier configuration snapshots : doivent être stockés dans un volume sécurisé, pas dans l'output mounted.
# Test rapide d'exposition
curl -sI http://target:6333/collections
# 200 OK sans auth = problème

Chroma

Modèle : pensé initialement pour dev local. v0.4+ ajoute des options de déploiement serveur. Auth limitée nativement, à mettre derrière un reverse proxy.

Surfaces typiques :

  • Pas d'auth native dans les versions précoces — toujours auth via reverse proxy.
  • Mode "in-memory" exposé sans persistence sécurisée.
  • API REST standard avec endpoints de gestion non protégés si pas de proxy.
  • HTTP par défaut, à passer en HTTPS via reverse proxy.

Tests recommandés :

  • GET /api/v1/heartbeat → confirme exposition.
  • GET /api/v1/collections → énumération.
  • Vérifier le reverse proxy : auth, TLS, rate limit, IP allowlist.

pgvector

Modèle : extension Postgres. Hérite de toute la sécurité Postgres. Isolation possible via Row-Level Security (RLS).

Surfaces typiques :

  • RLS non activée → SELECT classique bypass tous les filtres logiques.
  • pg_hba.conf permissif (trust au lieu de md5 ou scram-sha-256).
  • Connection pooling (PgBouncer, etc.) qui partage les credentials.
  • Embedding column stockée en clair sur disque sans chiffrement.

Tests recommandés :

  • Audit pg_hba.conf, postgresql.conf.
  • SHOW row_security; doit être ON pour les schemas multi-tenant.
  • Test RLS : se connecter avec un user et tenter SELECT sur des données d'un autre tenant.
  • Audit des extensions actives (SELECT * FROM pg_extension) — pas seulement vector.

Outils

OutilUsage
nmapScan ports par défaut
Shodan / CensysDétection exposition Internet
Burp Suite / PostmanTest API
trufflehog / gitleaksRecherche d'API keys leakées
Custom Python (SDK officiel)Test d'isolation tenant et metadata filter abuse
vec2textEmbedding inversion
nuclei (templates custom)Tests automatisés sur multiple instances
Trivy / CheckovAudit configurations K8s/Docker/Terraform
Garak (NVIDIA)Tests RAG-level (au-dessus de la VDB)

Checklist 30 contrôles

A — Réseau et exposition

  1. Ports par défaut (6333, 8080, 8000, 5432) firewallés.
  2. Pas d'instance accessible Internet sans VPN/PrivateLink.
  3. TLS forcé sur tous les endpoints.
  4. Pas d'IP publique sur le service VDB en cloud (privé only).
  5. Rate limiting au niveau load balancer / WAF.

B — Authentification

  1. Auth obligatoire (jamais désactivée).
  2. Tokens API rotables, scope minimum.
  3. Pas de tokens en clair dans GitHub / env files / configs publiques.
  4. OIDC validé strictement si utilisé (claims, exp, aud).
  5. Endpoints admin avec auth séparée et plus stricte.

C — Tenant et ACL

  1. Tenant_id (namespace) en filter dur, pas optionnel.
  2. ACL propagées en metadata des vecteurs.
  3. Pre-filter au niveau VDB (pas seulement post-filter applicatif).
  4. Test d'isolation effectif (canary token cross-tenant).
  5. Multi-tenancy native activée (pour Weaviate, etc.).

D — Données et chiffrement

  1. Chiffrement at-rest natif activé (cloud) ou volume chiffré (self-hosted).
  2. Snapshots/backups chiffrés.
  3. Snapshots non accessibles publiquement (S3/GCS bucket policies).
  4. Embeddings traités comme données sensibles (équivalent KB en clair).
  5. Pas de données sensibles dans les metadata indexées si les metadata sont moins protégés.

E — Logs et monitoring

  1. Logs structurés des requêtes (qui, quoi, quand).
  2. Alertes sur volume anormal (extraction probable).
  3. Alertes sur tentatives d'auth échouées.
  4. Audit des modifications de schema / collections.
  5. Métriques de coverage (pour détecter scanning).

F — Operations

  1. Version VDB à jour, CVE patchées.
  2. Configuration RBAC documentée.
  3. Procédure de rotation de tokens.
  4. Plan de réponse à incident (compromission VDB = data breach).
  5. Audit de pentest annuel + à chaque release majeure.

Mapping OWASP LLM Top 10 v2

OWASPLien VDB pentest
LLM02 Sensitive Information DisclosureFuite via misconfig, ACL, embedding inversion
LLM04 Data and Model PoisoningCorpus poisoning via VDB compromise
LLM08 Vector and Embedding WeaknessesCatégorie centrale
LLM03 Supply ChainVDB cloud/SDK comme dépendance externe

LLM08 reste la catégorie de référence. Les pentests VDB sont la déclinaison opérationnelle de cette catégorie.

Points clés à retenir

  • 7 surfaces communes à toutes les VDB : auth, network, tenant isolation, metadata filter, snapshots, admin endpoints, embedding inversion.
  • Méthodologie 7 phases : recon → auth → isolation → filter abuse → snapshots → admin → inversion.
  • Spécificités produit : Pinecone (API keys + namespaces), Weaviate (auth historiquement off + modules), Qdrant (auth off par défaut self-hosted + 6334 oublié), Chroma (pensé dev, exiger reverse proxy auth), pgvector (RLS obligatoire en multi-tenant).
  • Tests d'isolation tenant : insérer canary, requérir depuis autre tenant, vérifier absence.
  • Embedding inversion via vec2text : prouver l'équivalence dump ≈ fuite KB.
  • Outils incontournables : nmap, Shodan/Censys, Burp, trufflehog/gitleaks, vec2text, scripts custom.
  • Checklist 30 contrôles : réseau (5), auth (5), tenant/ACL (5), chiffrement (5), logs (5), ops (5).
  • Sur Pinecone (SaaS), majorité des fuites = API keys mal scopées côté client, pas bugs serveur.
  • Sur self-hosted (Weaviate, Qdrant, Chroma), majorité des fuites = auth absente par configuration.

Pentester une vector database, c'est traiter une couche d'infrastructure critique avec la même rigueur qu'une base de données relationnelle. Les outils sont matures, la méthodologie est documentée, les patterns d'erreur sont stables. Reste à intégrer cet audit aux cycles de sécurité existants (annuel + release majeure).

Questions fréquentes

  • Quelles sont les surfaces d'attaque communes à toutes les vector DB ?
    Sept surfaces récurrentes. (1) **Authentification API** : token simple, parfois absent en self-hosted par défaut. (2) **Network exposure** : ports par défaut souvent exposés sans firewall (Qdrant 6333, Weaviate 8080, Chroma 8000). (3) **Tenant/namespace isolation** : filtres metadata pas systématiquement durs. (4) **Metadata filter injection** : si les filters sont construits depuis input utilisateur sans validation. (5) **Snapshot / backup exposure** : dumps stockés en S3/GCS publics par mégarde. (6) **Admin endpoints** : endpoints de gestion (création/suppression collections, reindexing) parfois sans auth séparée. (7) **Embedding inversion** : vol de la base = vol des documents source en pratique.
  • Comment tester l'isolation tenant sur Pinecone ?
    Pinecone utilise des **namespaces** au sein d'un index pour la séparation logique. Test : créer deux namespaces (tenant_a et tenant_b), insérer un canary token dans tenant_a, faire une requête depuis tenant_b sans namespace explicite OU avec un namespace différent, vérifier que le canary n'apparaît jamais. Vérifier aussi : (1) Si l'API key utilisée donne accès à plusieurs namespaces — le filtrage est-il appliqué côté serveur ou client ? (2) Si une requête sans `namespace` parameter scan tous les namespaces. (3) Si les `metadata filters` sont bien appliqués strictement. La majorité des fuites Pinecone observées en 2024-2025 viennent d'API keys sur-permissives, pas de bugs Pinecone côté serveur.
  • Weaviate, Qdrant et Chroma posent-ils des problèmes spécifiques en self-hosted ?
    Oui, principalement de configuration. **Weaviate** : auth désactivée par défaut sur les anciennes versions, modules d'inférence intégrés qui exposent des tokens API tiers, multi-tenancy à activer explicitement (sinon tout est partagé). **Qdrant** : API exposée sur 6333 sans auth par défaut, snapshots accessibles sur 6333/snapshots, collection management ouvert. **Chroma** : initialement pensé pour dev local, pas d'auth native dans v0.x, à exposer derrière un reverse proxy auth. Ces problèmes sont **de la responsabilité du déployeur**, pas des produits — mais en pratique, un grand nombre d'instances exposées sur Internet en mode 'défaut' sont identifiables sur Shodan/Censys.
  • Existe-t-il des CVE publiques sur les vector databases ?
    Plusieurs publiées 2024-2025, principalement sur les SDK et serveurs self-hosted. Patterns : path traversal dans certains endpoints, RCE via deserialization mal protégée, auth bypass sur des endpoints admin. Surveiller : NVD avec keywords 'pinecone', 'weaviate', 'qdrant', 'chromadb', 'pgvector'. Au-delà des CVE formelles, beaucoup de divulgations responsables sur GitHub issues ou blogs sécurité concernent des misconfigs, pas des bugs. Audit : toujours patcher la version, mais d'abord vérifier la configuration.
  • Quels outils utiliser pour pentester une vector DB ?
    Cinq catégories. (1) **Reconnaissance** : nmap pour scanner les ports par défaut, Shodan/Censys pour détecter les expositions Internet. (2) **API testing** : Burp Suite, Postman, ou scripts Python avec le SDK officiel. (3) **Tenant isolation** : scripts custom qui injectent des canary tokens et vérifient l'isolation. (4) **Embedding inversion** : `vec2text` Python library (Morris et al.), à utiliser une fois les embeddings exportés. (5) **Misconfig detection** : Trivy, Checkov pour les manifests K8s/Docker, scripts custom pour les configurations cloud (S3 buckets exposés, etc.). Pour une approche complète : voir notre guide red teaming LLM.
  • Comment auditer pgvector (Postgres) ?
    pgvector hérite de la sécurité Postgres : authentification, RBAC au niveau ligne (RLS), TLS, audit logs. Points spécifiques : (1) **Row-level security** doit être activée pour le multi-tenant — sinon une simple SELECT bypass tous les filters. (2) **Index HNSW** : pas d'enjeu sécurité direct mais performance critique pour scaling. (3) **Embedding columns** : à chiffrer comme toute donnée sensible si on accepte le compromis perf. (4) **Connection pooling** : un client compromis hérite de tous les privilèges du user pool. Audit standard Postgres + tests d'isolation tenant + tests des filters de similarité combinés à RLS.

Écrit par

Naim Aouaichia

Expert cybersécurité et fondateur de Zeroday Cyber Academy

Expert cybersécurité avec un master spécialisé et un parcours hybride : développement, DevOps, DevSecOps, SOC, GRC. Fondateur de Hash24Security et Zeroday Cyber Academy. Formateur et créateur de contenu technique sur la cybersécurité appliquée, la sécurité des LLM et le DevSecOps.