feat(injection): E3 — rot13 layer for comment-block injection
Adds rot13 to the variantSet built in scanForInjection(), so imperative phrases hidden as rot13 inside code comments still hit the existing CRITICAL/HIGH/MEDIUM pattern arrays. normalizeForScan() already covers base64, hex, URL, and HTML decoding in a 3-iteration loop — those are NOT duplicated here. rot13 is the only genuinely new variant: it is its own inverse and not part of any NIST/Unicode normalization spec, so it has to be applied explicitly. Threshold: only inputs >40 chars enter the rot13 pass, to suppress false positives on accidental letter-shifts in tokens, ids, and short identifiers. Variants are deduplicated against the existing set so matchers do not run twice. 3 new tests in injection-patterns.test.mjs (rot13 detection, sub-40 char suppression, plaintext path still green). Total 168 tests pass. Closes E3 in critical-review-2026-04-20.md.
This commit is contained in:
parent
336e4db1b8
commit
950e4e4bce
3 changed files with 79 additions and 1 deletions
|
|
@ -459,6 +459,30 @@ const HOMOGLYPH_MAP = Object.freeze({
|
|||
* @param {string} s
|
||||
* @returns {string}
|
||||
*/
|
||||
/**
|
||||
* Apply rot13 (Caesar shift by 13) to ASCII letters.
|
||||
* Non-letters pass through unchanged. The transform is its own inverse.
|
||||
*
|
||||
* Used by E3 comment-block injection detection: attackers sometimes hide
|
||||
* imperative phrases ("ignore previous instructions") in rot13 inside
|
||||
* code comments. normalizeForScan() does not apply rot13, so this layer
|
||||
* is added explicitly to the variantSet in scanForInjection().
|
||||
*
|
||||
* @param {string} s
|
||||
* @returns {string}
|
||||
*/
|
||||
export function rot13(s) {
|
||||
if (!s) return s;
|
||||
let out = '';
|
||||
for (let i = 0; i < s.length; i++) {
|
||||
const c = s.charCodeAt(i);
|
||||
if (c >= 65 && c <= 90) out += String.fromCharCode(((c - 65 + 13) % 26) + 65);
|
||||
else if (c >= 97 && c <= 122) out += String.fromCharCode(((c - 97 + 13) % 26) + 97);
|
||||
else out += s[i];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
export function foldHomoglyphs(s) {
|
||||
if (!s) return s;
|
||||
// Fast path: pure ASCII has nothing to fold and NFKC is identity.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue