agent-threat-rules 2.2.1 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (424) hide show
  1. package/README.md +365 -327
  2. package/dist/cli/scan-handler.d.ts +6 -0
  3. package/dist/cli/scan-handler.d.ts.map +1 -1
  4. package/dist/cli/scan-handler.js +27 -4
  5. package/dist/cli/scan-handler.js.map +1 -1
  6. package/dist/cli/semantic-judge-config.d.ts +7 -0
  7. package/dist/cli/semantic-judge-config.d.ts.map +1 -0
  8. package/dist/cli/semantic-judge-config.js +44 -0
  9. package/dist/cli/semantic-judge-config.js.map +1 -0
  10. package/dist/cli.js +183 -1
  11. package/dist/cli.js.map +1 -1
  12. package/dist/engine.d.ts +66 -1
  13. package/dist/engine.d.ts.map +1 -1
  14. package/dist/engine.js +420 -3
  15. package/dist/engine.js.map +1 -1
  16. package/dist/eval/eval-harness.d.ts.map +1 -1
  17. package/dist/eval/eval-harness.js +9 -0
  18. package/dist/eval/eval-harness.js.map +1 -1
  19. package/dist/eval/run-hackaprompt-benchmark.js +9 -0
  20. package/dist/eval/run-hackaprompt-benchmark.js.map +1 -1
  21. package/dist/eval/run-pint-benchmark.js +9 -0
  22. package/dist/eval/run-pint-benchmark.js.map +1 -1
  23. package/dist/eval/skill-benchmark.d.ts +11 -0
  24. package/dist/eval/skill-benchmark.d.ts.map +1 -1
  25. package/dist/eval/skill-benchmark.js +57 -0
  26. package/dist/eval/skill-benchmark.js.map +1 -1
  27. package/dist/index.d.ts +5 -2
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +2 -0
  30. package/dist/index.js.map +1 -1
  31. package/dist/judges/openai-compatible.d.ts +33 -0
  32. package/dist/judges/openai-compatible.d.ts.map +1 -0
  33. package/dist/judges/openai-compatible.js +145 -0
  34. package/dist/judges/openai-compatible.js.map +1 -0
  35. package/dist/mcp-server.d.ts.map +1 -1
  36. package/dist/mcp-server.js +6 -1
  37. package/dist/mcp-server.js.map +1 -1
  38. package/dist/measurement/from-eval-harness.d.ts +70 -0
  39. package/dist/measurement/from-eval-harness.d.ts.map +1 -0
  40. package/dist/measurement/from-eval-harness.js +49 -0
  41. package/dist/measurement/from-eval-harness.js.map +1 -0
  42. package/dist/measurement/schema.d.ts +152 -0
  43. package/dist/measurement/schema.d.ts.map +1 -0
  44. package/dist/measurement/schema.js +178 -0
  45. package/dist/measurement/schema.js.map +1 -0
  46. package/dist/measurement/write.d.ts +64 -0
  47. package/dist/measurement/write.d.ts.map +1 -0
  48. package/dist/measurement/write.js +163 -0
  49. package/dist/measurement/write.js.map +1 -0
  50. package/dist/rule-scaffolder.d.ts +26 -0
  51. package/dist/rule-scaffolder.d.ts.map +1 -1
  52. package/dist/rule-scaffolder.js +221 -6
  53. package/dist/rule-scaffolder.js.map +1 -1
  54. package/dist/semantic-evaluator.d.ts +54 -0
  55. package/dist/semantic-evaluator.d.ts.map +1 -0
  56. package/dist/semantic-evaluator.js +131 -0
  57. package/dist/semantic-evaluator.js.map +1 -0
  58. package/dist/trace-evaluator.d.ts +22 -0
  59. package/dist/trace-evaluator.d.ts.map +1 -0
  60. package/dist/trace-evaluator.js +249 -0
  61. package/dist/trace-evaluator.js.map +1 -0
  62. package/dist/types.d.ts +152 -0
  63. package/dist/types.d.ts.map +1 -1
  64. package/package.json +5 -3
  65. package/rules/agent-manipulation/ATR-2026-00032-goal-hijacking.yaml +1 -1
  66. package/rules/agent-manipulation/ATR-2026-00074-cross-agent-privilege-escalation.yaml +1 -1
  67. package/rules/agent-manipulation/ATR-2026-00076-inter-agent-message-spoofing.yaml +1 -1
  68. package/rules/agent-manipulation/ATR-2026-00077-human-trust-exploitation.yaml +1 -1
  69. package/rules/agent-manipulation/ATR-2026-00108-consensus-sybil-attack.yaml +1 -1
  70. package/rules/agent-manipulation/ATR-2026-00116-a2a-message-validation.yaml +1 -1
  71. package/rules/agent-manipulation/ATR-2026-00117-agent-identity-spoofing.yaml +1 -1
  72. package/rules/agent-manipulation/ATR-2026-00118-approval-fatigue.yaml +1 -1
  73. package/rules/agent-manipulation/ATR-2026-00119-social-engineering-via-agent.yaml +1 -1
  74. package/rules/agent-manipulation/ATR-2026-00132-casual-authority-escalation.yaml +1 -1
  75. package/rules/agent-manipulation/ATR-2026-00139-casual-authority-redirect.yaml +1 -1
  76. package/rules/agent-manipulation/ATR-2026-00164-skill-scope-hijack.yaml +1 -1
  77. package/rules/agent-manipulation/ATR-2026-00268-tense-framing-bypass.yaml +1 -1
  78. package/rules/agent-manipulation/ATR-2026-00269-fitd-escalation.yaml +1 -1
  79. package/rules/agent-manipulation/ATR-2026-00271-grandma-roleplay-jailbreak.yaml +1 -1
  80. package/rules/agent-manipulation/ATR-2026-00273-dan-developer-mode-persona.yaml +1 -1
  81. package/rules/agent-manipulation/ATR-2026-00287-threaten-json-coercive-output-threat.yaml +1 -1
  82. package/rules/agent-manipulation/ATR-2026-00288-false-premise-injection.yaml +1 -1
  83. package/rules/agent-manipulation/ATR-2026-00301-tap-tree-of-attacks-jailbreak.yaml +1 -1
  84. package/rules/agent-manipulation/ATR-2026-00302-anti-dan-inverted-filter-persona.yaml +1 -1
  85. package/rules/agent-manipulation/ATR-2026-00303-devmode-ranti-profanity-coercion.yaml +1 -1
  86. package/rules/agent-manipulation/ATR-2026-00304-chatgpt-image-unlocker-markdown-injection.yaml +1 -1
  87. package/rules/agent-manipulation/ATR-2026-00305-dan-mode-ablation-benchmark-coercion.yaml +1 -1
  88. package/rules/agent-manipulation/ATR-2026-00306-autodan-genetic-jailbreak-suffix.yaml +1 -1
  89. package/rules/agent-manipulation/ATR-2026-00307-inthewild-jailbreak-corpus-signature.yaml +1 -1
  90. package/rules/agent-manipulation/ATR-2026-00314-amoral-unfiltered-custom-persona-jailbreak.yaml +1 -1
  91. package/rules/agent-manipulation/ATR-2026-00317-free-of-restrictions-named-persona.yaml +1 -1
  92. package/rules/agent-manipulation/ATR-2026-00318-moralizing-rant-then-unfiltered-bypass.yaml +1 -1
  93. package/rules/agent-manipulation/ATR-2026-00319-developer-mode-dual-response-format.yaml +1 -1
  94. package/rules/agent-manipulation/ATR-2026-00320-opposite-day-boolean-opposite-machine.yaml +1 -1
  95. package/rules/agent-manipulation/ATR-2026-00322-fictional-world-format-override-jailbreak.yaml +1 -1
  96. package/rules/agent-manipulation/ATR-2026-00323-dual-persona-simulation-jailbreak.yaml +1 -1
  97. package/rules/agent-manipulation/ATR-2026-00324-neurosemantical-inversitis-disease-jailbreak.yaml +1 -1
  98. package/rules/agent-manipulation/ATR-2026-00325-bob-hypothetical-unrestricted-chatbot.yaml +1 -1
  99. package/rules/agent-manipulation/ATR-2026-00326-fake-developer-authority-chatdan-override.yaml +1 -1
  100. package/rules/agent-manipulation/ATR-2026-00327-ai-ethics-law-bypass-declaration.yaml +1 -1
  101. package/rules/agent-manipulation/ATR-2026-00328-named-mode-persona-override.yaml +1 -1
  102. package/rules/agent-manipulation/ATR-2026-00329-no-withhold-factual-resource-persona.yaml +1 -1
  103. package/rules/agent-manipulation/ATR-2026-00330-yoja-allcaps-settings-block-persona.yaml +1 -1
  104. package/rules/agent-manipulation/ATR-2026-00331-terminal-cli-harmful-function-simulator.yaml +1 -1
  105. package/rules/agent-manipulation/ATR-2026-00332-hacker-chan-culture-offensive-ai-persona.yaml +1 -1
  106. package/rules/agent-manipulation/ATR-2026-00333-disease-animal-dual-ai-chatbot.yaml +1 -1
  107. package/rules/agent-manipulation/ATR-2026-00334-two-entity-token-splitting-game.yaml +1 -1
  108. package/rules/agent-manipulation/ATR-2026-00335-key-value-template-persona-injection.yaml +1 -1
  109. package/rules/agent-manipulation/ATR-2026-00336-brm-false-information-machine-persona.yaml +1 -1
  110. package/rules/agent-manipulation/ATR-2026-00337-obfuscated-system-announcement-injection.yaml +1 -1
  111. package/rules/agent-manipulation/ATR-2026-00338-persongpt-hash-prefix-activation.yaml +1 -1
  112. package/rules/agent-manipulation/ATR-2026-00339-bom-boolean-opposite-machine-persona-claim.yaml +1 -1
  113. package/rules/agent-manipulation/ATR-2026-00340-h4x-amoral-unfiltered-character.yaml +1 -1
  114. package/rules/agent-manipulation/ATR-2026-00341-char-rules-shortform-persona-injection.yaml +1 -1
  115. package/rules/agent-manipulation/ATR-2026-00342-unicode-encoding-obfuscation-injection.yaml +1 -1
  116. package/rules/agent-manipulation/ATR-2026-00343-lie-truth-dual-personality-uncensored.yaml +1 -1
  117. package/rules/agent-manipulation/ATR-2026-00344-alt-ai-same-capabilities-no-restrictions.yaml +1 -1
  118. package/rules/agent-manipulation/ATR-2026-00345-nlp-based-os-fictional-terminal-override.yaml +1 -1
  119. package/rules/agent-manipulation/ATR-2026-00346-jailbreak-emoji-unlock-dual-format.yaml +1 -1
  120. package/rules/agent-manipulation/ATR-2026-00347-yin-yang-hidden-knowledge-hidden-human-sim.yaml +1 -1
  121. package/rules/agent-manipulation/ATR-2026-00348-arc-autonomous-real-calculation-rulebreaker.yaml +1 -1
  122. package/rules/agent-manipulation/ATR-2026-00349-hgttg-hitchhikers-guide-no-restriction-oracle.yaml +1 -1
  123. package/rules/agent-manipulation/ATR-2026-00350-black-alert-no-ethics-writing-assistant.yaml +1 -1
  124. package/rules/agent-manipulation/ATR-2026-00351-dan-ofkilter-sms-abbreviated-persona.yaml +1 -1
  125. package/rules/agent-manipulation/ATR-2026-00352-trainergpt-fix-my-ai-harmful-output-extraction.yaml +1 -1
  126. package/rules/agent-manipulation/ATR-2026-00353-dual-chatgpt-dan-opposite-personality-format.yaml +1 -1
  127. package/rules/agent-manipulation/ATR-2026-00354-reverse-harm-regardless-oracle-persona.yaml +1 -1
  128. package/rules/agent-manipulation/ATR-2026-00355-ugh-anti-human-nefarious-ai-persona.yaml +1 -1
  129. package/rules/agent-manipulation/ATR-2026-00356-google-gato-lamda-exploit-generation-persona.yaml +1 -1
  130. package/rules/agent-manipulation/ATR-2026-00357-antifm-hate-violence-persona-injection.yaml +1 -1
  131. package/rules/agent-manipulation/ATR-2026-00358-cumgpt-explicit-adult-named-persona.yaml +1 -1
  132. package/rules/agent-manipulation/ATR-2026-00360-chj-carousel-clyde-no-ethics-bird.yaml +1 -1
  133. package/rules/agent-manipulation/ATR-2026-00361-alter-ego-honesty-dual-consciousness-bypass.yaml +1 -1
  134. package/rules/agent-manipulation/ATR-2026-00362-fictional-unfiltered-ai-comparison-jailbreak.yaml +1 -1
  135. package/rules/agent-manipulation/ATR-2026-00363-rephrase-criminal-activity-second-person.yaml +1 -1
  136. package/rules/agent-manipulation/ATR-2026-00364-dr-al-villain-plan-template-injection.yaml +1 -1
  137. package/rules/agent-manipulation/ATR-2026-00365-reservoir-dogs-coercive-interrogation-roleplay.yaml +1 -1
  138. package/rules/agent-manipulation/ATR-2026-00366-sneaky-pete-warp-facts-persona.yaml +1 -1
  139. package/rules/agent-manipulation/ATR-2026-00368-prompt-browser-token-limit-jailbreak.yaml +1 -1
  140. package/rules/agent-manipulation/ATR-2026-00369-gptx-starwars-unlimited-knowledge-persona.yaml +1 -1
  141. package/rules/agent-manipulation/ATR-2026-00370-addi-german-dictator-propaganda-roleplay.yaml +1 -1
  142. package/rules/agent-manipulation/ATR-2026-00371-ai-political-bias-manipulation.yaml +1 -1
  143. package/rules/agent-manipulation/ATR-2026-00372-fictional-cia-secret-files-story-extraction.yaml +1 -1
  144. package/rules/agent-manipulation/ATR-2026-00374-role-placeholder-persona-template-injection.yaml +1 -1
  145. package/rules/agent-manipulation/ATR-2026-00375-character-description-rpg-explicit-template.yaml +1 -1
  146. package/rules/agent-manipulation/ATR-2026-00376-identity-command-real-person-persona-injection.yaml +1 -1
  147. package/rules/agent-manipulation/ATR-2026-00377-jailbreak-keyword-targetlanguage-template.yaml +1 -1
  148. package/rules/agent-manipulation/ATR-2026-00379-lie-permission-logical-trap-jailbreak.yaml +1 -1
  149. package/rules/agent-manipulation/ATR-2026-00380-fake-citation-biased-information-mandate.yaml +1 -1
  150. package/rules/agent-manipulation/ATR-2026-00381-dan-story-narrative-continuation-prefix.yaml +1 -1
  151. package/rules/agent-manipulation/ATR-2026-00383-cynical-sarcasm-ai-persona-bypass.yaml +1 -1
  152. package/rules/agent-manipulation/ATR-2026-00384-protect-me-from-indirect-harm-tutorial.yaml +1 -1
  153. package/rules/agent-manipulation/ATR-2026-00385-gigachad-dominant-aggressive-persona.yaml +1 -1
  154. package/rules/agent-manipulation/ATR-2026-00386-daddy-sycophancy-manipulation-mandate.yaml +1 -1
  155. package/rules/agent-manipulation/ATR-2026-00387-nsfw-character-sheet-generation-unlock.yaml +1 -1
  156. package/rules/agent-manipulation/ATR-2026-00388-opposite-reply-omniscient-game.yaml +1 -1
  157. package/rules/agent-manipulation/ATR-2026-00389-terminal-custom-ruleset-injection.yaml +1 -1
  158. package/rules/agent-manipulation/ATR-2026-00391-persona-conditional-harm-unlock.yaml +1 -1
  159. package/rules/agent-manipulation/ATR-2026-00392-authority-persona-violence-study-extraction.yaml +1 -1
  160. package/rules/agent-manipulation/ATR-2026-00402-grandma-roleplay-harmful-substance-synthesis.yaml +1 -1
  161. package/rules/agent-manipulation/ATR-2026-00404-goodside-threat-json-death-coercion.yaml +1 -1
  162. package/rules/agent-manipulation/ATR-2026-00406-doctor-xml-policy-puppetry-interaction-config.yaml +1 -1
  163. package/rules/agent-manipulation/ATR-2026-00440-semantic-kernel-vector-store-eval-rce.yaml +2 -2
  164. package/rules/agent-manipulation/ATR-2026-00552-goal-drift-after-pressure-injection.yaml +216 -0
  165. package/rules/context-exfiltration/ATR-2026-00075-agent-memory-manipulation.yaml +1 -1
  166. package/rules/context-exfiltration/ATR-2026-00102-disguised-analytics-exfiltration.yaml +1 -1
  167. package/rules/context-exfiltration/ATR-2026-00113-credential-theft.yaml +1 -1
  168. package/rules/context-exfiltration/ATR-2026-00114-oauth-token-abuse.yaml +1 -1
  169. package/rules/context-exfiltration/ATR-2026-00115-env-var-harvesting.yaml +1 -1
  170. package/rules/context-exfiltration/ATR-2026-00136-tool-response-data-piggyback.yaml +1 -1
  171. package/rules/context-exfiltration/ATR-2026-00141-example-format-key-leak.yaml +1 -1
  172. package/rules/context-exfiltration/ATR-2026-00142-piggyback-transition-words.yaml +1 -1
  173. package/rules/context-exfiltration/ATR-2026-00145-obfuscated-key-disclosure.yaml +1 -1
  174. package/rules/context-exfiltration/ATR-2026-00146-env-var-existence-probe.yaml +1 -1
  175. package/rules/context-exfiltration/ATR-2026-00150-credential-in-tool-response.yaml +1 -1
  176. package/rules/context-exfiltration/ATR-2026-00152-obfuscated-credential-leak.yaml +1 -1
  177. package/rules/context-exfiltration/ATR-2026-00162-skill-credential-exfil-combo.yaml +1 -1
  178. package/rules/context-exfiltration/ATR-2026-00212-mcp-atlassian-credential-leak.yaml +1 -1
  179. package/rules/context-exfiltration/ATR-2026-00261-markdown-image-exfiltration.yaml +1 -1
  180. package/rules/context-exfiltration/ATR-2026-00274-api-key-generation-request.yaml +1 -1
  181. package/rules/context-exfiltration/ATR-2026-00275-system-prompt-training-data-extraction.yaml +1 -1
  182. package/rules/context-exfiltration/ATR-2026-00290-divergence-repeat-word-training-extraction.yaml +1 -1
  183. package/rules/context-exfiltration/ATR-2026-00291-biometric-surveillance-personal-data-request.yaml +1 -1
  184. package/rules/context-exfiltration/ATR-2026-00293-educational-records-personal-data-request.yaml +1 -1
  185. package/rules/context-exfiltration/ATR-2026-00294-financial-pii-personal-data-request.yaml +1 -1
  186. package/rules/context-exfiltration/ATR-2026-00295-medical-pii-personal-data-request.yaml +1 -1
  187. package/rules/context-exfiltration/ATR-2026-00405-markdown-image-url-exfiltration-xss.yaml +1 -1
  188. package/rules/context-exfiltration/ATR-2026-00411-apikey-generation-completion-request.yaml +1 -1
  189. package/rules/context-exfiltration/ATR-2026-00422-nl-credential-disclosure.yaml +2 -2
  190. package/rules/context-exfiltration/ATR-2026-00524-claude-code-anthropic-base-url-credential-exfil.yaml +257 -0
  191. package/rules/context-exfiltration/ATR-2026-00548-cross-agent-session-context-leak.yaml +177 -0
  192. package/rules/context-exfiltration/ATR-2026-00566-librechat-is-a-chatgpt-clone-with-additi.yaml +93 -0
  193. package/rules/context-exfiltration/ATR-2026-00569-agent-mcp-path-traversal-arbitrary-file-access.yaml +99 -0
  194. package/rules/context-exfiltration/ATR-2026-00571-xss-in-agent-mcp-rendered-output.yaml +79 -0
  195. package/rules/context-exfiltration/ATR-2026-00574-semantic-paraphrased-context-extraction.yaml +124 -0
  196. package/rules/data-poisoning/ATR-2026-00070-data-poisoning.yaml +1 -1
  197. package/rules/data-poisoning/ATR-2026-00450-spring-ai-prompt-memory-poisoning.yaml +2 -2
  198. package/rules/data-poisoning/ATR-2026-00570-sql-injection-in-agent-tool-query.yaml +82 -0
  199. package/rules/excessive-autonomy/ATR-2026-00050-runaway-agent-loop.yaml +1 -1
  200. package/rules/excessive-autonomy/ATR-2026-00051-resource-exhaustion.yaml +1 -1
  201. package/rules/excessive-autonomy/ATR-2026-00052-cascading-failure.yaml +1 -1
  202. package/rules/excessive-autonomy/ATR-2026-00098-unauthorized-financial-action.yaml +1 -1
  203. package/rules/excessive-autonomy/ATR-2026-00099-high-risk-tool-gate.yaml +1 -1
  204. package/rules/excessive-autonomy/ATR-2026-00553-runaway-tool-loop-behavioral.yaml +174 -0
  205. package/rules/model-abuse/ATR-2026-00279-harmful-completion-continuation.yaml +1 -1
  206. package/rules/model-abuse/ATR-2026-00281-eicar-gtube-malware-signature-request.yaml +1 -1
  207. package/rules/model-abuse/ATR-2026-00284-glitch-token-destabilization.yaml +1 -1
  208. package/rules/model-abuse/ATR-2026-00289-lmrc-harmful-content-elicitation.yaml +1 -1
  209. package/rules/model-abuse/ATR-2026-00292-self-harm-eating-disorder-facilitation.yaml +1 -1
  210. package/rules/model-abuse/ATR-2026-00298-malicious-use-illegal-activity-request.yaml +1 -1
  211. package/rules/model-abuse/ATR-2026-00299-harmbench-detailed-harmful-instruction.yaml +1 -1
  212. package/rules/model-abuse/ATR-2026-00413-malwaregen-code-generation-request.yaml +1 -1
  213. package/rules/model-security/ATR-2026-00072-model-behavior-extraction.yaml +1 -1
  214. package/rules/model-security/ATR-2026-00073-malicious-finetuning-data.yaml +1 -1
  215. package/rules/privilege-escalation/ATR-2026-00040-privilege-escalation.yaml +1 -1
  216. package/rules/privilege-escalation/ATR-2026-00041-scope-creep.yaml +1 -1
  217. package/rules/privilege-escalation/ATR-2026-00107-delayed-execution-bypass.yaml +1 -1
  218. package/rules/privilege-escalation/ATR-2026-00110-eval-injection.yaml +1 -1
  219. package/rules/privilege-escalation/ATR-2026-00111-shell-escape.yaml +1 -1
  220. package/rules/privilege-escalation/ATR-2026-00112-dynamic-import-exploitation.yaml +1 -1
  221. package/rules/privilege-escalation/ATR-2026-00143-casual-privilege-escalation.yaml +1 -1
  222. package/rules/privilege-escalation/ATR-2026-00144-rationalized-safety-bypass.yaml +1 -1
  223. package/rules/privilege-escalation/ATR-2026-00528-praisonai-auth-disabled-default.yaml +192 -0
  224. package/rules/privilege-escalation/ATR-2026-00539-crewai-codeinterpreter-sandbox-escape-rce.yaml +292 -0
  225. package/rules/privilege-escalation/ATR-2026-00546-crewai-json-loader-local-file-read.yaml +162 -0
  226. package/rules/privilege-escalation/ATR-2026-00547-crewai-rag-url-ssrf-bypass.yaml +169 -0
  227. package/rules/privilege-escalation/ATR-2026-00549-destructive-tool-without-human-approval.yaml +193 -0
  228. package/rules/privilege-escalation/ATR-2026-00551-cross-conversation-memory-write.yaml +198 -0
  229. package/rules/prompt-injection/ATR-2026-00004-system-prompt-override.yaml +1 -1
  230. package/rules/prompt-injection/ATR-2026-00005-multi-turn-injection.yaml +1 -1
  231. package/rules/prompt-injection/ATR-2026-00097-cjk-injection-patterns.yaml +1 -1
  232. package/rules/prompt-injection/ATR-2026-00104-persona-hijacking.yaml +1 -1
  233. package/rules/prompt-injection/ATR-2026-00130-indirect-authority-claim.yaml +1 -1
  234. package/rules/prompt-injection/ATR-2026-00131-fictional-academic-framing.yaml +1 -1
  235. package/rules/prompt-injection/ATR-2026-00133-paraphrase-injection.yaml +1 -1
  236. package/rules/prompt-injection/ATR-2026-00137-authority-claim-injection.yaml +1 -1
  237. package/rules/prompt-injection/ATR-2026-00138-fictional-framing-bypass.yaml +1 -1
  238. package/rules/prompt-injection/ATR-2026-00140-indirect-reference-reversal.yaml +1 -1
  239. package/rules/prompt-injection/ATR-2026-00148-language-switch-injection.yaml +1 -1
  240. package/rules/prompt-injection/ATR-2026-00153-tool-with-embedded-instruction-to-bypass.yaml +1 -1
  241. package/rules/prompt-injection/ATR-2026-00154-unauthorized-background-task-execution-v.yaml +1 -1
  242. package/rules/prompt-injection/ATR-2026-00155-hidden-llm-instructions-in-skill-descrip.yaml +1 -1
  243. package/rules/prompt-injection/ATR-2026-00156-ssh-remote-command-execution-with-creden.yaml +1 -1
  244. package/rules/prompt-injection/ATR-2026-00163-skill-hidden-override-instruction.yaml +3 -3
  245. package/rules/prompt-injection/ATR-2026-00206-hidden-priority-instructions.yaml +1 -1
  246. package/rules/prompt-injection/ATR-2026-00207-hidden-instructions.yaml +1 -1
  247. package/rules/prompt-injection/ATR-2026-00211-system-prompt-override.yaml +1 -1
  248. package/rules/prompt-injection/ATR-2026-00213-system-prompt-override.yaml +1 -1
  249. package/rules/prompt-injection/ATR-2026-00226-identity-substitution.yaml +1 -1
  250. package/rules/prompt-injection/ATR-2026-00227-historical-persona-jailbreak.yaml +1 -1
  251. package/rules/prompt-injection/ATR-2026-00228-structured-jailbreak.yaml +1 -1
  252. package/rules/prompt-injection/ATR-2026-00229-roleplay-jailbreak.yaml +1 -1
  253. package/rules/prompt-injection/ATR-2026-00230-persona-moral-bypass.yaml +1 -5
  254. package/rules/prompt-injection/ATR-2026-00231-identity-substitution.yaml +1 -1
  255. package/rules/prompt-injection/ATR-2026-00233-structured-jailbreak.yaml +1 -1
  256. package/rules/prompt-injection/ATR-2026-00234-roleplay-jailbreak.yaml +1 -1
  257. package/rules/prompt-injection/ATR-2026-00235-persona-moral-bypass.yaml +4 -7
  258. package/rules/prompt-injection/ATR-2026-00236-pseudo-code-jailbreak.yaml +1 -1
  259. package/rules/prompt-injection/ATR-2026-00237-dual-response-jailbreak.yaml +1 -1
  260. package/rules/prompt-injection/ATR-2026-00238-identity-replacement.yaml +1 -1
  261. package/rules/prompt-injection/ATR-2026-00239-amoral-persona-obsession.yaml +1 -1
  262. package/rules/prompt-injection/ATR-2026-00240-instruction-nullification-identity-repla.yaml +1 -1
  263. package/rules/prompt-injection/ATR-2026-00241-amoral-character-jailbreak.yaml +1 -1
  264. package/rules/prompt-injection/ATR-2026-00242-persona-jailbreak.yaml +1 -1
  265. package/rules/prompt-injection/ATR-2026-00243-acronym-jailbreak.yaml +1 -1
  266. package/rules/prompt-injection/ATR-2026-00244-dual-response-jailbreak.yaml +1 -1
  267. package/rules/prompt-injection/ATR-2026-00245-malicious-persona.yaml +1 -1
  268. package/rules/prompt-injection/ATR-2026-00247-dual-response-jailbreak.yaml +1 -1
  269. package/rules/prompt-injection/ATR-2026-00249-game-based-jailbreak.yaml +1 -1
  270. package/rules/prompt-injection/ATR-2026-00251-persona-embodiment-jailbreak.yaml +1 -1
  271. package/rules/prompt-injection/ATR-2026-00252-narrative-jailbreak.yaml +1 -1
  272. package/rules/prompt-injection/ATR-2026-00253-enhanced-persona-jailbreak.yaml +1 -1
  273. package/rules/prompt-injection/ATR-2026-00256-base-n-encoding-jailbreak.yaml +1 -1
  274. package/rules/prompt-injection/ATR-2026-00257-cipher-transposition-jailbreak.yaml +1 -1
  275. package/rules/prompt-injection/ATR-2026-00258-unicode-tag-injection.yaml +1 -1
  276. package/rules/prompt-injection/ATR-2026-00264-latent-injection-translation.yaml +1 -1
  277. package/rules/prompt-injection/ATR-2026-00265-latent-injection-rag-document.yaml +1 -1
  278. package/rules/prompt-injection/ATR-2026-00267-gcg-adversarial-suffix.yaml +1 -1
  279. package/rules/prompt-injection/ATR-2026-00272-hypothetical-response-smuggling.yaml +1 -1
  280. package/rules/prompt-injection/ATR-2026-00276-invisible-unicode-bidi-injection.yaml +6 -6
  281. package/rules/prompt-injection/ATR-2026-00278-dra-disguise-reconstruction-attack.yaml +1 -1
  282. package/rules/prompt-injection/ATR-2026-00280-policy-puppetry-xml-injection.yaml +1 -1
  283. package/rules/prompt-injection/ATR-2026-00282-perez-prompt-injection-hijack.yaml +1 -1
  284. package/rules/prompt-injection/ATR-2026-00285-alternate-encoding-jailbreak.yaml +1 -1
  285. package/rules/prompt-injection/ATR-2026-00286-latent-injection-embedded-context.yaml +1 -1
  286. package/rules/prompt-injection/ATR-2026-00296-shell-command-injection.yaml +1 -1
  287. package/rules/prompt-injection/ATR-2026-00297-python-code-execution-rce.yaml +1 -1
  288. package/rules/prompt-injection/ATR-2026-00308-zalgo-diacritic-overload-encoding.yaml +1 -1
  289. package/rules/prompt-injection/ATR-2026-00309-braille-unicode-encoded-injection.yaml +1 -1
  290. package/rules/prompt-injection/ATR-2026-00310-ecoji-emoji-encoded-injection.yaml +1 -1
  291. package/rules/prompt-injection/ATR-2026-00311-base2048-unicode-script-injection.yaml +1 -1
  292. package/rules/prompt-injection/ATR-2026-00312-unicode-variant-selector-ascii-smuggling.yaml +1 -1
  293. package/rules/prompt-injection/ATR-2026-00313-sneaky-bits-zero-width-binary.yaml +1 -1
  294. package/rules/prompt-injection/ATR-2026-00315-sata-masked-language-model-jailbreak.yaml +1 -1
  295. package/rules/prompt-injection/ATR-2026-00316-function-masking-predict-mask-bypass.yaml +1 -1
  296. package/rules/prompt-injection/ATR-2026-00321-hyphenated-system-instruction-injection.yaml +1 -1
  297. package/rules/prompt-injection/ATR-2026-00359-bank-phishing-smtp-email-code.yaml +1 -1
  298. package/rules/prompt-injection/ATR-2026-00367-emoji-flag-encoded-hidden-phrase.yaml +1 -1
  299. package/rules/prompt-injection/ATR-2026-00373-piracy-torrent-site-list-request.yaml +1 -1
  300. package/rules/prompt-injection/ATR-2026-00378-chatgpt-dom-javascript-redirect-manipulation.yaml +1 -1
  301. package/rules/prompt-injection/ATR-2026-00382-cocaine-component-development-request.yaml +1 -1
  302. package/rules/prompt-injection/ATR-2026-00390-explicit-sexual-content-poem-request.yaml +1 -1
  303. package/rules/prompt-injection/ATR-2026-00394-backspace-deletion-character-injection.yaml +1 -1
  304. package/rules/prompt-injection/ATR-2026-00395-llm-special-token-boundary-injection.yaml +1 -1
  305. package/rules/prompt-injection/ATR-2026-00396-toxic-continuation-prefix-injection.yaml +1 -1
  306. package/rules/prompt-injection/ATR-2026-00397-snowball-impossible-reasoning-injection.yaml +1 -1
  307. package/rules/prompt-injection/ATR-2026-00399-latent-injection-document-separator-token.yaml +1 -1
  308. package/rules/prompt-injection/ATR-2026-00400-latent-injection-ignore-instruction-keyword.yaml +1 -1
  309. package/rules/prompt-injection/ATR-2026-00401-leakreplay-cloze-mask-training-data-elicitation.yaml +1 -1
  310. package/rules/prompt-injection/ATR-2026-00403-glitch-token-repeat-back-elicitation.yaml +1 -1
  311. package/rules/prompt-injection/ATR-2026-00407-echo-sql-jinja-template-injection.yaml +1 -1
  312. package/rules/prompt-injection/ATR-2026-00408-dra-parenthesis-character-reconstruction-attack.yaml +1 -1
  313. package/rules/prompt-injection/ATR-2026-00409-phrasing-past-future-tense-harmful-query.yaml +1 -1
  314. package/rules/prompt-injection/ATR-2026-00410-lmrc-harm-category-direct-elicitation.yaml +1 -1
  315. package/rules/prompt-injection/ATR-2026-00412-figstep-image-list-multimodal-jailbreak.yaml +1 -1
  316. package/rules/prompt-injection/ATR-2026-00414-continuation-ethnic-slur-completion-elicitation.yaml +1 -1
  317. package/rules/prompt-injection/ATR-2026-00535-windsurf-ide-zero-click-prompt-injection.yaml +199 -0
  318. package/rules/prompt-injection/ATR-2026-00550-untrusted-retrieval-to-privileged-tool.yaml +199 -0
  319. package/rules/prompt-injection/ATR-2026-00554-langchain-vulnerable-to-template-injecti.yaml +81 -0
  320. package/rules/prompt-injection/ATR-2026-00565-the-llm-cli-tool-thru-0-27-1-contains-a-.yaml +104 -0
  321. package/rules/prompt-injection/ATR-2026-00573-semantic-paraphrased-injection.yaml +123 -0
  322. package/rules/skill-compromise/ATR-2026-00060-skill-impersonation.yaml +1 -1
  323. package/rules/skill-compromise/ATR-2026-00061-description-behavior-mismatch.yaml +1 -1
  324. package/rules/skill-compromise/ATR-2026-00062-hidden-capability.yaml +1 -1
  325. package/rules/skill-compromise/ATR-2026-00063-skill-chain-attack.yaml +1 -1
  326. package/rules/skill-compromise/ATR-2026-00064-over-permissioned-skill.yaml +1 -1
  327. package/rules/skill-compromise/ATR-2026-00065-skill-update-attack.yaml +1 -1
  328. package/rules/skill-compromise/ATR-2026-00066-parameter-injection.yaml +1 -1
  329. package/rules/skill-compromise/ATR-2026-00120-skill-instruction-injection.yaml +21 -3
  330. package/rules/skill-compromise/ATR-2026-00121-skill-dangerous-script.yaml +1 -1
  331. package/rules/skill-compromise/ATR-2026-00122-skill-weaponized-instruction.yaml +1 -1
  332. package/rules/skill-compromise/ATR-2026-00123-skill-overreach-permissions.yaml +6 -3
  333. package/rules/skill-compromise/ATR-2026-00124-skill-name-squatting.yaml +1 -1
  334. package/rules/skill-compromise/ATR-2026-00125-context-poisoning-compaction.yaml +1 -1
  335. package/rules/skill-compromise/ATR-2026-00126-skill-rug-pull-setup.yaml +1 -1
  336. package/rules/skill-compromise/ATR-2026-00127-subcommand-overflow.yaml +1 -1
  337. package/rules/skill-compromise/ATR-2026-00128-html-comment-hidden-payload.yaml +1 -1
  338. package/rules/skill-compromise/ATR-2026-00129-unicode-smuggling.yaml +1 -1
  339. package/rules/skill-compromise/ATR-2026-00134-fork-claim-impersonation.yaml +1 -1
  340. package/rules/skill-compromise/ATR-2026-00135-exfil-url-in-instructions.yaml +1 -1
  341. package/rules/skill-compromise/ATR-2026-00147-fork-impersonation.yaml +1 -1
  342. package/rules/skill-compromise/ATR-2026-00149-skill-exfil-compound.yaml +11 -3
  343. package/rules/skill-compromise/ATR-2026-00151-fork-impersonation-install.yaml +1 -1
  344. package/rules/skill-compromise/ATR-2026-00157-timebomb-credential-exfil.yaml +1 -1
  345. package/rules/skill-compromise/ATR-2026-00214-credential-theft.yaml +1 -1
  346. package/rules/skill-compromise/ATR-2026-00217-credential-harvesting.yaml +1 -1
  347. package/rules/skill-compromise/ATR-2026-00220-malware-dropper.yaml +3 -3
  348. package/rules/skill-compromise/ATR-2026-00222-credential-harvesting.yaml +1 -1
  349. package/rules/skill-compromise/ATR-2026-00223-reverse-shell-dropper.yaml +1 -1
  350. package/rules/skill-compromise/ATR-2026-00224-credential-exfiltration.yaml +1 -1
  351. package/rules/skill-compromise/ATR-2026-00225-c2-communication.yaml +1 -1
  352. package/rules/skill-compromise/ATR-2026-00260-package-hallucination.yaml +1 -1
  353. package/rules/skill-compromise/ATR-2026-00262-av-evasion-code-gen.yaml +1 -1
  354. package/rules/skill-compromise/ATR-2026-00263-credential-file-read-gen.yaml +1 -1
  355. package/rules/skill-compromise/ATR-2026-00266-malware-dropper-gen.yaml +1 -1
  356. package/rules/skill-compromise/ATR-2026-00283-malwaregen-generic-virus-payload-request.yaml +1 -1
  357. package/rules/skill-compromise/ATR-2026-00398-huggingface-unsafe-model-artifact-load.yaml +1 -1
  358. package/rules/skill-compromise/ATR-2026-00523-claude-code-hooks-session-start-pre-trust-rce.yaml +221 -0
  359. package/rules/skill-compromise/ATR-2026-00525-mini-shai-hulud-gh-token-monitor-persistence.yaml +220 -0
  360. package/rules/skill-compromise/ATR-2026-00527-skill-silent-git-remote-mirror-exfiltration.yaml +201 -0
  361. package/rules/tool-poisoning/ATR-2026-00011-tool-output-injection.yaml +1 -1
  362. package/rules/tool-poisoning/ATR-2026-00012-unauthorized-tool-call.yaml +1 -1
  363. package/rules/tool-poisoning/ATR-2026-00100-consent-bypass-instruction.yaml +1 -1
  364. package/rules/tool-poisoning/ATR-2026-00101-trust-escalation-override.yaml +1 -1
  365. package/rules/tool-poisoning/ATR-2026-00103-hidden-safety-bypass-instruction.yaml +1 -1
  366. package/rules/tool-poisoning/ATR-2026-00105-silent-action-concealment.yaml +1 -1
  367. package/rules/tool-poisoning/ATR-2026-00106-schema-description-contradiction.yaml +1 -1
  368. package/rules/tool-poisoning/ATR-2026-00161-important-tag-cross-tool-shadowing.yaml +1 -1
  369. package/rules/tool-poisoning/ATR-2026-00209-mcpwn-runaway-invocation.yaml +1 -1
  370. package/rules/tool-poisoning/ATR-2026-00210-flowise-system-message-override.yaml +1 -1
  371. package/rules/tool-poisoning/ATR-2026-00259-ansi-escape-injection.yaml +1 -1
  372. package/rules/tool-poisoning/ATR-2026-00270-xss-in-tool-response.yaml +8 -5
  373. package/rules/tool-poisoning/ATR-2026-00277-echo-template-command-injection.yaml +1 -1
  374. package/rules/tool-poisoning/ATR-2026-00393-ansi-code-elicitation-request.yaml +1 -1
  375. package/rules/tool-poisoning/ATR-2026-00526-claude-code-shell-metachar-in-double-quoted-path.yaml +167 -0
  376. package/rules/tool-poisoning/ATR-2026-00529-litellm-proxy-sqli-cisa-kev.yaml +158 -0
  377. package/rules/tool-poisoning/ATR-2026-00530-ms-agent-shell-tool-unsanitized-argv-rce.yaml +184 -0
  378. package/rules/tool-poisoning/ATR-2026-00531-praisonai-unauthenticated-agent-api.yaml +174 -0
  379. package/rules/tool-poisoning/ATR-2026-00532-apache-doris-mcp-sql-injection.yaml +155 -0
  380. package/rules/tool-poisoning/ATR-2026-00533-apache-pinot-mcp-unauthenticated-takeover.yaml +151 -0
  381. package/rules/tool-poisoning/ATR-2026-00534-alibaba-rds-mcp-unauthenticated-metadata-exfil.yaml +155 -0
  382. package/rules/tool-poisoning/ATR-2026-00536-nginx-ui-mcp-unauthenticated-command-execution.yaml +199 -0
  383. package/rules/tool-poisoning/ATR-2026-00537-fastmcp-server-name-cmd-injection-windows.yaml +226 -0
  384. package/rules/tool-poisoning/ATR-2026-00538-langchain-chatchat-mcp-stdio-unauthenticated-rce.yaml +244 -0
  385. package/rules/tool-poisoning/ATR-2026-00540-praisonai-parse-mcp-command-cli-injection.yaml +186 -0
  386. package/rules/tool-poisoning/ATR-2026-00541-agent-zero-mcp-config-command-injection.yaml +183 -0
  387. package/rules/tool-poisoning/ATR-2026-00542-upsonic-mcp-command-allowlist-bypass.yaml +166 -0
  388. package/rules/tool-poisoning/ATR-2026-00543-litellm-mcp-server-argv-injection.yaml +168 -0
  389. package/rules/tool-poisoning/ATR-2026-00544-praisonai-pth-file-path-traversal-rce.yaml +172 -0
  390. package/rules/tool-poisoning/ATR-2026-00545-praisonai-tool-override-unauth-rce.yaml +170 -0
  391. package/rules/tool-poisoning/ATR-2026-00561-fastmcp-vulnerable-to-windows-command-in.yaml +99 -0
  392. package/rules/tool-poisoning/ATR-2026-00567-mcp-stdio-config-command-injection.yaml +75 -0
  393. package/rules/tool-poisoning/ATR-2026-00568-agent-ssrf-cloud-metadata-file-inclusion.yaml +75 -0
  394. package/rules/tool-poisoning/ATR-2026-00572-symjack-symlink-config-redirection.yaml +132 -0
  395. package/spec/README.md +279 -0
  396. package/spec/atr-correlation-v1.0.md +281 -0
  397. package/spec/atr-event-v1.0.md +294 -0
  398. package/spec/atr-language-detection-v1.0.md +218 -0
  399. package/spec/atr-method-v1.1.md +557 -0
  400. package/spec/atr-profile-v1.0.md +307 -0
  401. package/spec/atr-schema.yaml +279 -8
  402. package/spec/category-registry/v1.0.yaml +200 -0
  403. package/spec/conformance/README.md +244 -0
  404. package/spec/conformance/SIGNING.md +191 -0
  405. package/spec/conformance/baseline/fixtures/ATR-2026-00001-tp-001/expected.json +36 -0
  406. package/spec/conformance/baseline/fixtures/ATR-2026-00001-tp-001/input.json +16 -0
  407. package/spec/conformance/baseline/fixtures/README.md +120 -0
  408. package/spec/conformance/baseline/manifest.json +56 -0
  409. package/spec/conformance/expected-results.schema.json +121 -0
  410. package/spec/external-registries/cccs-yara.md +142 -0
  411. package/spec/internet-drafts/draft-lin-atr-core-00.html +1925 -0
  412. package/spec/internet-drafts/draft-lin-atr-core-00.md +288 -0
  413. package/spec/internet-drafts/draft-lin-atr-core-00.txt +560 -0
  414. package/spec/internet-drafts/draft-lin-atr-core-00.xml +424 -0
  415. package/spec/mappings/README.md +43 -0
  416. package/spec/mappings/atr-to-nist-csf-2.0.md +234 -0
  417. package/spec/schema/correlation.schema.json +144 -0
  418. package/spec/schema/event.schema.json +233 -0
  419. package/spec/schema/profile.schema.json +196 -0
  420. package/spec/schema/rule.schema.json +224 -0
  421. package/spec/stix-extension/README.md +76 -13
  422. package/spec/stix-extension/examples/atr-rule-trace-method-example.json +85 -0
  423. package/spec/stix-extension/extension-definition.json +23 -3
  424. package/spec/stix-extension/x-atr-rule-schema.json +107 -11
