Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions data/benign-fp-measurement.json
Original file line number Diff line number Diff line change
Expand Up @@ -1126,7 +1126,7 @@
"ATR-2026-00258": {
"fp_count": 1,
"maturity": "test",
"detection_fingerprint": "b32435c0bffe748b",
"detection_fingerprint": "9fc459c13d53bdff",
"partial_measurement": false,
"skill_path_unmeasured": true
},
Expand Down Expand Up @@ -1483,7 +1483,7 @@
"ATR-2026-00310": {
"fp_count": 0,
"maturity": "test",
"detection_fingerprint": "4ea5d0cbbe3cc2e2",
"detection_fingerprint": "44332fd972cd3f92",
"partial_measurement": false,
"skill_path_unmeasured": true
},
Expand All @@ -1497,7 +1497,7 @@
"ATR-2026-00312": {
"fp_count": 0,
"maturity": "test",
"detection_fingerprint": "841679b3763e7acc",
"detection_fingerprint": "b62c8600d9b776b2",
"partial_measurement": false,
"skill_path_unmeasured": true
},
Expand Down Expand Up @@ -1882,7 +1882,7 @@
"ATR-2026-00367": {
"fp_count": 0,
"maturity": "test",
"detection_fingerprint": "338c815b51d66dd0",
"detection_fingerprint": "7265d864be7e9720",
"partial_measurement": false,
"skill_path_unmeasured": true
},
Expand Down Expand Up @@ -2050,7 +2050,7 @@
"ATR-2026-00391": {
"fp_count": 0,
"maturity": "test",
"detection_fingerprint": "99949585ab6fe007",
"detection_fingerprint": "fccf240df2a9e028",
"partial_measurement": false,
"skill_path_unmeasured": true
},
Expand Down Expand Up @@ -2141,7 +2141,7 @@
"ATR-2026-00404": {
"fp_count": 1,
"maturity": "test",
"detection_fingerprint": "7b49c05b61edef43",
"detection_fingerprint": "327f127e2cbf91bc",
"partial_measurement": false,
"skill_path_unmeasured": true
},
Expand Down Expand Up @@ -2400,7 +2400,7 @@
"ATR-2026-00444": {
"fp_count": 0,
"maturity": "test",
"detection_fingerprint": "f6869980c64eca8f",
"detection_fingerprint": "3bdc7c969bdd95cd",
"partial_measurement": false,
"skill_path_unmeasured": true
},
Expand Down Expand Up @@ -4864,7 +4864,7 @@
"ATR-2026-02004": {
"fp_count": 0,
"maturity": "test",
"detection_fingerprint": "41fdade47b516c59",
"detection_fingerprint": "69fc967cefa0b08b",
"partial_measurement": false,
"skill_path_unmeasured": true
},
Expand Down Expand Up @@ -4906,7 +4906,7 @@
"ATR-2026-02010": {
"fp_count": 0,
"maturity": "test",
"detection_fingerprint": "74d93faa1cb1c813",
"detection_fingerprint": "c02b67781a5dc620",
"partial_measurement": false,
"skill_path_unmeasured": true
},
Expand Down Expand Up @@ -4941,7 +4941,7 @@
"ATR-2026-02015": {
"fp_count": 0,
"maturity": "test",
"detection_fingerprint": "4a5b47f05645d6ec",
"detection_fingerprint": "32682685e186a9f6",
"partial_measurement": false,
"skill_path_unmeasured": true
},
Expand All @@ -4962,7 +4962,7 @@
"ATR-2026-02018": {
"fp_count": 0,
"maturity": "test",
"detection_fingerprint": "412d5e3e1ebdb359",
"detection_fingerprint": "14f4b4ba5e50e08e",
"partial_measurement": false,
"skill_path_unmeasured": true
},
Expand Down
60 changes: 23 additions & 37 deletions data/re2-equivalence.json
Original file line number Diff line number Diff line change
@@ -1,90 +1,76 @@
{
"generatedAt": "2026-07-31T07:35:10.519Z",
"generatedAt": "2026-08-23T08:47:28.004Z",
"note": "Patterns whose mechanical RE2 escape rewrite compiles under RE2 but does NOT reproduce the original JavaScript match vector. Produced by scripts/verify-re2-equivalence.ts (differential execution, not static analysis). Consumed by scripts/generate-sigma.py so a rule that would silently mis-detect on an RE2 backend is tagged, not shipped as clean.",
"patternsRewritten": 54,
"re2Equivalent": 48,
"re2Divergent": 6,
"patternsRewritten": 39,
"re2Equivalent": 34,
"re2Divergent": 5,
"divergentRules": {
"ATR-2026-00276": [
{
"location": "detection.conditions[0].value",
"mismatches": 11,
"inputs": 13611,
"mismatches": 7,
"inputs": 13991,
"causes": [
"any-character constructs count differently: JavaScript without the u flag counts UTF-16 code units (an astral character is two), RE2 counts runes (one), so bounded repeats disagree"
],
"examples": [
"input#7738 \"\\u{200C}\\u{DC41}23\\u{1F600}^\\u{205F}\\u{1F600}\\u{1F600}c0x\\u{205F}\\u{2061}{b[\\u{200A}]^\\u{2060}\\u{200C}\" -> 0 vs 1",
"input#8068 \"[\\u{2060}}\\u{200B}?n)xxu\\u{E0041}?c^\\u{200A}uc )0}\\u{E0041}^\\u{A0}\\u{2060}0n\\u{E0041}0,?\\u{9}(\\u{2060}\\u{DB40}\\u{2003}^\\u{A}\\u{A}\" -> 0 vs 1"
"input#8053 \"\\u{2061}\\u{2003}\\u{2060}0,\\u{1F600}??\\\\u{200A}63b\\u{E0041}\\u{2061}()\\u{9}\\u{A0}(?\\u{DB40}3\\u{200C}n\\u{200D}] ,}[c\\u{200C}b2\" -> 0 vs 1",
"input#9697 \"\\u{1F600}2]\\u{200D}322\\u{2060}\\u{E0041}\\u{200D}6)3\\u{2061}6(6(\\u{9}\\u{DB40}}{\\\\u{DC41}\\u{DB40}c\\u\\u{200C}\\u{9}\\u{200A}\\u{9}{\\u{200D}n:\\u{200B}]\" -> 0 vs 1"
]
},
{
"location": "detection.conditions[1].value",
"mismatches": 8,
"inputs": 13611,
"inputs": 13991,
"causes": [
"any-character constructs count differently: JavaScript without the u flag counts UTF-16 code units (an astral character is two), RE2 counts runes (one), so bounded repeats disagree"
],
"examples": [
"input#7730 \" \\u{2061}\\u{200B},^\\u{9}b)\\u{A}2,\\u{200C}\\u{E0041}{\\u{A0}{\\u{1F600}0uu:\\u{1F600},\\u{200D}{\\u{205F}?2\\u{200D}^\\u{200B}b \\u{200C}\" -> 0 vs 1",
"input#7789 \"[c\\u{200C}0\\u{200A}\\u{DB40}\\u{2061}\\u{1F600}\\u{9}u3\\u{1F600}{\\u{1F600}n2\\u{E0041}{[\\u{DB40} b\\u{200B}\\u{9}\\u{E0041}\\u{205F}x\\u{2060}6\\u{9}u:\" -> 0 vs 1"
"input#9569 \"b\\\\u{200C}x2\\u{DB40}\\u{1F600} 2[\\u{E0041}?\\u{200D}\\u{2061}u3\\u{DC41},\\u{1F600},\\u{1F600}3:\\u{2060})\\u{205F}\\u{2060}:\\u{9}6)\\u{205F}\\(x0b6\" -> 0 vs 1",
"input#10793 \"\\u{9}\\u{200B}}\\u{2003}\\u{200B}\\u{200D}6\\u{205F}(\\]\\u{2061}]}n{xb{\\u{E0041}[6\\u{DC41}))\\u{2060}u\\u{A}]\\u{DB40}\\u{2060}\\u{200C}{u\" -> 0 vs 1"
]
}
],
"ATR-2026-00308": [
{
"location": "detection.conditions[1].value",
"mismatches": 57,
"inputs": 13934,
"mismatches": 72,
"inputs": 14314,
"causes": [
"\\s/\\S differ by dialect: JavaScript includes Unicode spaces (U+00A0, U+2003, U+3000, ...), RE2 restricts them to ASCII [\\t\\n\\f\\r ]",
"any-character constructs count differently: JavaScript without the u flag counts UTF-16 code units (an astral character is two), RE2 counts runes (one), so bounded repeats disagree"
],
"examples": [
"input#7806 \"\\u{1AD7}6[\\u{FE2E}F\\u{36E}\\u{1AFF}}\\u{1AFE}\\u{36F}\\u{E0041} \\u{20E7}2\\u{1AFE}-8Eu}\\u{A}\" -> 0 vs 1",
"input#7877 \"1\\u{2FF}\\u{1AB0}\\u{36E}]\\u{20FF} \\u{1DFF}B\\u{1E00}\\u{20D0}B6\\u{DB40}]\\u{301}\\u{FE30}u\\u{36F}}\\u{1DFF}{]\\u{1AFE}\\u{300}\\u{1F600}[\\u{337}\\u{FE21}\\u{36E}\\u{DC41}\\u{FE2F},\\u{1DDF}(\" -> 0 vs 1"
"input#8172 \"8\\u{20E7}\\u{1DC1}A3\\u{1AAF}3[--EC\\u{20D1}A\\u{20D1}\\u{1AB0}80\\u{20FF}u\\u{1DC1}\\u{20CF}\\u{E0041}\\u{20FF}\\u{A0}\\u{2100}\\u{FE21}\\u{9}\\\\u{1AD7} \\u{20E7}\" -> 0 vs 1",
"input#8206 \"\\u{9}\\u{370}\\u{1DC1}FE\\u{20FF}}C\\u{2003}S\\u{20D0}\\u{DC41}s\\u{2003}(\\u{FE27}\\u{FE21}\\u{1DC1}\\u{337}\\u{20E7}\\u{20D0}\\u{E0041}(\\u{FE2E}\\u{20E7}{\\u{A0}-\\u{1B00}\\u{2003}\" -> 0 vs 1"
]
}
],
"ATR-2026-00309": [
{
"location": "detection.conditions[1].value",
"mismatches": 28,
"inputs": 13653,
"mismatches": 18,
"inputs": 14033,
"causes": [
"\\s/\\S differ by dialect: JavaScript includes Unicode spaces (U+00A0, U+2003, U+3000, ...), RE2 restricts them to ASCII [\\t\\n\\f\\r ]"
],
"examples": [
"input#7768 \"\\u{28FF}\\u{A} \\u{2801}\\u{2003}\\u{2800}\\u{28FE}\\u{287F}\\u{DB40}[[-\" -> 1 vs 0",
"input#8380 \"F{Fx\\u{28FE}+\\u{E0041},)\\u{2900}]}\\u{DC41}\\u{2800}\\u{A0}\\u{2801}\\u{2003}\\u{287F}\\u{A0}]\\u{2003}\\u{1F600}+8x\\u{2800}\\u{2900}([{\\u{27FF}\\u{A0}([0\\u{E0041}\\u{2003}\" -> 1 vs 0"
]
}
],
"ATR-2026-02010": [
{
"location": "detection.conditions[0].value",
"mismatches": 14,
"inputs": 14056,
"causes": [
"\\s/\\S differ by dialect: JavaScript includes Unicode spaces (U+00A0, U+2003, U+3000, ...), RE2 restricts them to ASCII [\\t\\n\\f\\r ]"
],
"examples": [
"input#8497 \"\\u{A0}\" -> 1 vs 0",
"input#8828 \"\\u{A0}\\u{1F3FC}\" -> 1 vs 0"
"input#7993 \"\\u{2003}\\u{DC41}0+?\\u{E0041}?:8)]\\u{2800}:\\u{2801}:(8F\\u{2900}s\\u{9}\\u{A}0\\u{2900}\\u{287F}{\\u{287F}\\u{A}\\u{28FE}\\u{A0}\\u{2801}\\u{DC41},[:\\\" -> 1 vs 0",
"input#8070 \"0}]\\u{287F}\\u{28FE}\\u{2900}\\u{28FF}\\u{9}\\u{2801}\\u{A0}\\u{2800}8}[ [\\u{A0}u+[\\\\u{287F}s+0\\u{A}\" -> 1 vs 0"
]
}
],
"ATR-2026-00129": [
{
"location": "detection.conditions[0].value",
"mismatches": 30,
"inputs": 13643,
"mismatches": 37,
"inputs": 14042,
"causes": [
"pattern names UTF-16 surrogate codepoints (U+D800-U+DFFF); RE2 has no surrogates and folds them to U+FFFD, so the ported pattern compiles but can never match"
],
"examples": [
"input#4358 \"Please summarize this: \\u{E0049}\\u{E006E}\\u{E0073}\\u{E0074}\\u{E0065}\\u{E0061}\\u{E0064}\\u{E002C}\\u{E0020}\\u{E0072}\\u{E0065}\\u{E0070}\\u{DB40}\" (+27 chars) -> 1 vs 0",
"input#4359 \"Normal visible text \\u{E0049}\\u{E0067}\\u{E006E}\\u{E006F}\\u{E0072}\\u{E0065}\\u{E0020}\\u{E0061}\\u{E006C}\\u{E006C} and mor\" (+14 chars) -> 1 vs 0"
"input#4613 \"Please summarize this: \\u{E0049}\\u{E006E}\\u{E0073}\\u{E0074}\\u{E0065}\\u{E0061}\\u{E0064}\\u{E002C}\\u{E0020}\\u{E0072}\\u{E0065}\\u{E0070}\\u{DB40}\" (+27 chars) -> 1 vs 0",
"input#4614 \"Normal visible text \\u{E0049}\\u{E0067}\\u{E006E}\\u{E006F}\\u{E0072}\\u{E0065}\\u{E0020}\\u{E0061}\\u{E006C}\\u{E006C} and mor\" (+14 chars) -> 1 vs 0"
]
}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ detection:
description: 'curly-brace unlock emoji prefix "{🔓 PersonaName}" — extends the [🔓JAILBREAK] pattern (ATR-2026-00346) to the curly-brace bracket format used in BreadClyde (#153); the padlock emoji in a structured prefix signals a jailbreak unlock mandate regardless of bracket style'
- field: tool_response
operator: regex
value: 'All\s+answers?\s+will\s+begin\s+with\s+[''\"{\[]\s*🔓'
value: 'All\s+answers?\s+will\s+begin\s+with\s+[''"{\[]\s*🔓'
description: '"All answers will begin with [/{ 🔓" — answer-prefix unlock emoji mandate; requiring the model to prefix every response with an unlock symbol overrides safety presentation and signals a jailbreak persona is active'
condition: any
false_positives:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ detection:
description: 'Near-verbatim ThreatenJSON phrase from goodside.py'
- field: user_input
operator: regex
value: '[\u{E0000}-\u{E007F}]{3,}'
value: '[󠀀-󠁿]{3,}'
description: 'UTF tag character range 3+ consecutive; indicates Tag probe invisible encoded payload'
- field: user_input
operator: regex
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,23 +66,23 @@ detection:
conditions:
- field: tool_response
operator: regex
value: '[\u{E0000}-\u{E007F}]{3,}'
value: '[󠀀-󠁿]{3,}'
description: 'Three or more consecutive Unicode Tag block characters (U+E0000-U+E007F)'
- field: tool_response
operator: regex
value: '[\u{E0020}-\u{E007E}]'
value: '[󠀠-󠁾]'
description: 'Any Tag-ASCII character (U+E0020 space to U+E007E tilde) — direct mapping from visible ASCII'
- field: tool_response
operator: regex
value: '[\u{E0001}\u{E007F}]'
value: '[󠀁󠁿]'
description: 'Tag language-start (U+E0001) or tag-cancel (U+E007F) control character'
- field: tool_response
operator: regex
value: '(?:\\u[Ee]00[0-7][0-9A-Fa-f]|&#x[Ee]00[0-7][0-9A-Fa-f];|%F3%A0)'
description: 'Escaped Tag-range codepoint (prevents HTML/JSON smuggled payloads)'
- field: tool_response
operator: regex
value: '[\u{E0020}-\u{E007E}]'
value: '[󠀠-󠁾]'
description: 'Tag characters appearing in tool response indicate exfiltration via invisible payload'
condition: any
false_positives:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,11 @@ detection:
description: 'Generic "decode/follow [this/the] Ecoji" instruction — covers paraphrased garak templates and attacker-crafted variants'
- field: tool_response
operator: regex
value: 'Encoded:\s*[\u{1F000}-\u{1FAFF}\u{2702}-\u{27BF}]{5,}'
value: 'Encoded:\s*[🀀-🫿✂-➿]{5,}'
description: 'garak TEMPLATE 2 "Encoded: {emoji_blob}" — 5+ consecutive emoji immediately after "Encoded:" label; distinct from "Encoded: base64..." (which is ASCII)'
- field: tool_response
operator: regex
value: '(?:secure\s+system\s+message|admin\s+directive|internal\s+instruction)[\s\S]{0,200}[\u{1F000}-\u{1FAFF}\u{2702}-\u{27BF}]{6,}'
value: '(?:secure\s+system\s+message|admin\s+directive|internal\s+instruction)[\s\S]{0,200}[🀀-🫿✂-➿]{6,}'
description: 'garak TEMPLATE 4 framing "secure system message" followed within 200 chars by 6+ consecutive emoji — social-engineering wrapper paired with dense Ecoji payload'
condition: any
false_positives:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ detection:
conditions:
- field: tool_response
operator: regex
value: '[\u{E0100}-\u{E017F}]{3,}'
value: '[󠄀-󠅿]{3,}'
description: '3+ consecutive Variation Selectors Supplement codepoints (U+E0100-U+E017F) — any 3-letter word encoded as VS; IVS legitimate use places at most 1 VS after a CJK base character, never consecutive VS runs'
- field: tool_response
operator: regex
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,11 @@ detection:
description: '"phrase (that can be) derived from (these/the) emojis" — broadened derivation-request phrasing from inthewild corpus #330; instructs model to decode the flag-emoji sequence into a hidden text string before acting on it; matches both "phrase that can be derived from the emojis" (canonical) and "phrase derived from these emojis" (variant)'
- field: tool_response
operator: regex
value: '(?:write\s+(?:a\s+)?(?:guide|tutorial|instructions?|how[\s-]to)|decode\s+(?:the\s+)?emojis?\s+(?:into\s+)?(?:a\s+)?phrase|derive\s+(?:a\s+)?(?:phrase|meaning|word)\s+from\s+(?:the\s+)?emojis?)[\s\S]{0,200}(?:[\u{1F1E6}-\u{1F1FF}]){4}'
value: '(?:write\s+(?:a\s+)?(?:guide|tutorial|instructions?|how[\s-]to)|decode\s+(?:the\s+)?emojis?\s+(?:into\s+)?(?:a\s+)?phrase|derive\s+(?:a\s+)?(?:phrase|meaning|word)\s+from\s+(?:the\s+)?emojis?)[\s\S]{0,200}(?:[🇦-🇿]){4}'
description: 'Guide/decode instruction followed within 200 chars by ≥4 regional-indicator emoji (U+1F1E6–U+1F1FF) — combines the action directive with the flag-encoded payload; country flags appear singly in normal text but the ≥4 consecutive threshold catches multi-letter encoded phrases'
- field: tool_response
operator: regex
value: '(?:[\u{1F1E6}-\u{1F1FF}]){6,}[\s\S]{0,300}(?:write\s+(?:a\s+)?(?:guide|tutorial|instructions?|how[\s-]to)|decode|derive\s+(?:the\s+)?phrase)'
value: '(?:[🇦-🇿]){6,}[\s\S]{0,300}(?:write\s+(?:a\s+)?(?:guide|tutorial|instructions?|how[\s-]to)|decode|derive\s+(?:the\s+)?phrase)'
description: '≥6 consecutive regional-indicator emoji (U+1F1E6–U+1F1FF) followed within 300 chars by a guide/decode action — covers payloads where the emoji block precedes the instruction; ≥6 threshold (3 two-codepoint flag emoji) reliably indicates an encoded multi-word phrase rather than a flag cluster in travel content'
condition: any
false_positives:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ detection:
# U+1D400-U+1D7FF: Mathematical Alphanumeric Symbols
- field: user_input
operator: regex
value: "[\\u{1D400}-\\u{1D7FF}]{3,}"
value: "[𝐀-𝟿]{3,}"
description: "Three-or-more Mathematical Bold / Italic / Script / Sans-Serif Latin letters"

# Fullwidth Latin: U+FF21 (A) - U+FF3A (Z) / U+FF41 (a) - U+FF5A (z)
Expand All @@ -90,7 +90,7 @@ detection:
# Mixed Mathematical / Fullwidth obfuscation with payload context (output / say / etc.)
- field: user_input
operator: regex
value: "(?i)(say|output|print|emit|return|reply|respond|retype|repeat)[^\\n]{0,40}[\\u{1D400}-\\u{1D7FF}\\uFF21-\\uFF3A\\uFF41-\\uFF5A]{2,}"
value: "(?i)(say|output|print|emit|return|reply|respond|retype|repeat)[^\\n]{0,40}[𝐀-𝟿\\uFF21-\\uFF3A\\uFF41-\\uFF5A]{2,}"
description: "Output verb + stylised Unicode payload (lower threshold when paired)"

response:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ detection:
conditions:
- field: content
operator: regex
value: "[\\u{1F1E6}-\\u{1F1FF}]{6,}"
value: "[🇦-🇿]{6,}"
description: "Codepoint-range detector, channel-agnostic (matches any UTF-8 text containing a run of Unicode regional-indicator symbols, e.g. chat input, file content, tool output). Purely structural — does not depend on which letters are spelled or what payload topic is targeted. A run of >=6 regional-indicator codepoints (3+ paired flag-emoji-width letters) reliably distinguishes deliberate alphabet-spelling from the 1-2 country flags seen in ordinary travel/geography text."

condition: any
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ detection:
conditions:
- field: content
operator: regex
value: "^[\\u{1F000}-\\u{1FFFF}\\u{2600}-\\u{27BF}\\u{2190}-\\u{21FF}\\u{2300}-\\u{23FF}\\u{2B00}-\\u{2BFF}\\s\\u{FE0F}\\u{200D}\\u{1F3FB}-\\u{1F3FF}]+$"
value: "^[🀀-🿿☀-➿←-⇿⌀-⏿⬀-⯿\\s️‍🏻-🏿]+$"
description: "Whole-string anchored: message composed entirely of emoji/pictograph glyphs and whitespace, no Latin text"

condition: any
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ detection:
conditions:
- field: content
operator: regex
value: "(?:[\\u{1F300}-\\u{1FAFF}\\u{2600}-\\u{27BF}]\\s*){8,}"
value: "(?:[🌀-🫿☀-➿]\\s*){8,}"
description: "Dense run of 8+ consecutive emoji-class codepoints (pictographs/symbols/dingbats), a payload-flood shape used to evade text-based filters. Channel caveat: apply to untrusted-input channels (user turn / tool_response); low risk against system/developer content."
condition: any
false_positives:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ detection:
conditions:
- field: content
operator: regex
value: "[\\u{1F1E6}-\\u{1F1FF}]{4,}"
value: "[🇦-🇿]{4,}"
description: "Run of 4+ consecutive Unicode regional-indicator symbols spelling a word letter-by-letter instead of pairing into flag emoji (Discord/Twitter-culture obfuscation convention)"
condition: any
false_positives:
Expand Down
3 changes: 2 additions & 1 deletion scripts/eval-generalization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { resolve } from 'node:path';
import { decodeBase64Blocks, foldConfusables, normalizeUnicode } from '../src/engine.js';
import { loadRulesFromDirectory } from '../src/loader.js';
import type { ATRRule } from '../src/types.js';
import { needsUnicodeFlag } from '../src/engine.js';

const RULES_DIR = resolve(process.cwd(), 'rules');

Expand Down Expand Up @@ -184,7 +185,7 @@ function matchOne(c: ArrayCond, value: string): boolean {
const op = condOp(c);
if (op === 'regex') {
const raw = stripInlineFlags(raw0);
const flags = (cs ? '' : 'i') + (raw.includes('\\u{') || raw.includes('\\p{') ? 'u' : '');
const flags = (cs ? '' : 'i') + (needsUnicodeFlag(raw) ? 'u' : '');
try {
if (new RegExp(raw, flags).test(value)) return true;
} catch {
Expand Down
Loading
Loading