FlowiseAI/Flowise · critical · Error

Invalid file path: path traversal attempt detected in "${key

Error message

Invalid file path: path traversal attempt detected in "${key}"

What it means

Thrown by getSafeFilePath() as the final containment guard: after resolving both baseDir and the key-joined path to absolute form, it computes path.relative(resolvedBase, resolvedPath) and rejects when that relative is '', '..', starts with '..'+sep, or is absolute. This catches any key that escapes baseDir via traversal sequences (`../`), symlinks resolving outside, absolute overrides, or a key that points at the baseDir root itself. The check is bypassed only if PATH_TRAVERSAL_SAFETY==='false', which must never be set in production.

Source

Thrown at packages/components/src/validator.ts:469

        decodedKey = decodeURIComponent(key)
    } catch {
        // malformed percent-encoding — keep the raw key; resolve/relative handle it safely
    }

    if (decodedKey.includes('\0')) {
        throw new Error(`Invalid file path: null byte detected in "${key}"`)
    }

    const resolvedBase = path.resolve(baseDir)
    const resolvedPath = path.resolve(resolvedBase, decodedKey)

    if (process.env.PATH_TRAVERSAL_SAFETY === 'false') {
        return resolvedPath
    }

    const relative = path.relative(resolvedBase, resolvedPath)
    if (relative === '' || relative === '..' || relative.startsWith('..' + path.sep) || path.isAbsolute(relative)) {
        throw new Error(`Invalid file path: path traversal attempt detected in "${key}"`)
    }

    return resolvedPath
}

View on GitHub (pinned to abe4a8601a)

Solutions

  1. Confirm PATH_TRAVERSAL_SAFETY is NOT set to 'false' in production — that setting disables this guard entirely.
  2. Sanitize the key to a single path segment (basename) before calling getSafeFilePath if directory structure is not required.
  3. Investigate the offending key in logs; if it is legitimate, restructure baseDir/key so the resolved path genuinely sits beneath baseDir.
  4. Ensure baseDir is itself a freshly created, dedicated sandbox dir (e.g. os.tmpdir() child) so escaped paths have nothing sensitive to reach.

Example fix

// before
const abs = getSafeFilePath(workspaceDir, req.params.key) // key may contain ../

// after
const safeKey = path.basename(req.params.key) // collapse to single segment first
if (safeKey !== req.params.key) {
    return res.status(400).json({ message: 'Invalid key' })
}
const abs = getSafeFilePath(workspaceDir, safeKey)
Defensive patterns

Strategy: validation

Validate before calling

// Collapse to a single segment first if directory structure isn't required
const safeKey = path.basename(key)
if (safeKey !== key) {
    return res.status(400).json({ message: 'Directory components are not allowed in the key' })
}
const abs = getSafeFilePath(baseDir, safeKey)

Type guard

const isRelativeSingleSegment = (baseDir: string, v: unknown): v is string => {
    if (typeof v !== 'string') return false
    const rel = path.relative(path.resolve(baseDir), path.resolve(baseDir, v))
    return rel !== '' && rel !== '..' && !rel.startsWith('..' + path.sep) && !path.isAbsolute(rel)
}

Try / catch

try {
    const abs = getSafeFilePath(baseDir, key)
} catch (e) {
    logger.warn('Path traversal blocked', { key, ip: req.ip })
    return res.status(400).json({ message: 'Invalid file path' })
}

Prevention

When it happens

Trigger: A key like `../../etc/passwd`; a key like `/etc/passwd` (absolute, escapes via override); a key that resolves to baseDir itself (relative === ''); encoded traversal `%2e%2e%2f` that decodes to `../`; a key referencing a symlinked target outside baseDir after resolution.

Common situations: Penetration testing; a buggy client that builds keys by concatenating user folders with relative paths; a multi-tenant storage layout where tenantId is missing and the key resolves to the shared root; misconfigured PATH_TRAVERSAL_SAFETY==='false' hiding the real escape.

Related errors


AI-assisted analysis of FlowiseAI/Flowise@abe4a8601a (2026-08-12). Data as JSON: /api/errors/749f16c74f6d2b71. Report an issue: GitHub.