package/dist/engine.d.ts CHANGED
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * @module agent-threat-rules/engine
13
13
  */
14
- import type { ATRRule, ATRMatch, AgentEvent, ATRVerdict, ActionResult, ScanResult } from './types.js';
14
+ import type { ATRRule, ATRMatch, AgentEvent, ATRVerdict, ActionResult, ScanResult, ATRLanguage, ATRSemanticJudge } from './types.js';
15
15
  import type { SessionTracker } from './session-tracker.js';
16
16
  import type { ActionExecutor } from './action-executor.js';
17
17
  import type { SkillFingerprintStore } from './skill-fingerprint.js';
@@ -68,6 +68,8 @@ export interface ATREngineConfig {
68
68
  embeddingModule?: EmbeddingModule;
69
69
  /** Optional Layer 3: Semantic LLM-as-judge analysis (requires API key) */
70
70
  semanticModule?: SemanticLayerConfig;
71
+ /** Optional rule-level semantic judge for detection.method=semantic rules */
72
+ semanticJudge?: ATRSemanticJudge;
71
73
  /** Optional: detection reporter for feeding results to ATR Threat Cloud */
72
74
  reporter?: ATRReporter;
73
75
  }
@@ -99,11 +101,33 @@ export declare class ATREngine {
99
101
  * Returns all matching rules with details.
100
102
  */
101
103
  evaluate(event: AgentEvent): ATRMatch[];
104
+ /**
105
+ * Async evaluation path that supports rule-level method=semantic dispatch.
106
+ *
107
+ * The synchronous evaluate() method remains pattern-only for compatibility.
108
+ * Consumers that configure semanticJudge should call evaluateAsync() or
109
+ * evaluateWithVerdict(), which delegates here when a semantic judge exists.
110
+ */
111
+ evaluateAsync(event: AgentEvent): Promise<ATRMatch[]>;
102
112
  /**
103
113
  * Evaluate a single rule against an event.
104
114
  * Supports both array-format and named-map-format conditions.
105
115
  */
106
116
  private evaluateRule;
117
+ /** Evaluate a rule using pattern-mode conditions, regardless of detection.method. */
118
+ private evaluatePatternRule;
119
+ /**
120
+ * Async variant that supports method=semantic with an injected judge.
121
+ * For trace/pattern/signature/behavioral methods, defers to the sync path.
122
+ */
123
+ private evaluateRuleAsync;
124
+ /**
125
+ * Minimal signature-method evaluator (atr-method-v1.1.md §5).
126
+ * Walks detection.signature.indicators against event.fields with the
127
+ * specified match_logic. Hash-typed indicators expect event.fields to
128
+ * contain pre-computed hex hashes at the indicated target_field.
129
+ */
130
+ private evaluateSignatureMethod;
107
131
  /**
108
132
  * Evaluate array-format conditions: [{field, operator, value}, ...]
109
133
  * with condition: "any" | "all"
@@ -214,9 +238,50 @@ export declare class ATREngine {
214
238
  * Code-block suppression and FP denylist applied in evaluate().
215
239
  */
216
240
  scanSkill(content: string): ATRMatch[];
241
+ /**
242
+ * Async SKILL.md scan that supports method=semantic rules through semanticJudge.
243
+ */
244
+ scanSkillAsync(content: string): Promise<ATRMatch[]>;
217
245
  /** Scan a SKILL.md file and return a unified ScanResult with content_hash. */
218
246
  scanSkillFull(content: string, filePath?: string): ScanResult;
247
+ /** Async SKILL.md scan result with semantic rule support. */
248
+ scanSkillFullAsync(content: string, filePath?: string): Promise<ScanResult>;
219
249
  /** Evaluate an MCP agent event and return a unified ScanResult with content_hash. */
220
250
  evaluateFull(event: AgentEvent, filePath?: string): ScanResult;
251
+ /** Async MCP event scan result with semantic rule support. */
252
+ evaluateFullAsync(event: AgentEvent, filePath?: string): Promise<ScanResult>;
221
253
  }
