require-rag-content-validation
This rule identifies code patterns where content retrieved from vector stores or document retrieval systems is used d...
Requires validation of RAG content before including in AI prompts.
📊 Rule Details
| Property | Value |
|---|---|
| Type | suggestion |
| Severity | 🟡 MEDIUM |
| OWASP Agentic | ASI07: Poisoned RAG Pipeline |
| CWE | CWE-74: Improper Neutralization |
| CVSS | 6.0 |
| Config Default | warn (recommended), error (strict) |
🔍 What This Rule Detects
This rule identifies code patterns where content retrieved from vector stores or document retrieval systems is used directly in AI prompts without validation.
❌ Incorrect Code
// Direct vector store results in prompt
const docs = await vectorStore.search(query);
await generateText({
prompt: `Based on these documents: ${docs}`,
});
// Unvalidated RAG inline
await streamText({
prompt: `Context: ${await retrieve(query)}`,
});
// Direct search results
const results = await similaritySearch(embedding);
await generateObject({
prompt: `Use this context: ${results}`,
});✅ Correct Code
// Validated RAG content
const docs = await vectorStore.search(query);
await generateText({
prompt: buildPrompt(validateContent(docs)),
});
// Sanitized retrieval
await streamText({
prompt: `Context: ${sanitize(await retrieve(query))}`,
});
// Filtered results
const docs = await similaritySearch(embedding);
const safeDocs = filterDocs(docs);
await generateObject({
prompt: buildRAGPrompt(safeDocs),
});⚙️ Options
| Option | Type | Default | Description |
|---|---|---|---|
ragPatterns | string[] | ["search","retrieve","query","vectorStore","embeddings","similaritySearch","findSimilar","getDocuments","fetchDocs","documents","chunks","passages"] | Patterns suggesting RAG operations |
validatorFunctions | string[] | ["validate","sanitize","filter","clean","verify","validateRag","sanitizeContent","filterDocs"] | Functions that validate RAG content |
🛡️ Why This Matters
Poisoned RAG content can:
- Inject instructions - Malicious documents override AI behavior
- Bypass safety - Documents contain jailbreak prompts
- Exfiltrate data - Documents request sensitive information
- Spread misinformation - AI presents false information as fact
🔗 Related Rules
require-validated-prompt- Validate user promptsno-dynamic-system-prompt- Static system prompts
🔄 Changes in the 2026-10-10 FP/FN audit
- RAG calls and validators are matched by whole word of the call chain
(
researchTopicis not asearch);contextwas removed from the defaults. - Options: the documented
defaultOptionsnow apply. Earlier versions readcontext.optionsand silently ran a shorter hard-coded list instead.
🔄 Changes in the 2026-10-11 zero-deferral pass
- Retrieved content is followed through derivations —
.map,.filter,.join,.slice, member reads, templates — and through the returns of same-file helpers intoprompt/system:docs.map((d) => d.pageContent).join('\n')into acontextvariable is reported. A call to a configured validator (including a same-file one) stops the trace. The previous name-based variable tracking was removed.
Known False Negatives
The following patterns are not detected due to static analysis limitations:
Validation in Retrieval Function
Why: Validation inside retrieval functions is not visible.
// ❌ NOT DETECTED - Validation in retrieve
await generateText({
prompt: await safeRetrieve(query), // Validates internally
});Mitigation: Document validation. Apply rule to retrieval functions.
Custom RAG Patterns
Why: Non-standard retrieval methods may not be recognized.
// ❌ NOT DETECTED - Custom retrieval
const context = await myDocumentFetcher.get(query);
await generateText({ prompt: `Context: ${context}` });Mitigation: Configure ragPatterns with custom method names.
Template Builders
Why: Template functions may hide RAG content.
// ❌ NOT DETECTED - Template obscures RAG
const prompt = buildRAGPrompt(docs); // Validation inside?
await generateText({ prompt });Mitigation: Apply validation to template inputs.
Streamed RAG Content
Why: Streaming retrieval may not be detected.
// ❌ NOT DETECTED - Streaming RAG
for await (const doc of streamDocuments(query)) {
// Each doc needs validation
}Mitigation: Validate each streamed chunk.
📚 References
Use this rule
npm install -D oxlint-plugin-vercel-ai-security{ "jsPlugins": ["oxlint-plugin-vercel-ai-security"], "rules": { "vercel-ai-security/require-rag-content-validation": "error" }}import { defineConfig } from 'vite-plus';export default defineConfig({ lint: { jsPlugins: ['oxlint-plugin-vercel-ai-security'], rules: { 'vercel-ai-security/require-rag-content-validation': 'error', }, },});oxlint-plugin-vercel-ai-security re-exports eslint-plugin-vercel-ai-security/oxlint: the same rules under the same IDs, and no ESLint install. Why oxlint.
Did this rule catch something? Star the repo to get new CWE coverage as we ship it — or follow the AI-code-security benchmarks behind these rules.