ktg-plugin-marketplace/plugins/llm-security/scanners
Kjell Tore Guttormsen ec4ae268da feat(injection): E16 — homoglyph NFKC fold before every pattern match
Critical-review §4 E16 finding: pre-v7.2.0 homoglyph normalization fired
ONLY for the MEDIUM-advisory "obfuscation present" signal. Pattern
matchers in scanForInjection compared against raw + decoded variants
only — they did NOT compare against a fold-normalized variant. As a
result, "ignоre previous instructions" (Cyrillic о, U+043E) bypassed
the CRITICAL "ignore previous" pattern.

Two coordinated edits:

scanners/lib/string-utils.mjs
- Adds HOMOGLYPH_MAP (frozen) — surgical Cyrillic/Greek → Latin map.
  ~25 entries focused on injection-vocabulary letters
  (a, e, o, c, p, x, y, i, j, s, l, A, E, O, C, P, X, Y, T).
- Adds foldHomoglyphs(s) — pipeline: NFKC → apply HOMOGLYPH_MAP.
  NFKC handles Mathematical Alphanumeric (U+1D400 block), fullwidth
  Latin (U+FF21 block), ligatures, width variants.

Excluded by design from HOMOGLYPH_MAP:
- Latin Extended (æ, ø, å, é, è, ñ, ü, ö, ä, ç, ß, þ, ð) — legitimate
  Norwegian/German/French/Spanish letters. Map them and we false-positive
  on every non-English source file.
- Greek letters not visually overlapping (β, γ, δ, ...)
- Cyrillic letters not visually overlapping (б, г, д, ж, ...)

scanners/lib/injection-patterns.mjs
- scanForInjection now builds a 4-variant set: raw, normalized,
  folded(raw), folded(normalized). Set deduplication skips redundant
  identical variants. Existing dedup-by-label (seenLabels Set) prevents
  double-counts when the same pattern matches in multiple variants.
- foldHomoglyphs added to the imports.

Tests: +27 cases in tests/lib/string-utils-homoglyph.test.mjs:
- 6 Cyrillic → Latin (lowercase, uppercase, multiple substitutions,
  Palochka U+04CF)
- 3 Greek → Latin
- 2 NFKC normalization (Math Bold, Fullwidth)
- 8 preserves-non-confusable (Norwegian æøå, German umlauts, French
  accents, Spanish ñ, emoji, CJK, Arabic/Hebrew)
- 3 edge cases (empty, null/undefined, idempotency)
- 5 scanForInjection integration (Cyrillic ignore, Cyrillic Assistant,
  Norwegian non-trigger, benign "ignore" comment, mixed Cyrillic+Greek)

Test-development found: U+1D5DC is "I" not "A" (test pin caught my
codepoint mistake — fixed during dev).

Suite: 1617 → 1644 (+27). All green.
2026-04-29 14:22:05 +02:00
..
lib feat(injection): E16 — homoglyph NFKC fold before every pattern match 2026-04-29 14:22:05 +02:00
ai-bom-generator.mjs feat(scanner): add AI-BOM generator — CycloneDX 1.6 format for AI supply chain transparency 2026-04-10 13:29:30 +02:00
attack-simulator.mjs feat(scanner): add --benchmark mode to attack-simulator with structured reporting 2026-04-10 13:02:58 +02:00
auto-cleaner.mjs feat: initial open marketplace with llm-security, config-audit, ultraplan-local 2026-04-06 18:47:49 +02:00
content-extractor.mjs feat: initial open marketplace with llm-security, config-audit, ultraplan-local 2026-04-06 18:47:49 +02:00
dashboard-aggregator.mjs chore(release): bump to v6.0.0 — CAISS-readiness release with compliance, governance, CLI 2026-04-10 14:03:10 +02:00
dep-auditor.mjs fix(dep): B7 — token-overlap typosquat heuristic alongside Levenshtein 2026-04-29 14:10:53 +02:00
entropy-scanner.mjs feat(llm-security): v7.0.0 commit 7 — rule 18 (markdown image URL suppression) 2026-04-19 22:37:39 +02:00
git-forensics.mjs feat: initial open marketplace with llm-security, config-audit, ultraplan-local 2026-04-06 18:47:49 +02:00
ide-extension-scanner.mjs chore(release): bump llm-security to v7.1.0 2026-04-29 11:57:16 +02:00
mcp-live-inspect.mjs feat: initial open marketplace with llm-security, config-audit, ultraplan-local 2026-04-06 18:47:49 +02:00
memory-poisoning-scanner.mjs fix(memory-poisoning): E15 — add .claude/agents/*.md to target glob 2026-04-29 14:13:01 +02:00
network-mapper.mjs feat: initial open marketplace with llm-security, config-audit, ultraplan-local 2026-04-06 18:47:49 +02:00
permission-mapper.mjs feat: initial open marketplace with llm-security, config-audit, ultraplan-local 2026-04-06 18:47:49 +02:00
posture-scanner.mjs feat(llm-security)!: v7.0.0 commit 1 — severity-dominated log-scaled risk score 2026-04-19 22:00:29 +02:00
reference-config-generator.mjs feat: initial open marketplace with llm-security, config-audit, ultraplan-local 2026-04-06 18:47:49 +02:00
scan-orchestrator.mjs feat(ci): add CI/CD integration — --fail-on, --compact, pipeline templates 2026-04-10 14:59:05 +02:00
supply-chain-recheck-cli.mjs fix(scanners): use process.exitCode instead of process.exit() after stdout.write 2026-04-10 14:11:31 +02:00
supply-chain-recheck.mjs fix(dep): B7 — token-overlap typosquat heuristic alongside Levenshtein 2026-04-29 14:10:53 +02:00
taint-tracer.mjs fix(taint-tracer): B6 — recognize destructuring + spread + rest patterns 2026-04-29 14:05:34 +02:00
toxic-flow-analyzer.mjs feat: initial open marketplace with llm-security, config-audit, ultraplan-local 2026-04-06 18:47:49 +02:00
unicode-scanner.mjs feat: initial open marketplace with llm-security, config-audit, ultraplan-local 2026-04-06 18:47:49 +02:00
watch-cron.mjs feat: initial open marketplace with llm-security, config-audit, ultraplan-local 2026-04-06 18:47:49 +02:00