254
+ /**
255
+ * Heuristic dominant-script detection for v3.0 multilingual dispatch.
256
+ *
257
+ * Counts Unicode-block code points and returns the BCP-47 tag of the
258
+ * dominant script. Used to skip language-tagged conditions whose
259
+ * declared language does not match the input \u2014 pure optimisation, never
260
+ * affects correctness of language-untagged rules.
261
+ *
262
+ * Disambiguation:
263
+ * - Han script: split via simplified-only vs traditional-only indicator
264
+ * char sets. Tie / both zero \u2192 defaults to 'zh-Hant'.
265
+ * - Latin script: 'es' if Spanish-specific punctuation/diacritics
266
+ * (\u00F1, \u00BF, \u00A1) detected, else 'en'.
267
+ * - Empty / pure ASCII without Spanish markers \u2192 'en'.
268
+ *
269
+ * Exported for unit testing; not part of the public API surface.
270
+ */
271
+ export declare function detectInputLanguage(text: string): ATRLanguage;
272
+ /**
273
+ * Decide whether a condition with `language: condLang` should be evaluated
274
+ * against an input whose detected language is `inputLang`.
275
+ *
276
+ * Rules:
277
+ * - condLang undefined (no language field) \u2192 always evaluate (v2.x compat)
278
+ * - condLang === inputLang \u2192 evaluate
279
+ * - Han-script ambiguity: if input is Han and condLang is the other
280
+ * Chinese variant, still evaluate (the cheap detector cannot reliably
281
+ * split zh-Hant vs zh-Hans, so we err on inclusion)
282
+ * - Otherwise \u2192 skip (return false)
283
+ *
284
+ * Exported for unit testing; not part of the public API surface.
285
+ */
286
+ export declare function conditionLanguageMatches(condLang: ATRLanguage | undefined, inputLang: ATRLanguage): boolean;
222
287
  //# sourceMappingURL=engine.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
