Skip to content

fix(scan): normalize separators before prompt-injection matching - #111

Merged
mrgoonie merged 2 commits into
mainfrom
claude/modest-wozniak-1bea2q
Oct 20, 2026
Merged

mrgoonie merged 2 commits into
mainfrom
claude/modest-wozniak-1bea2q

Conversation

@mrgoonie

Copy link
Copy Markdown
Contributor

Closes #110

Summary

The prompt-injection rules in content-scanner.ts (used by release scanning, GitHub import and skill detail) matched raw text, so separators that readers drop or render as spacing let an injection through. They now run on normalized candidates:

  • U+0085 (NEL), U+FFFD and the Hangul fillers (U+115F, U+1160, U+3164, U+FFA0 — ignorable but drawn as a blank) become a space;
  • every other \p{Default_Ignorable_Code_Point} (soft hyphen, zero-width and bidi controls, CGJ…) is checked both stripped (Ignore) and spaced (ignoreall).

Only the injection rules see the normalized text; findings, other rules and sanitizeContent (stored content) are unchanged.

Verification

  • New tests (soft hyphen, CGJ, ZWSP as separator, NEL, U+FFFD, Hangul fillers mixed with soft hyphen, benign soft hyphen and emoji ZWJ / VS16) fail on the old scanner and pass now; release-scan test proves a valid UTF-8 SKILL.md with a soft hyphen or NEL injection is quarantined.
  • pnpm test: 111 files, 2217 passed / 2 skipped (before the filler follow-up); scanner + release-scan suites 50/50 after it.
  • pnpm typecheck: clean.
  • Isolated subagent review found the filler + soft-hyphen bypass; fixed in 9d71347. \p{…}/u is ES2018 and the repo targets ES2022 / Workers V8; 1.2M-char input scans in ~62 ms.

Docs

docs/code-standards.md and docs/api-reference.md (release scan) describe the normalization.


Generated by Claude Code

Readers drop default-ignorable code points (soft hyphen, zero-width and
bidi controls) and render U+0085 and U+FFFD as breaks, so an injection
split by them slipped past the raw-text regexes. The injection rules now
run on the text with those separators spaced out and with ignorables both
stripped and spaced.

Closes #110

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LzvgR3j15o75z1c1acWjYy
Hangul fillers are default-ignorable yet drawn as a blank, so a filler
between words combined with a soft hyphen inside a word defeated both the
stripped and the spaced candidate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LzvgR3j15o75z1c1acWjYy
@mrgoonie
mrgoonie merged commit 17fca38 into main Oct 20, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(scan): normalize separators before prompt-injection matching

2 participants