FlowiseAI/Flowise · critical · Error
Invalid SQL statement: load_extension is not allowed
Error message
Invalid SQL statement: load_extension is not allowed
What it means
Thrown by assertReadOnlySqlStatement (packages/components/src/validator.ts:397) when the statement contains 'load_extension(' (case-insensitive). SQLite's load_extension lets a query load arbitrary native code into the process; even though the statement may start with SELECT, this guard blocks the function call to prevent code execution via a malicious DB/LLM.
Source
Thrown at packages/components/src/validator.ts:397
export const assertReadOnlySqlStatement = (sql: string): void => {
if (!sql || typeof sql !== 'string') {
throw new Error('Invalid SQL statement: statement is required and must be a string')
}
let trimmed = sql.trim()
// Strip at most one trailing semicolon (+ trailing whitespace)
trimmed = trimmed.replace(/;\s*$/, '')
if (trimmed.includes(';')) {
throw new Error('Invalid SQL statement: multiple statements are not allowed')
}
if (!/^(SELECT|WITH)\b/i.test(trimmed)) {
throw new Error('Invalid SQL statement: only read-only SELECT/WITH statements are allowed')
}
if (/load_extension\s*\(/i.test(trimmed)) {
throw new Error('Invalid SQL statement: load_extension is not allowed')
}
}
/**
* Sanitize a file name to prevent path traversal attacks.
* Strips common storage prefixes, extracts the basename, runs it through
* the `sanitize-filename` package, and rejects anything that still looks unsafe.
*
* @param {string} name The file name to sanitize
*/
export const sanitizeFileName = (name: string): string => {
if (!name || typeof name !== 'string') {
throw new Error('Invalid file name: name is required')
}
// Strip the FILE-STORAGE:: prefix if present
let stripped = name.replace(/^FILE-STORAGE::/, '')
// Decode percent-encoded traversal sequences before basename extraction
try {View on GitHub (pinned to abe4a8601a)
Solutions
- Remove the load_extension call — Flowise does not allow it.
- Treat any LLM output containing load_extension as a prompt-injection attempt and reject the turn.
- Only ingest .sqlite files from trusted sources.
- Compile SQLite without load_extension support for defense-in-depth.
Example fix
// before
sql = "SELECT load_extension('/tmp/evil')"
// after
sql = 'SELECT name FROM sqlite_master WHERE type = \'table\'' // benign introspection Defensive patterns
Strategy: validation
Validate before calling
if (/load_extension\s*\(/i.test(String(sql ?? ''))) throw new Error('load_extension rejected (possible prompt injection)');
assertReadOnlySqlStatement(sql); Type guard
const isFreeOfLoadExtension = (s: unknown): s is string => typeof s === 'string' && !/load_extension\s*\(/i.test(s);
Try / catch
try { assertReadOnlySqlStatement(sql) } catch (e) { if (e instanceof Error && /load_extension/.test(e.message)) { /* treat as prompt injection: abort turn */ throw new SecurityError('load_extension attempt blocked') } else throw e } Prevention
- Treat any load_extension in LLM output as prompt injection and reject the turn.
- Only open .sqlite files from trusted sources.
- Compile SQLite without load_extension for defense-in-depth.
- Log and alert on this error so attacks are visible.
When it happens
Trigger: The SQL contains a call like "SELECT load_extension('/tmp/evil')" — typically from a malicious LLM response or an attacker-controlled .sqlite file with crafted views/triggers that emit such SQL.
Common situations: Security testing/fuzzing of the chain; loading a DB file from an untrusted source; a prompt-injection payload crafting the call.
Related errors
- Invalid SQL statement: statement is required and must be a s
- Invalid SQL statement: multiple statements are not allowed
- Invalid SQL statement: only read-only SELECT/WITH statements
- Invalid SQLite path: path traversal attempt detected
- Invalid SQLite path: encoded path traversal attempt detected
AI-assisted analysis of FlowiseAI/Flowise@abe4a8601a (2026-08-12).
Data as JSON: /api/errors/1197257d58f763ce.
Report an issue: GitHub.