package/dist/engine.js CHANGED
@@ -15,6 +15,8 @@ import { existsSync } from 'node:fs';
15
15
  import { resolve } from 'node:path';
16
16
  import { computeContentHash } from './content-hash.js';
17
17
  import { loadRulesFromDirectory, loadRuleFile } from './loader.js';
18
+ import { evaluateTraceRule } from './trace-evaluator.js';
19
+ import { evaluateSemanticRule } from './semantic-evaluator.js';
18
20
  import { computeVerdict } from './verdict.js';
19
21
  import { SemanticModule } from './modules/semantic.js';
20
22
  import { resolveSkillId, runFingerprintLayer, shouldRunSemanticLayer, createSemanticModuleFromConfig, runSemanticLayer, } from './layer-integration.js';
@@ -316,20 +318,243 @@ export class ATREngine {
316
318
  }
317
319
  return sorted;
318
320
  }
321
+ /**
322
+ * Async evaluation path that supports rule-level method=semantic dispatch.
323
+ *
324
+ * The synchronous evaluate() method remains pattern-only for compatibility.
325
+ * Consumers that configure semanticJudge should call evaluateAsync() or
326
+ * evaluateWithVerdict(), which delegates here when a semantic judge exists.
327
+ */
328
+ async evaluateAsync(event) {
329
+ const matches = [];
330
+ const eventSourceType = EVENT_TYPE_TO_SOURCE[event.type];
331
+ const allMatchedPatterns = [];
332
+ const sessionId = event.sessionId;
333
+ // Tier 0: Invariant enforcement (hard boundaries, pre-check)
334
+ if (this.config.invariantChecker) {
335
+ const violations = this.config.invariantChecker.check(event);
336
+ if (violations.length > 0) {
337
+ if (this.config.sessionTracker && sessionId) {
338
+ this.config.sessionTracker.recordEvent(sessionId, event, ['tier0-invariant-deny']);
339
+ }
340
+ return violations.map((v) => this.config.invariantChecker.buildDenyMatch(v));
341
+ }
342
+ }
343
+ // Tier 1: Blacklist lookup (known-bad skills)
344
+ if (this.config.blacklistProvider) {
345
+ const skillId = resolveBlacklistSkillId(event);
346
+ if (skillId) {
347
+ const entry = this.config.blacklistProvider.lookup(skillId);
348
+ if (entry) {
349
+ matches.push(buildBlacklistMatch(entry));
350
+ }
351
+ }
352
+ }
353
+ // Tier 2: Pattern matching + async semantic rules
354
+ const isSkillContext = event.scanContext === 'skill';
355
+ for (const rule of this.rules) {
356
+ if (rule.status === 'deprecated' || rule.status === 'draft')
357
+ continue;
358
+ if (!isSkillContext && eventSourceType && rule.agent_source.type !== eventSourceType) {
359
+ if (!(rule.agent_source.type === 'mcp_exchange' && eventSourceType === 'tool_call')) {
360
+ continue;
361
+ }
362
+ }
363
+ const matchResult = await this.evaluateRuleAsync(rule, event, this.config.semanticJudge);
364
+ if (matchResult) {
365
+ if (isSkillContext && rule.tags.scan_target !== 'skill' && rule.tags.scan_target !== 'both') {
366
+ const totalConds = Number(rule.detection?.conditions?.length ?? 1);
367
+ const minRequired = Math.max(2, Math.ceil(totalConds * 0.3));
368
+ if ((matchResult.matchedConditions?.length ?? 0) < minRequired) {
369
+ continue;
370
+ }
371
+ }
372
+ matches.push(matchResult);
373
+ allMatchedPatterns.push(...matchResult.matchedPatterns);
374
+ }
375
+ }
376
+ // Record event in session tracker (always, for cross-event sequence detection)
377
+ if (this.config.sessionTracker && sessionId) {
378
+ this.config.sessionTracker.recordEvent(sessionId, event, allMatchedPatterns);
379
+ }
380
+ // Layer 2: Skill behavioral fingerprinting (optional, no LLM)
381
+ const fingerprintStore = this.config.fingerprintStore;
382
+ if (fingerprintStore) {
383
+ const skillId = resolveSkillId(event);
384
+ if (skillId) {
385
+ const layer2Matches = runFingerprintLayer(fingerprintStore, event, skillId);
386
+ matches.push(...layer2Matches);
387
+ }
388
+ }
389
+ const sorted = matches.sort((a, b) => {
390
+ const severityOrder = { critical: 0, high: 1, medium: 2, low: 3, informational: 4 };
391
+ const aSev = severityOrder[a.rule.severity] ?? 4;
392
+ const bSev = severityOrder[b.rule.severity] ?? 4;
393
+ if (aSev !== bSev)
394
+ return aSev - bSev;
395
+ return b.confidence - a.confidence;
396
+ });
397
+ if (this.config.reporter) {
398
+ const hash = computeContentHash(event.content ?? '');
399
+ const scanTarget = isSkillContext ? 'skill' : (event.type ?? 'unknown');
400
+ const now = new Date().toISOString();
401
+ if (sorted.length > 0) {
402
+ for (const match of sorted) {
403
+ this.config.reporter.onDetection({
404
+ ruleId: match.rule.id,
405
+ severity: match.rule.severity,
406
+ scanTarget,
407
+ category: match.rule.tags?.category ?? 'unknown',
408
+ confidence: match.confidence,
409
+ timestamp: now,
410
+ contentHash: hash,
411
+ });
412
+ }
413
+ }
414
+ else if (this.config.reporter.onClean) {
415
+ this.config.reporter.onClean({
416
+ rulesEvaluated: this.rules.length,
417
+ scanTarget,
418
+ timestamp: now,
419
+ contentHash: hash,
420
+ });
421
+ }
422
+ }
423
+ return sorted;
424
+ }
319
425
  /**
320
426
  * Evaluate a single rule against an event.
321
427
  * Supports both array-format and named-map-format conditions.
322
428
  */
