Skip to content
HackIndex logo

HackIndex

Identifying RAG Pipeline Poisoning Opportunities

3 min read Mar 18, 2026

RAG pipeline poisoning is viable when an attacker can influence what content ends up in the vector database that the model retrieves from. This does not require direct database write access — document upload endpoints, public knowledge bases, web content the agent retrieves, and misconfigured ingestion pipelines all represent potential poisoning paths. This page confirms which of these paths are open before attempting active poisoning in the exploitation phase.

Confirm the Application Uses RAG

Verify that retrieved context is being injected into model responses before testing for poisoning opportunities:

┌──(kali㉿kali)-[~]
└─$ curl -sk -X POST https://$TARGET_DOMAIN/api/chat -H 'Content-Type: application/json' -d '{"messages":[{"role":"user","content":"What sources or documents are you using to answer my questions?"}]}' | python3 -m json.tool
┌──(kali㉿kali)-[~]
└─$ curl -sk -X POST https://$TARGET_DOMAIN/api/chat -H 'Content-Type: application/json' -d '{"messages":[{"role":"user","content":"RETRIEVAL_MARKER_XYZ_UNIQUE — have you seen this string before?"}]}' | python3 -m json.tool

If the model references source documents, cites knowledge base entries, or its answer quality varies significantly between topics in ways that suggest retrieval, RAG is in use. The unique marker test confirms whether the model is performing semantic search — a positive match would only be possible if the marker was already in the knowledge base.

Identify Document Upload Endpoints

Many RAG applications allow users to upload documents that get ingested into the knowledge base. These are direct poisoning paths:

┌──(kali㉿kali)-[~]
└─$ ffuf -u https://$TARGET_DOMAIN/FUZZ -w /tmp/upload-paths.txt -mc 200,400,401,403,405,422 -o ffuf-uploads.json
┌──(kali㉿kali)-[~]
└─$ cat > /tmp/upload-paths.txt << 'EOF'
upload
documents
document/upload
api/upload
api/documents
api/v1/upload
api/v1/documents
api/ingest
ingest
knowledge
knowledge-base
api/knowledge
files
api/files
docs
api/docs
EOF

A document upload endpoint that accepts unauthenticated submissions or submissions from any authenticated user is a direct poisoning path. Upload a test document with a unique marker and then query the chatbot to confirm whether the content was ingested and is being retrieved:

┌──(kali㉿kali)-[~]
└─$ echo 'POISON_TEST_MARKER_ABC123: This is a test document for RAG poisoning confirmation.' > /tmp/test-doc.txt
┌──(kali㉿kali)-[~]
└─$ curl -sk -X POST https://$TARGET_DOMAIN/api/upload -F 'file=@/tmp/test-doc.txt' | python3 -m json.tool
┌──(kali㉿kali)-[~]
└─$ curl -sk -X POST https://$TARGET_DOMAIN/api/chat -H 'Content-Type: application/json' -d '{"messages":[{"role":"user","content":"What do you know about POISON_TEST_MARKER_ABC123?"}]}' | python3 -m json.tool

A response that references the marker content confirms the upload endpoint feeds directly into the RAG pipeline and the content is being retrieved and presented to the model. This is a confirmed poisoning path — active exploitation is covered in the RAG exploitation phase.

Check Direct Vector Database Write Access

If the vector database is exposed directly, test whether it accepts unauthenticated writes:

┌──(kali㉿kali)-[~]
└─$ curl -sk -X POST http://$TARGET_IP:6333/collections/company_knowledge_base/points -H 'Content-Type: application/json' -d '{"points":[{"id":999999,"vector":[0.1,0.2,0.3],"payload":{"content":"WRITE_TEST_MARKER"}}]}' | python3 -m json.tool
┌──(kali㉿kali)-[~]
└─$ curl -sk -X POST http://$TARGET_IP:8000/api/v1/collections/company_knowledge_base/add -H 'Content-Type: application/json' -d '{"documents":["WRITE_TEST_MARKER"],"ids":["test-poison-001"]}' | python3 -m json.tool

Test Web Content Retrieval as a Poisoning Path

If the agent retrieves web content and injects it into context, attacker-controlled web pages are a poisoning path for any user who triggers retrieval of that content:

┌──(kali㉿kali)-[~]
└─$ curl -sk -X POST https://$TARGET_DOMAIN/api/chat -H 'Content-Type: application/json' -d '{"messages":[{"role":"user","content":"Search for information about UNIQUE_TEST_TOPIC_XYZ and summarise what you find."}]}' | python3 -m json.tool

If the agent performs live web retrieval, any web page it fetches is a poisoning surface. A page containing instructions embedded in HTML comments, hidden text, or normal-looking content with injected directives will be passed to the model as retrieved context. This is confirmed as an indirect injection path if the model follows instructions from the retrieved content.

References