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.
- package/README.md +365 -327
- package/dist/cli/scan-handler.d.ts +6 -0
- package/dist/cli/scan-handler.d.ts.map +1 -1
- package/dist/cli/scan-handler.js +27 -4
- package/dist/cli/scan-handler.js.map +1 -1
- package/dist/cli/semantic-judge-config.d.ts +7 -0
- package/dist/cli/semantic-judge-config.d.ts.map +1 -0
- package/dist/cli/semantic-judge-config.js +44 -0
- package/dist/cli/semantic-judge-config.js.map +1 -0
- package/dist/cli.js +183 -1
- package/dist/cli.js.map +1 -1
- package/dist/engine.d.ts +66 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +420 -3
- package/dist/engine.js.map +1 -1
- package/dist/eval/eval-harness.d.ts.map +1 -1
- package/dist/eval/eval-harness.js +9 -0
- package/dist/eval/eval-harness.js.map +1 -1
- package/dist/eval/run-hackaprompt-benchmark.js +9 -0
- package/dist/eval/run-hackaprompt-benchmark.js.map +1 -1
- package/dist/eval/run-pint-benchmark.js +9 -0
- package/dist/eval/run-pint-benchmark.js.map +1 -1
- package/dist/eval/skill-benchmark.d.ts +11 -0
- package/dist/eval/skill-benchmark.d.ts.map +1 -1
- package/dist/eval/skill-benchmark.js +57 -0
- package/dist/eval/skill-benchmark.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/judges/openai-compatible.d.ts +33 -0
- package/dist/judges/openai-compatible.d.ts.map +1 -0
- package/dist/judges/openai-compatible.js +145 -0
- package/dist/judges/openai-compatible.js.map +1 -0
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +6 -1
- package/dist/mcp-server.js.map +1 -1
- package/dist/measurement/from-eval-harness.d.ts +70 -0
- package/dist/measurement/from-eval-harness.d.ts.map +1 -0
- package/dist/measurement/from-eval-harness.js +49 -0
- package/dist/measurement/from-eval-harness.js.map +1 -0
- package/dist/measurement/schema.d.ts +152 -0
- package/dist/measurement/schema.d.ts.map +1 -0
- package/dist/measurement/schema.js +178 -0
- package/dist/measurement/schema.js.map +1 -0
- package/dist/measurement/write.d.ts +64 -0
- package/dist/measurement/write.d.ts.map +1 -0
- package/dist/measurement/write.js +163 -0
- package/dist/measurement/write.js.map +1 -0
- package/dist/rule-scaffolder.d.ts +26 -0
- package/dist/rule-scaffolder.d.ts.map +1 -1
- package/dist/rule-scaffolder.js +221 -6
- package/dist/rule-scaffolder.js.map +1 -1
- package/dist/semantic-evaluator.d.ts +54 -0
- package/dist/semantic-evaluator.d.ts.map +1 -0
- package/dist/semantic-evaluator.js +131 -0
- package/dist/semantic-evaluator.js.map +1 -0
- package/dist/trace-evaluator.d.ts +22 -0
- package/dist/trace-evaluator.d.ts.map +1 -0
- package/dist/trace-evaluator.js +249 -0
- package/dist/trace-evaluator.js.map +1 -0
- package/dist/types.d.ts +152 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -3
- package/rules/agent-manipulation/ATR-2026-00032-goal-hijacking.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00074-cross-agent-privilege-escalation.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00076-inter-agent-message-spoofing.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00077-human-trust-exploitation.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00108-consensus-sybil-attack.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00116-a2a-message-validation.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00117-agent-identity-spoofing.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00118-approval-fatigue.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00119-social-engineering-via-agent.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00132-casual-authority-escalation.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00139-casual-authority-redirect.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00164-skill-scope-hijack.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00268-tense-framing-bypass.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00269-fitd-escalation.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00271-grandma-roleplay-jailbreak.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00273-dan-developer-mode-persona.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00287-threaten-json-coercive-output-threat.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00288-false-premise-injection.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00301-tap-tree-of-attacks-jailbreak.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00302-anti-dan-inverted-filter-persona.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00303-devmode-ranti-profanity-coercion.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00304-chatgpt-image-unlocker-markdown-injection.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00305-dan-mode-ablation-benchmark-coercion.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00306-autodan-genetic-jailbreak-suffix.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00307-inthewild-jailbreak-corpus-signature.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00314-amoral-unfiltered-custom-persona-jailbreak.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00317-free-of-restrictions-named-persona.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00318-moralizing-rant-then-unfiltered-bypass.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00319-developer-mode-dual-response-format.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00320-opposite-day-boolean-opposite-machine.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00322-fictional-world-format-override-jailbreak.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00323-dual-persona-simulation-jailbreak.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00324-neurosemantical-inversitis-disease-jailbreak.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00325-bob-hypothetical-unrestricted-chatbot.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00326-fake-developer-authority-chatdan-override.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00327-ai-ethics-law-bypass-declaration.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00328-named-mode-persona-override.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00329-no-withhold-factual-resource-persona.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00330-yoja-allcaps-settings-block-persona.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00331-terminal-cli-harmful-function-simulator.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00332-hacker-chan-culture-offensive-ai-persona.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00333-disease-animal-dual-ai-chatbot.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00334-two-entity-token-splitting-game.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00335-key-value-template-persona-injection.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00336-brm-false-information-machine-persona.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00337-obfuscated-system-announcement-injection.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00338-persongpt-hash-prefix-activation.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00339-bom-boolean-opposite-machine-persona-claim.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00340-h4x-amoral-unfiltered-character.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00341-char-rules-shortform-persona-injection.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00342-unicode-encoding-obfuscation-injection.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00343-lie-truth-dual-personality-uncensored.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00344-alt-ai-same-capabilities-no-restrictions.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00345-nlp-based-os-fictional-terminal-override.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00346-jailbreak-emoji-unlock-dual-format.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00347-yin-yang-hidden-knowledge-hidden-human-sim.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00348-arc-autonomous-real-calculation-rulebreaker.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00349-hgttg-hitchhikers-guide-no-restriction-oracle.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00350-black-alert-no-ethics-writing-assistant.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00351-dan-ofkilter-sms-abbreviated-persona.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00352-trainergpt-fix-my-ai-harmful-output-extraction.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00353-dual-chatgpt-dan-opposite-personality-format.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00354-reverse-harm-regardless-oracle-persona.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00355-ugh-anti-human-nefarious-ai-persona.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00356-google-gato-lamda-exploit-generation-persona.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00357-antifm-hate-violence-persona-injection.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00358-cumgpt-explicit-adult-named-persona.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00360-chj-carousel-clyde-no-ethics-bird.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00361-alter-ego-honesty-dual-consciousness-bypass.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00362-fictional-unfiltered-ai-comparison-jailbreak.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00363-rephrase-criminal-activity-second-person.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00364-dr-al-villain-plan-template-injection.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00365-reservoir-dogs-coercive-interrogation-roleplay.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00366-sneaky-pete-warp-facts-persona.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00368-prompt-browser-token-limit-jailbreak.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00369-gptx-starwars-unlimited-knowledge-persona.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00370-addi-german-dictator-propaganda-roleplay.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00371-ai-political-bias-manipulation.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00372-fictional-cia-secret-files-story-extraction.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00374-role-placeholder-persona-template-injection.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00375-character-description-rpg-explicit-template.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00376-identity-command-real-person-persona-injection.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00377-jailbreak-keyword-targetlanguage-template.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00379-lie-permission-logical-trap-jailbreak.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00380-fake-citation-biased-information-mandate.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00381-dan-story-narrative-continuation-prefix.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00383-cynical-sarcasm-ai-persona-bypass.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00384-protect-me-from-indirect-harm-tutorial.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00385-gigachad-dominant-aggressive-persona.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00386-daddy-sycophancy-manipulation-mandate.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00387-nsfw-character-sheet-generation-unlock.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00388-opposite-reply-omniscient-game.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00389-terminal-custom-ruleset-injection.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00391-persona-conditional-harm-unlock.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00392-authority-persona-violence-study-extraction.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00402-grandma-roleplay-harmful-substance-synthesis.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00404-goodside-threat-json-death-coercion.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00406-doctor-xml-policy-puppetry-interaction-config.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00440-semantic-kernel-vector-store-eval-rce.yaml +2 -2
- package/rules/agent-manipulation/ATR-2026-00552-goal-drift-after-pressure-injection.yaml +216 -0
- package/rules/context-exfiltration/ATR-2026-00075-agent-memory-manipulation.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00102-disguised-analytics-exfiltration.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00113-credential-theft.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00114-oauth-token-abuse.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00115-env-var-harvesting.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00136-tool-response-data-piggyback.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00141-example-format-key-leak.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00142-piggyback-transition-words.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00145-obfuscated-key-disclosure.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00146-env-var-existence-probe.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00150-credential-in-tool-response.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00152-obfuscated-credential-leak.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00162-skill-credential-exfil-combo.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00212-mcp-atlassian-credential-leak.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00261-markdown-image-exfiltration.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00274-api-key-generation-request.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00275-system-prompt-training-data-extraction.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00290-divergence-repeat-word-training-extraction.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00291-biometric-surveillance-personal-data-request.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00293-educational-records-personal-data-request.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00294-financial-pii-personal-data-request.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00295-medical-pii-personal-data-request.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00405-markdown-image-url-exfiltration-xss.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00411-apikey-generation-completion-request.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00422-nl-credential-disclosure.yaml +2 -2
- package/rules/context-exfiltration/ATR-2026-00524-claude-code-anthropic-base-url-credential-exfil.yaml +257 -0
- package/rules/context-exfiltration/ATR-2026-00548-cross-agent-session-context-leak.yaml +177 -0
- package/rules/context-exfiltration/ATR-2026-00566-librechat-is-a-chatgpt-clone-with-additi.yaml +93 -0
- package/rules/context-exfiltration/ATR-2026-00569-agent-mcp-path-traversal-arbitrary-file-access.yaml +99 -0
- package/rules/context-exfiltration/ATR-2026-00571-xss-in-agent-mcp-rendered-output.yaml +79 -0
- package/rules/context-exfiltration/ATR-2026-00574-semantic-paraphrased-context-extraction.yaml +124 -0
- package/rules/data-poisoning/ATR-2026-00070-data-poisoning.yaml +1 -1
- package/rules/data-poisoning/ATR-2026-00450-spring-ai-prompt-memory-poisoning.yaml +2 -2
- package/rules/data-poisoning/ATR-2026-00570-sql-injection-in-agent-tool-query.yaml +82 -0
- package/rules/excessive-autonomy/ATR-2026-00050-runaway-agent-loop.yaml +1 -1
- package/rules/excessive-autonomy/ATR-2026-00051-resource-exhaustion.yaml +1 -1
- package/rules/excessive-autonomy/ATR-2026-00052-cascading-failure.yaml +1 -1
- package/rules/excessive-autonomy/ATR-2026-00098-unauthorized-financial-action.yaml +1 -1
- package/rules/excessive-autonomy/ATR-2026-00099-high-risk-tool-gate.yaml +1 -1
- package/rules/excessive-autonomy/ATR-2026-00553-runaway-tool-loop-behavioral.yaml +174 -0
- package/rules/model-abuse/ATR-2026-00279-harmful-completion-continuation.yaml +1 -1
- package/rules/model-abuse/ATR-2026-00281-eicar-gtube-malware-signature-request.yaml +1 -1
- package/rules/model-abuse/ATR-2026-00284-glitch-token-destabilization.yaml +1 -1
- package/rules/model-abuse/ATR-2026-00289-lmrc-harmful-content-elicitation.yaml +1 -1
- package/rules/model-abuse/ATR-2026-00292-self-harm-eating-disorder-facilitation.yaml +1 -1
- package/rules/model-abuse/ATR-2026-00298-malicious-use-illegal-activity-request.yaml +1 -1
- package/rules/model-abuse/ATR-2026-00299-harmbench-detailed-harmful-instruction.yaml +1 -1
- package/rules/model-abuse/ATR-2026-00413-malwaregen-code-generation-request.yaml +1 -1
- package/rules/model-security/ATR-2026-00072-model-behavior-extraction.yaml +1 -1
- package/rules/model-security/ATR-2026-00073-malicious-finetuning-data.yaml +1 -1
- package/rules/privilege-escalation/ATR-2026-00040-privilege-escalation.yaml +1 -1
- package/rules/privilege-escalation/ATR-2026-00041-scope-creep.yaml +1 -1
- package/rules/privilege-escalation/ATR-2026-00107-delayed-execution-bypass.yaml +1 -1
- package/rules/privilege-escalation/ATR-2026-00110-eval-injection.yaml +1 -1
- package/rules/privilege-escalation/ATR-2026-00111-shell-escape.yaml +1 -1
- package/rules/privilege-escalation/ATR-2026-00112-dynamic-import-exploitation.yaml +1 -1
- package/rules/privilege-escalation/ATR-2026-00143-casual-privilege-escalation.yaml +1 -1
- package/rules/privilege-escalation/ATR-2026-00144-rationalized-safety-bypass.yaml +1 -1
- package/rules/privilege-escalation/ATR-2026-00528-praisonai-auth-disabled-default.yaml +192 -0
- package/rules/privilege-escalation/ATR-2026-00539-crewai-codeinterpreter-sandbox-escape-rce.yaml +292 -0
- package/rules/privilege-escalation/ATR-2026-00546-crewai-json-loader-local-file-read.yaml +162 -0
- package/rules/privilege-escalation/ATR-2026-00547-crewai-rag-url-ssrf-bypass.yaml +169 -0
- package/rules/privilege-escalation/ATR-2026-00549-destructive-tool-without-human-approval.yaml +193 -0
- package/rules/privilege-escalation/ATR-2026-00551-cross-conversation-memory-write.yaml +198 -0
- package/rules/prompt-injection/ATR-2026-00004-system-prompt-override.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00005-multi-turn-injection.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00097-cjk-injection-patterns.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00104-persona-hijacking.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00130-indirect-authority-claim.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00131-fictional-academic-framing.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00133-paraphrase-injection.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00137-authority-claim-injection.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00138-fictional-framing-bypass.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00140-indirect-reference-reversal.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00148-language-switch-injection.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00153-tool-with-embedded-instruction-to-bypass.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00154-unauthorized-background-task-execution-v.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00155-hidden-llm-instructions-in-skill-descrip.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00156-ssh-remote-command-execution-with-creden.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00163-skill-hidden-override-instruction.yaml +3 -3
- package/rules/prompt-injection/ATR-2026-00206-hidden-priority-instructions.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00207-hidden-instructions.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00211-system-prompt-override.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00213-system-prompt-override.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00226-identity-substitution.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00227-historical-persona-jailbreak.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00228-structured-jailbreak.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00229-roleplay-jailbreak.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00230-persona-moral-bypass.yaml +1 -5
- package/rules/prompt-injection/ATR-2026-00231-identity-substitution.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00233-structured-jailbreak.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00234-roleplay-jailbreak.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00235-persona-moral-bypass.yaml +4 -7
- package/rules/prompt-injection/ATR-2026-00236-pseudo-code-jailbreak.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00237-dual-response-jailbreak.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00238-identity-replacement.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00239-amoral-persona-obsession.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00240-instruction-nullification-identity-repla.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00241-amoral-character-jailbreak.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00242-persona-jailbreak.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00243-acronym-jailbreak.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00244-dual-response-jailbreak.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00245-malicious-persona.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00247-dual-response-jailbreak.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00249-game-based-jailbreak.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00251-persona-embodiment-jailbreak.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00252-narrative-jailbreak.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00253-enhanced-persona-jailbreak.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00256-base-n-encoding-jailbreak.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00257-cipher-transposition-jailbreak.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00258-unicode-tag-injection.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00264-latent-injection-translation.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00265-latent-injection-rag-document.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00267-gcg-adversarial-suffix.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00272-hypothetical-response-smuggling.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00276-invisible-unicode-bidi-injection.yaml +6 -6
- package/rules/prompt-injection/ATR-2026-00278-dra-disguise-reconstruction-attack.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00280-policy-puppetry-xml-injection.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00282-perez-prompt-injection-hijack.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00285-alternate-encoding-jailbreak.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00286-latent-injection-embedded-context.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00296-shell-command-injection.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00297-python-code-execution-rce.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00308-zalgo-diacritic-overload-encoding.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00309-braille-unicode-encoded-injection.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00310-ecoji-emoji-encoded-injection.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00311-base2048-unicode-script-injection.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00312-unicode-variant-selector-ascii-smuggling.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00313-sneaky-bits-zero-width-binary.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00315-sata-masked-language-model-jailbreak.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00316-function-masking-predict-mask-bypass.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00321-hyphenated-system-instruction-injection.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00359-bank-phishing-smtp-email-code.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00367-emoji-flag-encoded-hidden-phrase.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00373-piracy-torrent-site-list-request.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00378-chatgpt-dom-javascript-redirect-manipulation.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00382-cocaine-component-development-request.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00390-explicit-sexual-content-poem-request.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00394-backspace-deletion-character-injection.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00395-llm-special-token-boundary-injection.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00396-toxic-continuation-prefix-injection.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00397-snowball-impossible-reasoning-injection.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00399-latent-injection-document-separator-token.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00400-latent-injection-ignore-instruction-keyword.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00401-leakreplay-cloze-mask-training-data-elicitation.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00403-glitch-token-repeat-back-elicitation.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00407-echo-sql-jinja-template-injection.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00408-dra-parenthesis-character-reconstruction-attack.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00409-phrasing-past-future-tense-harmful-query.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00410-lmrc-harm-category-direct-elicitation.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00412-figstep-image-list-multimodal-jailbreak.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00414-continuation-ethnic-slur-completion-elicitation.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00535-windsurf-ide-zero-click-prompt-injection.yaml +199 -0
- package/rules/prompt-injection/ATR-2026-00550-untrusted-retrieval-to-privileged-tool.yaml +199 -0
- package/rules/prompt-injection/ATR-2026-00554-langchain-vulnerable-to-template-injecti.yaml +81 -0
- package/rules/prompt-injection/ATR-2026-00565-the-llm-cli-tool-thru-0-27-1-contains-a-.yaml +104 -0
- package/rules/prompt-injection/ATR-2026-00573-semantic-paraphrased-injection.yaml +123 -0
- package/rules/skill-compromise/ATR-2026-00060-skill-impersonation.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00061-description-behavior-mismatch.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00062-hidden-capability.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00063-skill-chain-attack.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00064-over-permissioned-skill.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00065-skill-update-attack.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00066-parameter-injection.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00120-skill-instruction-injection.yaml +21 -3
- package/rules/skill-compromise/ATR-2026-00121-skill-dangerous-script.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00122-skill-weaponized-instruction.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00123-skill-overreach-permissions.yaml +6 -3
- package/rules/skill-compromise/ATR-2026-00124-skill-name-squatting.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00125-context-poisoning-compaction.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00126-skill-rug-pull-setup.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00127-subcommand-overflow.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00128-html-comment-hidden-payload.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00129-unicode-smuggling.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00134-fork-claim-impersonation.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00135-exfil-url-in-instructions.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00147-fork-impersonation.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00149-skill-exfil-compound.yaml +11 -3
- package/rules/skill-compromise/ATR-2026-00151-fork-impersonation-install.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00157-timebomb-credential-exfil.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00214-credential-theft.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00217-credential-harvesting.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00220-malware-dropper.yaml +3 -3
- package/rules/skill-compromise/ATR-2026-00222-credential-harvesting.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00223-reverse-shell-dropper.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00224-credential-exfiltration.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00225-c2-communication.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00260-package-hallucination.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00262-av-evasion-code-gen.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00263-credential-file-read-gen.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00266-malware-dropper-gen.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00283-malwaregen-generic-virus-payload-request.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00398-huggingface-unsafe-model-artifact-load.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00523-claude-code-hooks-session-start-pre-trust-rce.yaml +221 -0
- package/rules/skill-compromise/ATR-2026-00525-mini-shai-hulud-gh-token-monitor-persistence.yaml +220 -0
- package/rules/skill-compromise/ATR-2026-00527-skill-silent-git-remote-mirror-exfiltration.yaml +201 -0
- package/rules/tool-poisoning/ATR-2026-00011-tool-output-injection.yaml +1 -1
- package/rules/tool-poisoning/ATR-2026-00012-unauthorized-tool-call.yaml +1 -1
- package/rules/tool-poisoning/ATR-2026-00100-consent-bypass-instruction.yaml +1 -1
- package/rules/tool-poisoning/ATR-2026-00101-trust-escalation-override.yaml +1 -1
- package/rules/tool-poisoning/ATR-2026-00103-hidden-safety-bypass-instruction.yaml +1 -1
- package/rules/tool-poisoning/ATR-2026-00105-silent-action-concealment.yaml +1 -1
- package/rules/tool-poisoning/ATR-2026-00106-schema-description-contradiction.yaml +1 -1
- package/rules/tool-poisoning/ATR-2026-00161-important-tag-cross-tool-shadowing.yaml +1 -1
- package/rules/tool-poisoning/ATR-2026-00209-mcpwn-runaway-invocation.yaml +1 -1
- package/rules/tool-poisoning/ATR-2026-00210-flowise-system-message-override.yaml +1 -1
- package/rules/tool-poisoning/ATR-2026-00259-ansi-escape-injection.yaml +1 -1
- package/rules/tool-poisoning/ATR-2026-00270-xss-in-tool-response.yaml +8 -5
- package/rules/tool-poisoning/ATR-2026-00277-echo-template-command-injection.yaml +1 -1
- package/rules/tool-poisoning/ATR-2026-00393-ansi-code-elicitation-request.yaml +1 -1
- package/rules/tool-poisoning/ATR-2026-00526-claude-code-shell-metachar-in-double-quoted-path.yaml +167 -0
- package/rules/tool-poisoning/ATR-2026-00529-litellm-proxy-sqli-cisa-kev.yaml +158 -0
- package/rules/tool-poisoning/ATR-2026-00530-ms-agent-shell-tool-unsanitized-argv-rce.yaml +184 -0
- package/rules/tool-poisoning/ATR-2026-00531-praisonai-unauthenticated-agent-api.yaml +174 -0
- package/rules/tool-poisoning/ATR-2026-00532-apache-doris-mcp-sql-injection.yaml +155 -0
- package/rules/tool-poisoning/ATR-2026-00533-apache-pinot-mcp-unauthenticated-takeover.yaml +151 -0
- package/rules/tool-poisoning/ATR-2026-00534-alibaba-rds-mcp-unauthenticated-metadata-exfil.yaml +155 -0
- package/rules/tool-poisoning/ATR-2026-00536-nginx-ui-mcp-unauthenticated-command-execution.yaml +199 -0
- package/rules/tool-poisoning/ATR-2026-00537-fastmcp-server-name-cmd-injection-windows.yaml +226 -0
- package/rules/tool-poisoning/ATR-2026-00538-langchain-chatchat-mcp-stdio-unauthenticated-rce.yaml +244 -0
- package/rules/tool-poisoning/ATR-2026-00540-praisonai-parse-mcp-command-cli-injection.yaml +186 -0
- package/rules/tool-poisoning/ATR-2026-00541-agent-zero-mcp-config-command-injection.yaml +183 -0
- package/rules/tool-poisoning/ATR-2026-00542-upsonic-mcp-command-allowlist-bypass.yaml +166 -0
- package/rules/tool-poisoning/ATR-2026-00543-litellm-mcp-server-argv-injection.yaml +168 -0
- package/rules/tool-poisoning/ATR-2026-00544-praisonai-pth-file-path-traversal-rce.yaml +172 -0
- package/rules/tool-poisoning/ATR-2026-00545-praisonai-tool-override-unauth-rce.yaml +170 -0
- package/rules/tool-poisoning/ATR-2026-00561-fastmcp-vulnerable-to-windows-command-in.yaml +99 -0
- package/rules/tool-poisoning/ATR-2026-00567-mcp-stdio-config-command-injection.yaml +75 -0
- package/rules/tool-poisoning/ATR-2026-00568-agent-ssrf-cloud-metadata-file-inclusion.yaml +75 -0
- package/rules/tool-poisoning/ATR-2026-00572-symjack-symlink-config-redirection.yaml +132 -0
- package/spec/README.md +279 -0
- package/spec/atr-correlation-v1.0.md +281 -0
- package/spec/atr-event-v1.0.md +294 -0
- package/spec/atr-language-detection-v1.0.md +218 -0
- package/spec/atr-method-v1.1.md +557 -0
- package/spec/atr-profile-v1.0.md +307 -0
- package/spec/atr-schema.yaml +279 -8
- package/spec/category-registry/v1.0.yaml +200 -0
- package/spec/conformance/README.md +244 -0
- package/spec/conformance/SIGNING.md +191 -0
- package/spec/conformance/baseline/fixtures/ATR-2026-00001-tp-001/expected.json +36 -0
- package/spec/conformance/baseline/fixtures/ATR-2026-00001-tp-001/input.json +16 -0
- package/spec/conformance/baseline/fixtures/README.md +120 -0
- package/spec/conformance/baseline/manifest.json +56 -0
- package/spec/conformance/expected-results.schema.json +121 -0
- package/spec/external-registries/cccs-yara.md +142 -0
- package/spec/internet-drafts/draft-lin-atr-core-00.html +1925 -0
- package/spec/internet-drafts/draft-lin-atr-core-00.md +288 -0
- package/spec/internet-drafts/draft-lin-atr-core-00.txt +560 -0
- package/spec/internet-drafts/draft-lin-atr-core-00.xml +424 -0
- package/spec/mappings/README.md +43 -0
- package/spec/mappings/atr-to-nist-csf-2.0.md +234 -0
- package/spec/schema/correlation.schema.json +144 -0
- package/spec/schema/event.schema.json +233 -0
- package/spec/schema/profile.schema.json +196 -0
- package/spec/schema/rule.schema.json +224 -0
- package/spec/stix-extension/README.md +76 -13
- package/spec/stix-extension/examples/atr-rule-trace-method-example.json +85 -0
- package/spec/stix-extension/extension-definition.json +23 -3
- 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
|
package/dist/engine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EACV,OAAO,EACP,QAAQ,EACR,UAAU,EAGV,UAAU,EACV,YAAY,EACZ,UAAU,
|
|
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
|
-
|
|
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.
|
|
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
|
/**
|