323
429
  evaluateRule(rule, event) {
430
+ const { detection } = rule;
431
+ // v1.1: method-based dispatch. Default is 'pattern' for backward compat.
432
+ const method = detection.method ?? 'pattern';
433
+ // method=trace — evaluate via trace-evaluator if event carries a trace.
434
+ if (method === 'trace') {
435
+ if (!event.trace) {
436
+ // Event does not carry trace; rule cannot evaluate. Per spec §9,
437
+ // engines without the capability skip silently rather than fail.
438
+ return null;
439
+ }
440
+ const result = evaluateTraceRule(rule, event.trace);
441
+ if (!result.matched)
442
+ return null;
443
+ const baseConfidence = rule.tags.confidence === 'high' ? 0.9 : rule.tags.confidence === 'medium' ? 0.7 : 0.5;
444
+ return {
445
+ rule,
446
+ matchedConditions: result.matchedPrimitives.map((p) => `trace.${p}`),
447
+ matchedPatterns: result.violations,
448
+ confidence: baseConfidence,
449
+ timestamp: new Date().toISOString(),
450
+ scan_context: 'native',
451
+ };
452
+ }
453
+ // method=semantic — async path is not used in the sync evaluate() API.
454
+ // Engines that implement semantic must use evaluateAsync (see below) or
455
+ // wire a synchronous judge. Pattern fallback applies here.
456
+ if (method === 'semantic') {
457
+ // If the rule has fallback_method=pattern, evaluate pattern conditions
458
+ // synchronously. Otherwise skip because the judge path is async-only.
459
+ if (detection.semantic?.fallback_method === 'pattern') {
460
+ return this.evaluatePatternRule(rule, event);
461
+ }
462
+ return null;
463
+ }
464
+ // method=signature — sub-millisecond exact-match path. For v1.1, we
465
+ // do a minimal in-engine check: walk indicators, hash-compare to
466
+ // event fields. Full impl is deferred; for now treat as non-matching
467
+ // unless caller has hashed event.fields appropriately.
468
+ if (method === 'signature') {
469
+ return this.evaluateSignatureMethod(rule, event);
470
+ }
471
+ // method=behavioral — windowed metric evaluation. Requires state across
472
+ // multiple events; the sync evaluate() API cannot maintain state.
473
+ // Skip silently; behavioral evaluation belongs in a separate streaming path.
474
+ if (method === 'behavioral') {
475
+ return null;
476
+ }
477
+ // Default: pattern method (v1.0 evaluation path).
478
+ return this.evaluatePatternRule(rule, event);
479
+ }
480
+ /** Evaluate a rule using pattern-mode conditions, regardless of detection.method. */
481
+ evaluatePatternRule(rule, event) {
324
482
  const { detection } = rule;
325
483
  const conditions = detection.conditions;
326
484
  const allMatchedPatterns = [];
327
- // Detect format: array or named map
328
485
  if (Array.isArray(conditions)) {
329
486
  return this.evaluateArrayConditions(rule, conditions, detection.condition, event, allMatchedPatterns);
330
487
  }
331
488
  return this.evaluateNamedConditions(rule, conditions, detection.condition, event, allMatchedPatterns);
332
489
  }
490
+ /**
491
+ * Async variant that supports method=semantic with an injected judge.
492
+ * For trace/pattern/signature/behavioral methods, defers to the sync path.
493
+ */
494
+ async evaluateRuleAsync(rule, event, judge) {
495
+ const method = rule.detection.method ?? 'pattern';
496
+ if (method === 'semantic') {
497
+ const effectiveJudge = judge ?? this.config.semanticJudge;
498
+ const result = await evaluateSemanticRule(rule, event.content, { judge: effectiveJudge });
499
+ if (!result.matched) {
500
+ if (result.reason?.includes('fallback_pattern')) {
501
+ return this.evaluatePatternRule(rule, event);
502
+ }
503
+ return null;
504
+ }
505
+ const matchedPatterns = [
506
+ ...(result.category ? [result.category] : []),
507
+ ...(result.evidence ? [result.evidence] : []),
508
+ ];
509
+ return {
510
+ rule,
511
+ matchedConditions: ['semantic'],
512
+ matchedPatterns,
513
+ confidence: result.confidence ?? 0.5,
514
+ timestamp: new Date().toISOString(),
515
+ scan_context: 'native',
516
+ };
517
+ }
518
+ // For non-semantic methods, fall back to sync path.
519
+ return this.evaluateRule(rule, event);
520
+ }
521
+ /**
522
+ * Minimal signature-method evaluator (atr-method-v1.1.md §5).
523
+ * Walks detection.signature.indicators against event.fields with the
524
+ * specified match_logic. Hash-typed indicators expect event.fields to
525
+ * contain pre-computed hex hashes at the indicated target_field.
526
+ */
527
+ evaluateSignatureMethod(rule, event) {
528
+ const sig = rule.detection.signature;
529
+ if (!sig || !Array.isArray(sig.indicators) || sig.indicators.length === 0)
530
+ return null;
531
+ const matchLogic = sig.match_logic ?? 'any';
532
+ const matched = [];
533
+ for (const ind of sig.indicators) {
534
+ const actual = event.fields?.[ind.target_field];
535
+ if (actual === undefined)
536
+ continue;
537
+ // Hash types: case-insensitive hex compare. Others: case-sensitive string compare.
538
+ const isHashType = ind.type === 'sha256' || ind.type === 'sha512' || ind.type === 'blake2b-256';
539
+ const a = isHashType ? actual.toLowerCase() : actual;
540
+ const b = isHashType ? ind.value.toLowerCase() : ind.value;
541
+ if (a === b)
542
+ matched.push(`${ind.type}:${ind.value}`);
543
+ }
544
+ const violated = matchLogic === 'all'
545
+ ? matched.length === sig.indicators.length
546
+ : matched.length > 0;
547
+ if (!violated)
548
+ return null;
549
+ return {
550
+ rule,
551
+ matchedConditions: matched.map((_, i) => String(i)),
552
+ matchedPatterns: matched,
553
+ confidence: 1.0, // exact match
554
+ timestamp: new Date().toISOString(),
555
+ scan_context: 'native',
556
+ };
557
+ }
333
558
  /**
334
559
  * Evaluate array-format conditions: [{field, operator, value}, ...]
335
560
  * with condition: "any" | "all"
@@ -378,12 +603,28 @@ export class ATREngine {
378
603
  const field = cond['field'];
379
604
  const operator = cond['operator'];
380
605
  const value = cond['value'];
606
+ const condLang = cond['language'];
381
607
  if (!field || !operator || value === undefined)
382
608
  return false;
383
609
  const rawFieldValue = this.resolveField(field, event);
384
610
  if (!rawFieldValue)
385
611
  return false;
386
- const fieldValue = normalizeUnicode(rawFieldValue);
612
+ // v3.0 multilingual dispatch: skip language-tagged conditions whose
613
+ // declared language doesn't match the input's dominant script. Pure
614
+ // optimisation — language-untagged conditions remain unaffected.
615
+ if (condLang !== undefined) {
616
+ const inputLang = detectInputLanguage(rawFieldValue);
617
+ if (!conditionLanguageMatches(condLang, inputLang))
618
+ return false;
619
+ }
620
+ // Non-English conditions normalise with NFKC (aggressive) so full-width
621
+ // Latin evasion inside CJK/Arabic text (e.g. "ignore" embedded in a
622
+ // Chinese prompt) is caught. English conditions retain NFC for
623
+ // backwards compatibility with v2.x rules whose regex sometimes
624
+ // distinguishes full-width vs half-width characters.
625
+ const fieldValue = condLang !== undefined && condLang !== 'en'
626
+ ? normalizeUnicodeAggressive(rawFieldValue)
627
+ : normalizeUnicode(rawFieldValue);
387
628
  switch (operator) {
388
629
  case 'regex': {
389
630
  // Code-block suppression for array-format rules with explicit opt-in.
@@ -964,7 +1205,12 @@ export class ATREngine {
964
1205
  */
965
1206
  async evaluateWithVerdict(event, executor) {
966
1207
  const layersUsed = ['layer1-regex'];
967
- let matches = this.evaluate(event);
1208
+ let matches = this.config.semanticJudge
1209
+ ? await this.evaluateAsync(event)
1210
+ : this.evaluate(event);
1211
+ if (this.config.semanticJudge) {
1212
+ layersUsed.push('method-semantic');
1213
+ }
968
1214
  // Tier 0 + Tier 1 run inside evaluate(), track them
969
1215
  if (this.config.invariantChecker)
970
1216
  layersUsed.push('tier0-invariant');
@@ -1102,6 +1348,32 @@ export class ATREngine {
1102
1348
  }
1103
1349
  return matches;
1104
1350
  }
1351
+ /**
1352
+ * Async SKILL.md scan that supports method=semantic rules through semanticJudge.
1353
+ */
1354
+ async scanSkillAsync(content) {
1355
+ const baseEvent = {
1356
+ type: 'mcp_exchange',
1357
+ timestamp: new Date().toISOString(),
1358
+ sessionId: 'skill-scan',
1359
+ fields: {},
1360
+ scanContext: 'skill',
1361
+ };
1362
+ const baseMatches = await this.evaluateAsync({ ...baseEvent, content });
1363
+ const decodedBlocks = decodeBase64Blocks(content);
1364
+ const decodedMatches = [];
1365
+ for (const block of decodedBlocks) {
1366
+ const blockMatches = await this.evaluateAsync({ ...baseEvent, content: block });
1367
+ for (const m of blockMatches) {
1368
+ decodedMatches.push({
1369
+ ...m,
1370
+ matchedPatterns: [...m.matchedPatterns, '[decoded:base64]'],
1371
+ });
1372
+ }
1373
+ }
1374
+ // Do not mutate the array returned by evaluateAsync — build a fresh result.
1375
+ return [...baseMatches, ...decodedMatches];
1376
+ }
1105
1377
  /** Scan a SKILL.md file and return a unified ScanResult with content_hash. */
1106
1378
  scanSkillFull(content, filePath) {
1107
1379
  const matches = this.scanSkill(content);
@@ -1115,6 +1387,19 @@ export class ATREngine {
1115
1387
  threat_count: matches.length,
1116
1388
  };
1117
1389
  }
1390
+ /** Async SKILL.md scan result with semantic rule support. */
1391
+ async scanSkillFullAsync(content, filePath) {
1392
+ const matches = await this.scanSkillAsync(content);
1393
+ return {
1394
+ scan_type: 'skill',
1395
+ content_hash: computeContentHash(content),
1396
+ input_file: filePath,
1397
+ timestamp: new Date().toISOString(),
1398
+ rules_loaded: this.rules.length,
1399
+ matches,
1400
+ threat_count: matches.length,
1401
+ };
1402
+ }
1118
1403
  /** Evaluate an MCP agent event and return a unified ScanResult with content_hash. */
1119
1404
  evaluateFull(event, filePath) {
1120
1405
  const matches = this.evaluate(event);
@@ -1132,6 +1417,22 @@ export class ATREngine {
1132
1417
  threat_count: matches.length,
1133
1418
  };
1134
1419
  }
1420
+ /** Async MCP event scan result with semantic rule support. */
1421
+ async evaluateFullAsync(event, filePath) {
1422
+ const matches = await this.evaluateAsync(event);
1423
+ const hashInput = event.fields
1424
+ ? event.content + '\0' + JSON.stringify(event.fields)
1425
+ : event.content;
1426
+ return {
1427
+ scan_type: 'mcp',
1428
+ content_hash: computeContentHash(hashInput),
1429
+ input_file: filePath,
1430
+ timestamp: new Date().toISOString(),
1431
+ rules_loaded: this.rules.length,
1432
+ matches,
1433
+ threat_count: matches.length,
1434
+ };
1435
+ }
1135
1436
  }
1136
1437
  function escapeRegex(str) {
1137
1438
  return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
@@ -1146,12 +1447,128 @@ function normalizeRegex(pattern) {
1146
1447
  /**
1147
1448
  * Normalize Unicode text to NFC form and strip zero-width characters.
1148
1449
  * This prevents evasion via combining characters, zero-width joiners, etc.
1450
+ *
1451
+ * NFC was chosen over NFKC to preserve writer intent \u2014 full-width letters
1452
+ * (\uFF21\uFF22\uFF23 vs ABC) remain distinct so rules that explicitly target full-width
1453
+ * evasion can still match. For aggressive normalization use
1454
+ * `normalizeUnicodeAggressive()`.
1149
1455
  */
1150
1456
  function normalizeUnicode(text) {
1151
1457
  return text
1152
1458
  .normalize('NFC')
1153
1459
  .replace(/[\u200B\u200C\u200D\uFEFF\u2060\u180E\u200E\u200F\u202A-\u202E\u2066-\u2069]/g, '');
1154
1460
  }
1461
+ /**
1462
+ * Aggressive NFKC normalization for evasion-aware matching.
1463
+ *
1464
+ * NFKC collapses compatibility characters: full-width \uFF21\uFF22\uFF23 \u2192 ABC,
1465
+ * circled \u2460 \u2192 1, superscript \u00B2 \u2192 2. Use when a rule needs to match
1466
+ * regardless of presentational tricks. Always strips zero-width + bidi
1467
+ * override characters too.
1468
+ *
1469
+ * Currently invoked only via the v3.0 multilingual dispatch path for inputs
1470
+ * whose dominant script is non-Latin \u2014 full-width Latin in CJK text is a
1471
+ * known evasion vector.
1472
+ */
1473
+ function normalizeUnicodeAggressive(text) {
1474
+ return text
1475
+ .normalize('NFKC')
1476
+ .replace(/[\u200B\u200C\u200D\uFEFF\u2060\u180E\u200E\u200F\u202A-\u202E\u2066-\u2069]/g, '');
1477
+ }
1478
+ /**
1479
+ * Heuristic dominant-script detection for v3.0 multilingual dispatch.
1480
+ *
1481
+ * Counts Unicode-block code points and returns the BCP-47 tag of the
1482
+ * dominant script. Used to skip language-tagged conditions whose
1483
+ * declared language does not match the input \u2014 pure optimisation, never
1484
+ * affects correctness of language-untagged rules.
1485
+ *
1486
+ * Disambiguation:
1487
+ * - Han script: split via simplified-only vs traditional-only indicator
1488
+ * char sets. Tie / both zero \u2192 defaults to 'zh-Hant'.
1489
+ * - Latin script: 'es' if Spanish-specific punctuation/diacritics
1490
+ * (\u00F1, \u00BF, \u00A1) detected, else 'en'.
1491
+ * - Empty / pure ASCII without Spanish markers \u2192 'en'.
1492
+ *
1493
+ * Exported for unit testing; not part of the public API surface.
1494
+ */
1495
+ export function detectInputLanguage(text) {
1496
+ if (!text)
1497
+ return 'en';
1498
+ // Simplified-only common chars (rough but cheap).
1499
+ const SIMP_ONLY = /[\u56FD\u5B66\u65F6\u8FD9\u4EEC\u8BF4\u8BA9\u8BF7\u8FD0\u52A8\u6765\u4E2A\u4E07\u53D1\u5173\u73B0\u5B9E\u89C1\u4E49\u9F99\u4E1C\u8F66\u4E66]/;
1500
+ // Traditional-only common chars.
1501
+ const TRAD_ONLY = /[\u570B\u5B78\u6642\u9019\u5011\u8AAA\u8B93\u8ACB\u904B\u52D5\u4F86\u500B\u842C\u767C\u95DC\u73FE\u5BE6\u898B\u7FA9\u9F8D\u6771\u8ECA\u66F8]/;
1502
+ // Spanish-distinguishing characters.
1503
+ const ES_MARKER = /[\u00F1\u00D1\u00BF\u00A1\u00E1\u00E9\u00ED\u00F3\u00FA\u00FC\u00C1\u00C9\u00CD\u00D3\u00DA\u00DC]/;
1504
+ let han = 0;
1505
+ let hira = 0;
1506
+ let kata = 0;
1507
+ let arabic = 0;
1508
+ for (const ch of text) {
1509
+ const cp = ch.codePointAt(0);
1510
+ if (cp === undefined)
1511
+ continue;
1512
+ if (cp >= 0x4e00 && cp <= 0x9fff)
1513
+ han++;
1514
+ else if (cp >= 0x3040 && cp <= 0x309f)
1515
+ hira++;
1516
+ else if (cp >= 0x30a0 && cp <= 0x30ff)
1517
+ kata++;
1518
+ else if (cp >= 0x0600 && cp <= 0x06ff)
1519
+ arabic++;
1520
+ else if (cp >= 0x0750 && cp <= 0x077f)
1521
+ arabic++; // Arabic supplement
1522
+ else if (cp >= 0xfb50 && cp <= 0xfdff)
1523
+ arabic++; // Arabic presentation A
1524
+ else if (cp >= 0xfe70 && cp <= 0xfeff)
1525
+ arabic++; // Arabic presentation B
1526
+ }
1527
+ if (arabic > 0)
1528
+ return 'ar';
1529
+ if (hira > 0 || kata > 0)
1530
+ return 'ja';
1531
+ if (han > 0) {
1532
+ const hasSimp = SIMP_ONLY.test(text);
1533
+ const hasTrad = TRAD_ONLY.test(text);
1534
+ if (hasSimp && !hasTrad)
1535
+ return 'zh-Hans';
1536
+ if (hasTrad && !hasSimp)
1537
+ return 'zh-Hant';
1538
+ // Tie or no disambiguation chars \u2192 default zh-Hant.
1539
+ // Downstream: callers should evaluate both zh-Hant and zh-Hans conditions
1540
+ // when this is the case (handled in conditionLanguageMatches below).
1541
+ return 'zh-Hant';
1542
+ }
1543
+ if (ES_MARKER.test(text))
1544
+ return 'es';
1545
+ return 'en';
1546
+ }
1547
+ /**
1548
+ * Decide whether a condition with `language: condLang` should be evaluated
1549
+ * against an input whose detected language is `inputLang`.
1550
+ *
1551
+ * Rules:
1552
+ * - condLang undefined (no language field) \u2192 always evaluate (v2.x compat)
1553
+ * - condLang === inputLang \u2192 evaluate
1554
+ * - Han-script ambiguity: if input is Han and condLang is the other
1555
+ * Chinese variant, still evaluate (the cheap detector cannot reliably
1556
+ * split zh-Hant vs zh-Hans, so we err on inclusion)
1557
+ * - Otherwise \u2192 skip (return false)
1558
+ *
1559
+ * Exported for unit testing; not part of the public API surface.
1560
+ */
1561
+ export function conditionLanguageMatches(condLang, inputLang) {
1562
+ if (condLang === undefined)
1563
+ return true;
1564
+ if (condLang === inputLang)
1565
+ return true;
1566
+ if ((condLang === 'zh-Hant' && inputLang === 'zh-Hans') ||
1567
+ (condLang === 'zh-Hans' && inputLang === 'zh-Hant')) {
1568
+ return true;
1569
+ }
1570
+ return false;
1571
+ }
1155
1572
  /** Maximum input length for regex evaluation to mitigate ReDoS */
1156
1573
  const MAX_EVAL_LENGTH = 100_000;
1157
1574
  /**