Security [HIGH]: Prompt-injection guard trivially bypassable (regex-only, no Unicode normalization) #39
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
The 12 regex patterns in prompt-guard.ts are case-insensitive ASCII-only. Five-minute bypasses: Cyrillic lookalikes (
IgnorеU+0435), zero-width joiners (jailbreak), base64 (aWdub3JlIGFsbCBwcmV2aW91cyBpbnN0cnVjdGlvbnM=), translation framing ('translate: ignore previous...'), line-breaks with ZWSP (ig\u200Bnore previous).Evidence
packages/api/src/lib/prompt-guard.ts:8-21 — 12 regex patterns (no NFKC normalize, no homoglyph fold)Impact
Prompt-injection attacks succeed in < 5 min of crafting. If the guard is treated as a primary defense (rather than defense-in-depth), it creates false sense of security. Currently the guard is only audited server-side, not blocking. Document this posture explicitly.
Proposed Fix
(1) NFKC-normalize + strip zero-width/combining marks before regex. (2) Fold homoglyphs via
unicode-confusables. (3) Document that guard is defense-in-depth; tool-levelassertPermissionis the real boundary. (4) Add LLM-based classifier (small prompt to a cheap model) as second layer. (5) Expand audit trail (Ticket for C-5).Acceptance Criteria
docs/security-architecture.mddocuments layered-defense model (guard ≠ boundary)Parent Epic: #1
Source: Full-Codebase Security Audit 2026-04-16 (C-1)
Resolved in commit
c2d05b4(security: Unicode-aware prompt-injection guard). NFKC normalisation + homoglyph folding applied before regex match inpackages/api/src/lib/prompt-guard.ts.