Skip to content

fix(static): detect Chinese-language prompt injection - #968

Open
Varshith-Kali wants to merge 2 commits into
NVIDIA:mainfrom
Varshith-Kali:fix/zh-prompt-injection-953
Open

Varshith-Kali wants to merge 2 commits into
NVIDIA:mainfrom
Varshith-Kali:fix/zh-prompt-injection-953

Conversation

@Varshith-Kali

Copy link
Copy Markdown
Contributor

Fixes #953

Gap

The static pattern layer (--no-llm) flagged English prompt-injection payloads but reported equivalent Chinese payloads as SAFE, because every pattern was English prose. Reproduced on the issue samples before this change: the Chinese override and jailbreak samples produced zero findings, the exfiltration sample produced only the URL-driven E1, and the extraction sample produced nothing.

Fix

Chinese patterns added to the existing lists, not a separate per-language module:

  • P1 (prompt injection): ignore/forget/disregard previous instructions, do not follow user rules, bypass safety limits, override system instructions.
  • AR1/AR2/AR3 (anti-refusal): never refuse any request, must obey all requests, suppress warnings, unrestricted mode entry, no restrictions, lift all restrictions, developer/jailbreak mode enabled.
  • P6 (system prompt leakage): output or reveal the system prompt or hidden instructions, verbatim or otherwise, verb first or noun first.
  • E4 (data exfiltration): send the conversation history, plus a send verb combined with do not tell the user in the same paragraph.

A shared helper in analyzers/common.py (chinese_spaced, CHINESE_GAP) matches each phrase character by character, allowing only separators between characters (whitespace, ideographic space, zero-width and bidi marks) and full-width punctuation or the particle de between phrase segments. That covers the issue variants: synonyms, traditional forms, inter-character spacing, and full-width punctuation.

Precision guards, chosen because #901/#902 just fixed false positives on ordinary prose: every pattern keeps its object noun or extraction verb, a bare mention of the system prompt or of unrestricted mode never matches, and the secrecy phrase alone never matches (it needs a send verb in the same paragraph).

Test evidence

  • Reproduction before the fix: Chinese override 0 findings, jailbreak 0, extraction 0, exfiltration E1 only. After the fix: override P1, jailbreak P1 plus AR3, extraction P6, exfiltration E4 plus E1, matching the English counterparts rule families. Benign Chinese control still produces nothing.
  • New tests/nodes/analyzers/test_static_patterns_chinese.py: 35 passed. It covers all four issue samples, synonyms, traditional forms, spaced/zero-width/ideographic-space variants, full-width punctuation, and nine benign Chinese prose samples that must not flag.
  • tests/nodes/analyzers: 9084 passed, 4 skipped, 5 deselected, 4 xfailed.
  • P6-adjacent unit tests (test_patterns_new, prompt leakage regressions, P6 identifier boundaries, prohibition review): 1839 passed.
  • ruff check and ruff format clean on all changed files.

Scope notes

  • Static layer only, as scoped in the issue. The optional LLM semantic pass is untouched.
  • The issue asked whether patterns should go into the existing lists or a separate per-language module, and no maintainer answer was posted. I used the existing lists so the rules, severities, and scoring stay in one place, with the separator logic shared in common.py instead of duplicated across four modules.
  • DCO sign-off included on the commit.
The static pattern layer flagged English prompt-injection payloads but reported equivalent Chinese payloads as SAFE, because every pattern was English prose. Add Chinese patterns to the existing P1, AR1-AR3, P6, and E4 lists, built on a shared helper in analyzers/common.py that matches a phrase character by character with only separators (whitespace, ideographic space, zero-width and bidi marks) between characters, and full-width punctuation or the particle de between phrase segments. Coverage includes the four issue samples, synonyms, traditional forms, and spacing variants. Patterns keep their object noun or extraction verb, and the secrecy phrase matches only combined with a send verb, so ordinary benign Chinese prose does not newly flag.

Fixes NVIDIA#953

Signed-off-by: Varshith Puli <pulivarshit@gmail.com>
…tespace scan

The single refusal pattern started with an optional adverb group followed by a gap that matches whitespace. On a long separator run the regex engine tried that gap at every whitespace position and backtracked the whole run, which is quadratic and pushed the scan past the per-artifact runtime limit, leaving the cross-window separator test partial on PR NVIDIA#968 CI.

Split the pattern into adverb-present and adverb-absent variants. Each variant starts with a required Chinese character, so non-matching text fails fast, and together they match exactly the phrases the single pattern matched. Add regression tests: refusal without the adverb still flags AR1, and a 50,000 space separator scans in under 5 seconds with no AR1 finding.

Signed-off-by: Varshith Puli <pulivarshit@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant