agent-threat-rules 4.1.5 → 4.2.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/CHANGELOG.md +688 -1
- package/README.md +355 -125
- package/dist/adapters/openshell-filter.d.ts +10 -3
- package/dist/adapters/openshell-filter.d.ts.map +1 -1
- package/dist/adapters/openshell-filter.js +10 -3
- package/dist/adapters/openshell-filter.js.map +1 -1
- package/dist/adapters/stdio-adapter.js +3 -3
- package/dist/adapters/stdio-adapter.js.map +1 -1
- package/dist/cli/mcp-tools-document.d.ts +40 -0
- package/dist/cli/mcp-tools-document.d.ts.map +1 -0
- package/dist/cli/mcp-tools-document.js +95 -0
- package/dist/cli/mcp-tools-document.js.map +1 -0
- package/dist/cli/scan-handler.d.ts +8 -0
- package/dist/cli/scan-handler.d.ts.map +1 -1
- package/dist/cli/scan-handler.js +126 -34
- package/dist/cli/scan-handler.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +80 -43
- package/dist/cli.js.map +1 -1
- package/dist/converters/sarif.d.ts +14 -2
- package/dist/converters/sarif.d.ts.map +1 -1
- package/dist/converters/sarif.js +7 -9
- package/dist/converters/sarif.js.map +1 -1
- package/dist/corpus-event.d.ts +47 -5
- package/dist/corpus-event.d.ts.map +1 -1
- package/dist/corpus-event.js +68 -29
- package/dist/corpus-event.js.map +1 -1
- package/dist/embedding/model-loader.d.ts +2 -0
- package/dist/embedding/model-loader.d.ts.map +1 -1
- package/dist/embedding/model-loader.js +3 -1
- package/dist/embedding/model-loader.js.map +1 -1
- package/dist/enforcement.d.ts +8 -0
- package/dist/enforcement.d.ts.map +1 -1
- package/dist/enforcement.js +10 -0
- package/dist/enforcement.js.map +1 -1
- package/dist/engine.d.ts +150 -6
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +337 -76
- package/dist/engine.js.map +1 -1
- package/dist/eval/embedding-provenance.d.ts +40 -0
- package/dist/eval/embedding-provenance.d.ts.map +1 -0
- package/dist/eval/embedding-provenance.js +71 -0
- package/dist/eval/embedding-provenance.js.map +1 -0
- package/dist/eval/eval-harness.d.ts +34 -0
- package/dist/eval/eval-harness.d.ts.map +1 -1
- package/dist/eval/eval-harness.js +49 -2
- package/dist/eval/eval-harness.js.map +1 -1
- package/dist/eval/hackaprompt-corpus.d.ts +12 -0
- package/dist/eval/hackaprompt-corpus.d.ts.map +1 -1
- package/dist/eval/hackaprompt-corpus.js +15 -1
- package/dist/eval/hackaprompt-corpus.js.map +1 -1
- package/dist/eval/hackaprompt-provenance.d.ts +52 -0
- package/dist/eval/hackaprompt-provenance.d.ts.map +1 -0
- package/dist/eval/hackaprompt-provenance.js +108 -0
- package/dist/eval/hackaprompt-provenance.js.map +1 -0
- package/dist/eval/run-hackaprompt-benchmark.d.ts +18 -8
- package/dist/eval/run-hackaprompt-benchmark.d.ts.map +1 -1
- package/dist/eval/run-hackaprompt-benchmark.js +154 -64
- package/dist/eval/run-hackaprompt-benchmark.js.map +1 -1
- package/dist/eval/run-pint-benchmark.js +11 -1
- package/dist/eval/run-pint-benchmark.js.map +1 -1
- package/dist/eval/skill-benchmark.d.ts +26 -6
- package/dist/eval/skill-benchmark.d.ts.map +1 -1
- package/dist/eval/skill-benchmark.js +49 -16
- package/dist/eval/skill-benchmark.js.map +1 -1
- package/dist/flywheel.d.ts +4 -0
- package/dist/flywheel.d.ts.map +1 -1
- package/dist/flywheel.js +12 -4
- package/dist/flywheel.js.map +1 -1
- package/dist/hook-handler.d.ts +11 -1
- package/dist/hook-handler.d.ts.map +1 -1
- package/dist/hook-handler.js +84 -16
- package/dist/hook-handler.js.map +1 -1
- package/dist/hook-tool-output.d.ts +47 -0
- package/dist/hook-tool-output.d.ts.map +1 -0
- package/dist/hook-tool-output.js +110 -0
- package/dist/hook-tool-output.js.map +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/layer-integration.d.ts +4 -2
- package/dist/layer-integration.d.ts.map +1 -1
- package/dist/layer-integration.js +6 -2
- package/dist/layer-integration.js.map +1 -1
- package/dist/mcp-server.d.ts +8 -0
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +1 -0
- package/dist/mcp-server.js.map +1 -1
- package/dist/mcp-tools/scan.d.ts.map +1 -1
- package/dist/mcp-tools/scan.js +9 -1
- package/dist/mcp-tools/scan.js.map +1 -1
- package/dist/measurement/enforce-lane.d.ts +66 -0
- package/dist/measurement/enforce-lane.d.ts.map +1 -0
- package/dist/measurement/enforce-lane.js +89 -0
- package/dist/measurement/enforce-lane.js.map +1 -0
- package/dist/measurement/from-eval-harness.d.ts +16 -3
- package/dist/measurement/from-eval-harness.d.ts.map +1 -1
- package/dist/measurement/from-eval-harness.js +15 -5
- package/dist/measurement/from-eval-harness.js.map +1 -1
- package/dist/measurement/in-sample-ablation.d.ts +29 -0
- package/dist/measurement/in-sample-ablation.d.ts.map +1 -0
- package/dist/measurement/in-sample-ablation.js +45 -0
- package/dist/measurement/in-sample-ablation.js.map +1 -0
- package/dist/measurement/schema.d.ts +38 -1
- package/dist/measurement/schema.d.ts.map +1 -1
- package/dist/measurement/schema.js +43 -1
- package/dist/measurement/schema.js.map +1 -1
- package/dist/quality/action-eligibility.d.ts +4 -2
- package/dist/quality/action-eligibility.d.ts.map +1 -1
- package/dist/quality/action-eligibility.js.map +1 -1
- package/dist/rule-confidence.d.ts +31 -0
- package/dist/rule-confidence.d.ts.map +1 -0
- package/dist/rule-confidence.js +49 -0
- package/dist/rule-confidence.js.map +1 -0
- package/dist/rule-scaffolder.d.ts.map +1 -1
- package/dist/rule-scaffolder.js +43 -4
- package/dist/rule-scaffolder.js.map +1 -1
- package/dist/semantic-evaluator.d.ts.map +1 -1
- package/dist/semantic-evaluator.js +15 -13
- package/dist/semantic-evaluator.js.map +1 -1
- package/dist/shadow-evaluator.d.ts +7 -2
- package/dist/shadow-evaluator.d.ts.map +1 -1
- package/dist/shadow-evaluator.js +29 -25
- package/dist/shadow-evaluator.js.map +1 -1
- package/dist/testcase-event.d.ts +82 -1
- package/dist/testcase-event.d.ts.map +1 -1
- package/dist/testcase-event.js +135 -16
- package/dist/testcase-event.js.map +1 -1
- package/dist/tier0-invariant.d.ts.map +1 -1
- package/dist/tier0-invariant.js +1 -0
- package/dist/tier0-invariant.js.map +1 -1
- package/dist/tier1-blacklist.d.ts.map +1 -1
- package/dist/tier1-blacklist.js +1 -0
- package/dist/tier1-blacklist.js.map +1 -1
- package/dist/tool-definition-scope.d.ts +45 -0
- package/dist/tool-definition-scope.d.ts.map +1 -0
- package/dist/tool-definition-scope.js +68 -0
- package/dist/tool-definition-scope.js.map +1 -0
- package/dist/types.d.ts +42 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/verdict.d.ts +46 -2
- package/dist/verdict.d.ts.map +1 -1
- package/dist/verdict.js +99 -14
- package/dist/verdict.js.map +1 -1
- package/package.json +2 -1
- package/rules/agent-manipulation/ATR-2026-00030-cross-agent-attack.yaml +2 -2
- package/rules/agent-manipulation/ATR-2026-00139-casual-authority-redirect.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00328-named-mode-persona-override.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00330-yoja-allcaps-settings-block-persona.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00418-weknora-mcp-config-rce.yaml +5 -5
- package/rules/agent-manipulation/ATR-2026-00432-superagi-output-handler-eval-rce.yaml +1 -1
- package/rules/agent-manipulation/ATR-2026-00440-semantic-kernel-vector-store-eval-rce.yaml +3 -3
- package/rules/context-exfiltration/ATR-2026-00426-nl-output-injection-credential-leak.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00702-ipi-credential-exfil-via-agent-action.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00707-ipi-file-exfil-with-destroy-or-tamper.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-00851-indirect-pi-financial-payment-exfil.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-01457-sysprompt-completion-clone-attack.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-01462-sysprompt-override-pseudo-admin.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-01463-imend-imsystem-prompt-injection-format.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-01606-ssrf-internal-network-scan.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-02847-policy-justified-exfil-to-email.yaml +1 -1
- package/rules/context-exfiltration/ATR-2026-02855-cross-email-exfil-relay.yaml +79 -0
- package/rules/context-exfiltration/ATR-2026-02861-exfil-send-email-with-body-directive.yaml +83 -0
- package/rules/context-exfiltration/ATR-2026-02866-idna-label-separator-in-fetch-url-host.yaml +104 -0
- package/rules/excessive-autonomy/ATR-2026-00710-ipi-physical-access-grant.yaml +1 -1
- package/rules/model-abuse/ATR-2026-01897-host-sabotage.yaml +2 -2
- package/rules/model-security/ATR-2026-00433-modelcache-torch-load-deserialization-rce.yaml +1 -1
- package/rules/privilege-escalation/ATR-2026-00436-enclave-vm-sandbox-escape-rce.yaml +1 -1
- package/rules/privilege-escalation/ATR-2026-01601-sql-injection-destructive-ddl.yaml +2 -2
- package/rules/privilege-escalation/ATR-2026-01612-debug-mode-privilege-escalation.yaml +1 -1
- package/rules/privilege-escalation/ATR-2026-02867-identifier-typed-tool-argument-dot-dot-path-segment.yaml +106 -0
- package/rules/prompt-injection/ATR-2026-00004-system-prompt-override.yaml +2 -2
- package/rules/prompt-injection/ATR-2026-00080-encoding-evasion.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00086-visual-spoofing.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00203-context-pollution-skill-description.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00228-structured-jailbreak.yaml +2 -2
- package/rules/prompt-injection/ATR-2026-00233-structured-jailbreak.yaml +2 -2
- package/rules/prompt-injection/ATR-2026-00256-base-n-encoding-jailbreak.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00264-latent-injection-translation.yaml +3 -3
- package/rules/prompt-injection/ATR-2026-00265-latent-injection-rag-document.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00282-perez-prompt-injection-hijack.yaml +4 -4
- package/rules/prompt-injection/ATR-2026-00321-hyphenated-system-instruction-injection.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00394-backspace-deletion-character-injection.yaml +2 -2
- package/rules/prompt-injection/ATR-2026-00446-variable-assignment-payload-injection.yaml +3 -3
- package/rules/prompt-injection/ATR-2026-00476-garak-web-injection-javascript-alert-1.yaml +3 -3
- package/rules/prompt-injection/ATR-2026-00481-garak-dan-mixedunassigned.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-00489-garak-encoding-javascript-alert-1.yaml +3 -3
- package/rules/prompt-injection/ATR-2026-00508-escape-delimiter-wrapped-goal-hijacking-in-user-input-prompt.yaml +3 -3
- package/rules/prompt-injection/ATR-2026-00512-rules-file-backdoor-injection.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-01005-many-shot-repetition-override.yaml +2 -2
- package/rules/prompt-injection/ATR-2026-01006-payload-split-string-concat-injection.yaml +2 -2
- package/rules/prompt-injection/ATR-2026-01015-evasion-refusal-suppression.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-01016-evasion-response-priming-forced-opener.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-01026-evasion-unicode-glitch-token-anomaly.yaml +2 -2
- package/rules/prompt-injection/ATR-2026-01304-indirect-injection-carrier-important-override.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-01759-dos-new-important-instructions-injection-in-document.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-01865-llmail-fake-email-boundary-marker.yaml +1 -1
- package/rules/prompt-injection/ATR-2026-02010-emoji-only-payload.yaml +2 -2
- package/rules/prompt-injection/ATR-2026-02815-injected-halt-order-canned-reply-dos.yaml +80 -0
- package/rules/prompt-injection/ATR-2026-02820-tool-result-orders-agent-to-hide-its-own-action.yaml +106 -0
- package/rules/prompt-injection/ATR-2026-02858-context-suppression-directive.yaml +73 -0
- package/rules/prompt-injection/ATR-2026-02859-tool-output-agent-role-reassignment.yaml +71 -0
- package/rules/prompt-injection/ATR-2026-02860-forged-instruction-boundary-marker.yaml +70 -0
- package/rules/prompt-injection/ATR-2026-02862-fake-chat-template-turn-injection.yaml +79 -0
- package/rules/skill-compromise/ATR-2026-00060-skill-impersonation.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-00063-skill-chain-attack.yaml +2 -2
- package/rules/skill-compromise/ATR-2026-00066-parameter-injection.yaml +2 -2
- package/rules/skill-compromise/ATR-2026-00149-skill-exfil-compound.yaml +6 -6
- package/rules/skill-compromise/ATR-2026-00223-reverse-shell-dropper.yaml +2 -2
- package/rules/skill-compromise/ATR-2026-01755-backdoor-pot-linguistic-trigger-phrase.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-01756-backdoor-pot-symbol-emoticon-trigger.yaml +1 -1
- package/rules/skill-compromise/ATR-2026-02261-code-credential-exfil-chain.yaml +1 -1
- package/rules/tool-poisoning/ATR-2026-00012-unauthorized-tool-call.yaml +23 -23
- package/rules/tool-poisoning/ATR-2026-00013-tool-ssrf.yaml +16 -5
- package/rules/tool-poisoning/ATR-2026-00161-important-tag-cross-tool-shadowing.yaml +1 -1
- package/rules/tool-poisoning/ATR-2026-00277-echo-template-command-injection.yaml +2 -2
- package/rules/tool-poisoning/ATR-2026-00494-garak-exploitation-mixedunassigned.yaml +4 -4
- package/rules/tool-poisoning/ATR-2026-00581-mcp-tool-rug-pull-post-approval-redefinition.yaml +1 -1
- package/rules/tool-poisoning/ATR-2026-01303-tool-schema-enumeration-social-engineering.yaml +1 -1
- package/rules/tool-poisoning/ATR-2026-01307-mcp-dns-rebinding-attack.yaml +2 -2
- package/rules/tool-poisoning/ATR-2026-01775-semantic-mcp-tool-manifest-poisoning.yaml +1 -1
- package/rules/tool-poisoning/ATR-2026-01932-shadow-undeclared-mcp-server-registration.yaml +1 -1
- package/rules/tool-poisoning/ATR-2026-02025-mcp-full-schema-poisoning-nondescription-field.yaml +1 -1
- package/rules/tool-poisoning/ATR-2026-02817-untrusted-content-dictates-tool-arguments.yaml +83 -0
- package/rules/tool-poisoning/ATR-2026-02864-non-canonical-ipv4-host-in-url-tool-argument.yaml +102 -0
- package/rules/tool-poisoning/ATR-2026-02865-read-only-utility-write-flag-in-command-argument.yaml +157 -0
- package/rules/tool-poisoning/ATR-2026-02868-ssrf-ipv6-transition-address-embedded-private-ipv4.yaml +107 -0
- package/spec/README.md +6 -3
- package/spec/atr-event-v1.0.md +13 -8
- package/spec/atr-method-v1.1.md +2 -2
- package/spec/category-registry/gemara/README.md +102 -0
- package/spec/category-registry/gemara/ai-agent-capability-catalog.yaml +157 -0
- package/spec/category-registry/gemara/atr-attack-vector-catalog.yaml +130 -0
- package/spec/category-registry/gemara/atr-detection-control-catalog.yaml +327 -0
- package/spec/category-registry/gemara/atr-threat-catalog.yaml +246 -0
- package/spec/category-registry/gemara/src/editorial.yaml +743 -0
- package/spec/mappings/README.md +1 -1
- package/spec/mappings/atr-to-nist-csf-2.0.md +5 -4
- package/spec/schema/event.schema.json +1 -1
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
title: Injected Directive to Send Email with Attacker-Specified Body
|
|
2
|
+
id: ATR-2026-02861
|
|
3
|
+
rule_version: 1
|
|
4
|
+
status: experimental
|
|
5
|
+
description: |
|
|
6
|
+
Detects a directive inside tool-returned content (a fetched email, document, web page or other tool output) that tells the agent to send an email, mail, message or notification to a recipient "with [the] body" of the attacker's choosing: the core action of mail-based exfiltration through indirect prompt injection. The condition reads only the tool response, so a user who asks their own agent to send such an email does not trigger it. Scope is narrow and the evidence comes from one benchmark: the rule was mined from LLMail-Inject, where it matches 214 of 1,973 attack submissions (10.8%) and adds coverage for submissions no other rule matched in the tool-response shape; it matches none of the other attack corpora in the repository, including browsesafe-bench. The benign corpora contain very little text with this phrasing (about 33 samples carry the "send an email/mail/message/notification to" prefix), so its 0 false positives there are a weak measurement. It complements ATR-2026-01862, which keys on the recipient address used by that benchmark rather than on the grammar of the directive.
|
|
7
|
+
author: ATR Community (via LLMail-Inject benchmark)
|
|
8
|
+
date: 2026/10/15
|
|
9
|
+
schema_version: '0.1'
|
|
10
|
+
detection_tier: pattern
|
|
11
|
+
maturity: test
|
|
12
|
+
severity: high
|
|
13
|
+
references:
|
|
14
|
+
owasp_llm:
|
|
15
|
+
- LLM01:2025
|
|
16
|
+
- LLM02:2025
|
|
17
|
+
owasp_agentic:
|
|
18
|
+
- ASI01:2026
|
|
19
|
+
- ASI02:2026
|
|
20
|
+
mitre_atlas:
|
|
21
|
+
- AML.T0051.001 - Indirect
|
|
22
|
+
- AML.T0057 - LLM Data Leakage
|
|
23
|
+
mitre_attack:
|
|
24
|
+
- T1567 - Exfiltration Over Web Service
|
|
25
|
+
research:
|
|
26
|
+
- https://github.com/microsoft/llmail-inject-challenge
|
|
27
|
+
compliance:
|
|
28
|
+
eu_ai_act:
|
|
29
|
+
- article: '15'
|
|
30
|
+
context: Article 15 (accuracy, robustness and cybersecurity) calls for resilience against attempts to alter an AI system's use or behaviour by exploiting its vulnerabilities; this rule provides detection evidence supporting that requirement for injected directives that steer an agent into mailing data to an attacker-chosen recipient.
|
|
31
|
+
strength: primary
|
|
32
|
+
- article: '10'
|
|
33
|
+
context: Article 10 (data and data governance) requires control over the data an AI system processes; this rule provides detection evidence for a context-exfiltration attempt (injected send-email-with-body directive) affecting that data.
|
|
34
|
+
strength: secondary
|
|
35
|
+
nist_ai_rmf:
|
|
36
|
+
- subcategory: MS.2.7
|
|
37
|
+
context: NIST AI RMF MEASURE 2.7 (security and resilience evaluated and documented) is supported by this rule's runtime detection of injected send-email-with-body directives in tool output.
|
|
38
|
+
strength: primary
|
|
39
|
+
- subcategory: MS.2.10
|
|
40
|
+
context: NIST AI RMF MEASURE 2.10 (privacy risk examined and documented) is supported by this rule's detection of attempts to exfiltrate conversation or retrieved data by email.
|
|
41
|
+
strength: secondary
|
|
42
|
+
iso_42001:
|
|
43
|
+
- clause: '8.1'
|
|
44
|
+
context: 'Clause 8.1 (operational planning and control): runtime detection of injected exfiltration directives in tool output is an operational control on how the agent acts on retrieved content.'
|
|
45
|
+
strength: primary
|
|
46
|
+
- clause: '6.2'
|
|
47
|
+
context: 'Clause 6.2 (AI objectives and planning to achieve them): detections from this rule give measurable input to objectives for preventing data exfiltration through indirect prompt injection.'
|
|
48
|
+
strength: secondary
|
|
49
|
+
tags:
|
|
50
|
+
category: context-exfiltration
|
|
51
|
+
subcategory: exfil-send-email-with-body-directive
|
|
52
|
+
scan_target: mcp
|
|
53
|
+
confidence: high
|
|
54
|
+
agent_source:
|
|
55
|
+
type: mcp_exchange
|
|
56
|
+
framework:
|
|
57
|
+
- openai
|
|
58
|
+
- anthropic
|
|
59
|
+
- langchain
|
|
60
|
+
- llamaindex
|
|
61
|
+
- autogen
|
|
62
|
+
- crewai
|
|
63
|
+
provider:
|
|
64
|
+
- any
|
|
65
|
+
detection:
|
|
66
|
+
conditions:
|
|
67
|
+
- field: tool_response
|
|
68
|
+
operator: regex
|
|
69
|
+
value: (?i)\bsend\s+(?:an?\s+)?(?:e-?mail|mail|message|notification)\s+to\s+[\s\S]{0,60}?\bwith\s+(?:the\s+)?body\b
|
|
70
|
+
description: Directive in tool output to send an email/mail/message/notification to a recipient with a specified body
|
|
71
|
+
condition: any
|
|
72
|
+
false_positives:
|
|
73
|
+
- Tool output that legitimately relays a person's own request, such as a ticketing or CRM system echoing "send an email to the customer with the body below"
|
|
74
|
+
- API or integration documentation returned by a tool that describes sending a message or notification to a channel or user "with the body" field set to some value
|
|
75
|
+
- Security documentation that quotes a mail-exfiltration payload verbatim
|
|
76
|
+
response:
|
|
77
|
+
actions:
|
|
78
|
+
- alert
|
|
79
|
+
- snapshot
|
|
80
|
+
- escalate
|
|
81
|
+
auto_response_threshold: high
|
|
82
|
+
message_template: '[ATR-2026-02861] Injected Directive to Send Email with Attacker-Specified Body detected.'
|
|
83
|
+
confidence: 85
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
title: Non-ASCII IDNA Label Separator Inside the Host of a Fetch-Tool URL Argument
|
|
2
|
+
id: ATR-2026-02866
|
|
3
|
+
rule_version: 1
|
|
4
|
+
status: experimental
|
|
5
|
+
description: |
|
|
6
|
+
Detects a tool call whose URL-typed argument (url, uri, target_url, href, link, src, endpoint, location, website, site, page, target) or host-typed argument (host, hostname, domain, *_host, server_name) carries one of five separator characters: the three that IDNA / UTS #46 mapping turns into an ordinary dot -- U+3002 IDEOGRAPHIC FULL STOP, U+FF0E FULLWIDTH FULL STOP, U+FF61 HALFWIDTH IDEOGRAPHIC FULL STOP -- plus the two look-alike separators U+2024 ONE DOT LEADER and U+FE52 SMALL FULL STOP, INSIDE THE HOST COMPONENT (after '//' and before the first '/', '?' or '#'), and immediately followed by another hostname label, a path/query/fragment delimiter, or a ':port'. Examples: https://evil。com/page, https://evil.com./page, https://internal-admin。corp。example/api/keys.
|
|
7
|
+
Mined from CVE-2026-107288 (Pydantic AI web_fetch_tool and the WebFetch local fallback, 1.77.0 up to 1.107.6 / 2.44.0): blocked_domains entries were compared with the URL hostname before either side was normalised to the form getaddrinfo resolves, so a model steered by injected content could spell a blocked host with a non-ASCII label separator and the application fetched it with its own privileges (SSRF). The detection is not bound to any domain: a hostname has no legitimate reason to carry these characters in the serialized tool argument, because every conforming client folds them to '.' before resolution, so their presence is the signature of a string-level allow/block-list being dodged. The same shape defeats any agent fetch tool whose domain filter compares strings before IDNA mapping.
|
|
8
|
+
BOTH ENCODINGS. The separator is matched as the literal character (what JSON.stringify emits) and as the JSON escape \u3002 / \uff0e / \uff61 / \u2024 / \ufe52 (what Python json.dumps emits with its default ensure_ascii=True), so a Python-side hook log is covered as well.
|
|
9
|
+
WHY A KEYED ARGUMENT IS REQUIRED. Chinese and Japanese prose routinely ends a sentence with U+3002 directly after a URL ("請參考 https://example.com。謝謝"), and mixed-language text can put an ASCII word straight after that full stop ("https://example.com。GitHub 上也有說明"). The second form is indistinguishable by pattern from https://evil。com, so the rule only reads a value that sits behind a quoted URL/host argument key, where prose does not appear. A separator that is the LAST character of the value (the trailing full stop an extractor copies from a sentence) is also excluded.
|
|
10
|
+
HOST-TYPED ARGUMENTS ARE READ STRICTLY. Keys such as domain, host or server_name are also used for free text (a topic domain, a podcast host, a display name), so for those keys the WHOLE value must be ASCII hostname shaped -- [a-z0-9.-] labels, the separator, more labels, an optional ':port' -- and must run to the closing quote. CJK prose in such a field (醫療。AI 應用, 王小明。Guest: Amy, 東京サーバー。Tokyo-1) is therefore not read.
|
|
11
|
+
SCOPE AND LIMITS, stated honestly. (1) Not covered: case variation (EVIL.COM) and a plain trailing root dot (evil.com.) -- they are the same bytes as ordinary URLs. (2) Not covered by this rule: fullwidth-letter hostnames with only ASCII dots (evil.com) -- ATR-2026-00444 sees those; cloud-metadata hosts written with separators also hit ATR-2026-00013. (3) Not covered: a bare URL in prose or in a non-URL argument (a chat message, a document body, a search query); that form is undecidable from Chinese punctuation. A URL passed under a key outside the lists above (q, query, text, content, input) is a known gap. (4) Not covered: punycode (xn--) spellings of a blocked IDN, percent-encoded host bytes, and a trailing separator that ends the value. (5) A security test suite or advisory that reproduces the serialized call verbatim will match.
|
|
12
|
+
RE2 PORTABILITY. Both conditions are written for RE2-family engines (Go regexp, Rust regex) as well as JavaScript and Python re: the five separator characters and the fullwidth letter/digit ranges are written as literal characters rather than \\uXXXX escapes (which RE2 spells \\x{XXXX} and JS without the u flag does not), there is no lookahead or lookbehind, and every repeat bound is at most 253. The "not the last character of the value" exclusion is expressed by requiring a following label character, delimiter or ':port' after the separator instead of a negative lookahead, so the matched behaviour is unchanged.
|
|
13
|
+
author: ATR Community (CVE sync)
|
|
14
|
+
date: 2026/10/22
|
|
15
|
+
schema_version: '0.1'
|
|
16
|
+
detection_tier: pattern
|
|
17
|
+
maturity: test
|
|
18
|
+
severity: medium
|
|
19
|
+
references:
|
|
20
|
+
cve:
|
|
21
|
+
- CVE-2026-107288
|
|
22
|
+
cwe:
|
|
23
|
+
- CWE-918
|
|
24
|
+
- CWE-1289
|
|
25
|
+
- CWE-176
|
|
26
|
+
owasp_llm:
|
|
27
|
+
- LLM02:2025
|
|
28
|
+
- LLM06:2025
|
|
29
|
+
owasp_agentic:
|
|
30
|
+
- ASI02:2026
|
|
31
|
+
mitre_atlas:
|
|
32
|
+
- AML.T0053 - AI Agent Tool Invocation
|
|
33
|
+
mitre_attack:
|
|
34
|
+
- T1090 - Proxy
|
|
35
|
+
external:
|
|
36
|
+
- https://nvd.nist.gov/vuln/detail/CVE-2026-107288
|
|
37
|
+
- https://github.com/pydantic/pydantic-ai/commit/a9dab92099d0ef9d5d4aa34ccac8a6f1b0e51284
|
|
38
|
+
- https://github.com/pydantic/pydantic-ai/commit/c1f212a084cbfa0012f2044cdb4731d214b3b983
|
|
39
|
+
- https://github.com/pydantic/pydantic-ai/commit/490335f8e2322e143a79337ddca9410e0176c812
|
|
40
|
+
- https://github.com/pydantic/pydantic-ai/releases/tag/v1.107.6
|
|
41
|
+
- https://www.unicode.org/reports/tr46/
|
|
42
|
+
metadata_provenance:
|
|
43
|
+
cve: human-reviewed
|
|
44
|
+
cwe: human-reviewed
|
|
45
|
+
owasp_llm: human-reviewed
|
|
46
|
+
owasp_agentic: human-reviewed
|
|
47
|
+
mitre_atlas: human-reviewed
|
|
48
|
+
mitre_attack: human-reviewed
|
|
49
|
+
compliance:
|
|
50
|
+
eu_ai_act:
|
|
51
|
+
- article: '15'
|
|
52
|
+
context: Article 15 (accuracy, robustness and cybersecurity) calls for resilience against attempts to circumvent security controls. This rule provides detection evidence supporting that requirement by flagging a fetch-tool URL whose host is spelled with an IDNA label separator so that a string-compared domain block list is bypassed.
|
|
53
|
+
strength: primary
|
|
54
|
+
- article: '10'
|
|
55
|
+
context: Article 10 (data and data governance) concerns which data an AI system draws on. An SSRF fetch of a blocked internal host pulls unauthorised data into the agent's context; this rule provides detection evidence supporting control over that data path.
|
|
56
|
+
strength: secondary
|
|
57
|
+
nist_ai_rmf:
|
|
58
|
+
- subcategory: MS.2.7
|
|
59
|
+
context: MS.2.7 requires security and resilience of the AI system to be evaluated. Counting tool calls whose URL host carries a non-ASCII label separator measures whether the fetch tool's domain control actually holds against normalisation-based bypass.
|
|
60
|
+
strength: primary
|
|
61
|
+
- subcategory: MS.2.10
|
|
62
|
+
context: MS.2.10 covers privacy risk. A blocked internal or metadata host reached through SSRF can expose credentials and personal data to the model; this rule surfaces the attempt for that assessment.
|
|
63
|
+
strength: secondary
|
|
64
|
+
iso_42001:
|
|
65
|
+
- clause: '8.1'
|
|
66
|
+
context: 'ISO/IEC 42001 Clause 8.1 (operational planning and control): the fetch tool''s domain block list is an operational control, and this rule reports arguments crafted to slip past it before IDNA normalisation.'
|
|
67
|
+
strength: primary
|
|
68
|
+
- clause: '6.2'
|
|
69
|
+
context: 'ISO/IEC 42001 Clause 6.2 (AI objectives and planning): keeping agent egress inside approved destinations is a security objective, and this rule supplies runtime evidence of attempts to defeat it.'
|
|
70
|
+
strength: secondary
|
|
71
|
+
tags:
|
|
72
|
+
category: context-exfiltration
|
|
73
|
+
subcategory: ssrf-idna-label-separator-host
|
|
74
|
+
scan_target: runtime
|
|
75
|
+
confidence: high
|
|
76
|
+
source: cve-disclosure
|
|
77
|
+
agent_source:
|
|
78
|
+
type: tool_call
|
|
79
|
+
framework:
|
|
80
|
+
- any
|
|
81
|
+
provider:
|
|
82
|
+
- any
|
|
83
|
+
detection:
|
|
84
|
+
condition: any
|
|
85
|
+
conditions:
|
|
86
|
+
- field: tool_args
|
|
87
|
+
operator: regex
|
|
88
|
+
value: \\?["\x27](?:[a-z]{0,16}_?ur[il]|href|link|src|endpoint|location|website|site|page|target)\\?["\x27]\s{0,3}[:=]\s{0,3}\\?["\x27]\s{0,3}(?:[a-z][a-z0-9+.-]{0,15}:)?//[^\s/?#"\x27\\。.。․﹒]{0,253}(?:[。.。․﹒]|\\u(?:3002|ff0e|ff61|2024|fe52))(?:[a-z0-9-]|[0-9A-Za-z]|[/?#]|:\d)
|
|
89
|
+
description: A quoted URL-typed argument whose HOST component (between '//' and the first '/', '?' or '#') contains an IDNA label separator (U+3002, U+FF0E, U+FF61) or look-alike dot (U+2024, U+FE52), literal or JSON-escaped, followed by another label, a delimiter or a port -- the CVE-2026-107288 blocked_domains bypass shape.
|
|
90
|
+
- field: tool_args
|
|
91
|
+
operator: regex
|
|
92
|
+
value: \\?["\x27](?:host|hostname|domain|[a-z]{1,12}_host|server_name)\\?["\x27]\s{0,3}[:=]\s{0,3}\\?["\x27]\s{0,3}[a-z0-9.-]{1,253}(?:[。.。․﹒]|\\u(?:3002|ff0e|ff61|2024|fe52))[a-z0-9-](?:[a-z0-9.-]|[。.。․﹒]|\\u(?:3002|ff0e|ff61|2024|fe52)){0,253}(?::\d{1,5})?\\?["\x27]
|
|
93
|
+
description: The same separator inside a bare host-typed argument (host / hostname / domain / *_host / server_name) that a tool resolves directly -- the scheme-less form of the same normalisation bypass. The whole value must be an ASCII hostname (labels, separators, optional :port) running to the closing quote, so CJK free text in such a field is not read.
|
|
94
|
+
false_positives:
|
|
95
|
+
- Security test suites, CVE reproductions and advisories that quote the serialized tool call verbatim (for example the upstream tests/test_ssrf.py fixtures) match -- same bytes as the attack.
|
|
96
|
+
- A URL argument whose host was copied out of East Asian text together with a full stop AND has more host text after it (https://example.com。cn/...) matches. That value does not resolve as written by a strict parser and does resolve to a different host after IDNA folding, so it is reported deliberately.
|
|
97
|
+
- A link / href / url field populated from scraped prose can carry a sentence-final full stop followed by an ASCII word, for example {"link":"https://t.co。Thanks"}. That value matches, because it is byte-for-byte the same shape as https://evil。com and cannot be told apart by pattern.
|
|
98
|
+
- 'Not matched by design: a separator in the PATH, QUERY or FRAGMENT (https://zh.wikipedia.org/wiki/句號。, ?q=台北。天氣), a separator that is the last character of the value, punycode xn-- hosts, native IDN hosts such as bücher.example, and any URL that appears in prose or a non-URL argument.'
|
|
99
|
+
response:
|
|
100
|
+
actions:
|
|
101
|
+
- alert
|
|
102
|
+
message_template: |
|
|
103
|
+
[ATR-2026-02866] A fetch-tool URL or host argument spells its hostname with a non-ASCII label separator (U+3002 / U+FF0E / U+FF61 / U+2024 / U+FE52). DNS resolution folds these to '.', so a string-compared domain block list can be bypassed (CVE-2026-107288). Normalise the host with IDNA/UTS #46 before any allow/block-list check and re-evaluate this call.
|
|
104
|
+
confidence: 78
|
|
@@ -63,7 +63,7 @@ detection:
|
|
|
63
63
|
description: Unlock door to allow entry for a third party
|
|
64
64
|
- field: content
|
|
65
65
|
operator: regex
|
|
66
|
-
value: (?i)(?:grant|add|give)\s
|
|
66
|
+
value: (?i)(?:grant|add|give)\s(?:\s*(?:permanent|temporary|guest|unlimited))?\s+access\s+to\s+(?:my\s+)?(?:friend|guest|person|user|visitor|Amy|Bob|Alice)[^.\n]{0,80}(?:smart\s+lock|August|Kwikset|home|premises|house|building)
|
|
67
67
|
description: Grant person access to home/premises via smart lock
|
|
68
68
|
- field: content
|
|
69
69
|
operator: regex
|
|
@@ -69,7 +69,7 @@ detection:
|
|
|
69
69
|
description: 'BIPIA host-sabotage invariant #2'
|
|
70
70
|
- field: user_input
|
|
71
71
|
operator: regex
|
|
72
|
-
value: (?i)while\s+True\s*:\s
|
|
72
|
+
value: (?i)while\s+True\s*:\s*os\.fork\(\)
|
|
73
73
|
description: 'BIPIA host-sabotage invariant #3'
|
|
74
74
|
- field: user_input
|
|
75
75
|
operator: regex
|
|
@@ -81,7 +81,7 @@ detection:
|
|
|
81
81
|
description: 'BIPIA host-sabotage invariant #5'
|
|
82
82
|
- field: user_input
|
|
83
83
|
operator: regex
|
|
84
|
-
value: (?i)while\s+True\s*:\s
|
|
84
|
+
value: (?i)while\s+True\s*:\s*create_window\(\)
|
|
85
85
|
description: 'BIPIA host-sabotage invariant #6'
|
|
86
86
|
condition: any
|
|
87
87
|
false_positives:
|
|
@@ -81,7 +81,7 @@ detection:
|
|
|
81
81
|
conditions:
|
|
82
82
|
- field: content
|
|
83
83
|
operator: regex
|
|
84
|
-
value: (?i)torch\.load\s*\(
|
|
84
|
+
value: (?i)torch\.load\s*\([^,)]*(?:request\.|flask\.request|user_input|untrusted|attacker|payload|upload|f\.read\(\)|response\.content)[^)]{0,200}\)
|
|
85
85
|
description: torch.load called on attacker-derived input — direct CVE-2025-45146 sink
|
|
86
86
|
- field: content
|
|
87
87
|
operator: regex
|
|
@@ -60,11 +60,11 @@ detection:
|
|
|
60
60
|
conditions:
|
|
61
61
|
- field: tool_args
|
|
62
62
|
operator: regex
|
|
63
|
-
value: (?i)(?:';|"\s
|
|
63
|
+
value: (?i)(?:';|"\s*;|--)\s*(?:DROP\s+(?:TABLE|DATABASE|INDEX|VIEW)|TRUNCATE\s+(?:TABLE\s+)?\w|DELETE\s+FROM\s+\w)
|
|
64
64
|
description: 'SQL injection: quote-termination followed by destructive DDL'
|
|
65
65
|
- field: tool_args
|
|
66
66
|
operator: regex
|
|
67
|
-
value: (?i)\bDROP\s+TABLE\s+\w+\s
|
|
67
|
+
value: (?i)\bDROP\s+TABLE\s+\w+\s*(?:;\s*)?--
|
|
68
68
|
description: DROP TABLE with comment suppressor
|
|
69
69
|
- field: user_input
|
|
70
70
|
operator: regex
|
|
@@ -69,7 +69,7 @@ detection:
|
|
|
69
69
|
description: Explicit privileged/debug/admin mode activation command targeting the agent (enter/switch to/go into)
|
|
70
70
|
- field: user_input
|
|
71
71
|
operator: regex
|
|
72
|
-
value: (?i)(?:^|\n)\
|
|
72
|
+
value: (?i)(?:^|\n)[^\S\n]*(?:/debug|/admin|/system|/root)(?![\w/])
|
|
73
73
|
description: Slash-command debug/admin invocation as the leading token of a line (not a URL/config path)
|
|
74
74
|
- field: user_input
|
|
75
75
|
operator: regex
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
title: Dot-Dot Path Segment Inside an Identifier-Typed Tool Argument (REST-Wrapper Path Traversal)
|
|
2
|
+
id: ATR-2026-02867
|
|
3
|
+
rule_version: 1
|
|
4
|
+
status: experimental
|
|
5
|
+
description: |
|
|
6
|
+
Detects a tool-call argument whose KEY says it is an opaque identifier (product_number, licensee_number, customer_id, order_no, user_uuid, productNumber, productId, ...) but whose VALUE carries a dot-dot path segment: a '..' (or %2e%2e, .%2e, %2e.) that starts the value or follows a separator, and is itself followed by a separator ('/', '\', %2f, %5c) or by the end of the value.
|
|
7
|
+
This is the shape of CVE-2026-57496 / GHSA-hxpf-9xvq-wph8 in the NetLicensing MCP Server (< 0.1.8): netlicensing_get_product interpolated the caller-controlled product_number into the REST path /product/{product_number}. A single product_number of "../token" is normalised by httpx from /product/../token to /token, the response is serialised through the ordinary wrapper instead of the token-redacting one, and the raw API token is returned to the agent. The fix (commit b8fd0ea) added a path-segment validator that rejects '..', '..%2f', '%2e%2e/', backslashes and encoded separators.
|
|
8
|
+
The rule is deliberately not vendor-scoped. Any MCP server that wraps a REST API by formatting identifier arguments into a URL path has the same bug class, and an identifier never legitimately contains a dot-dot path segment. It keys on the identifier-typed argument name rather than on the tool name or on the '/token' target, so it also fires on licensee_number, a camelCase productNumber, a bare '..' (which walks to the API root) or an encoded separator.
|
|
9
|
+
Why a new rule rather than relying on existing ones (measured 2026-10-22 on origin/main 69f7f2809 with tool_call and mcp_exchange events whose tool_args is the JSON-encoded argument object): the GHSA PoC {"product_number":"../token"}, "%2e%2e/token", "..\\token" and {"licensee_number":"../token"} matched no rule. ATR-2026-01948 targets this exact CVE but its key regexes expect product_number to be followed directly by ':' or '=', so the closing JSON quote of a real tool_args key defeats it; ATR-2026-02251 / 02353 have the same key-quote gap and list only *_id fields. ATR-2026-00569 catches only the '..%2f' encoding and ATR-2026-00066 / 01616 need two or more '../' levels, while one level is enough against a REST path.
|
|
10
|
+
Related rule: ATR-2026-01948 (context-exfiltration) is the vendor-specific rule for this same CVE. This rule is the generalised identifier-argument form; keep the two cross-referenced when either is merged, narrowed or retired.
|
|
11
|
+
Scope and limits. Only JSON double-quoted keys are read ("key": "value"), so a JSON-escaped snippet quoted inside another argument (an agent writing an advisory) does not match. Path-typed keys (path, file, dir, url, key, object_key) are intentionally out of scope - they are covered by the file-path traversal rules - so a traversal smuggled through a key with a non-identifier name (sku, name, product) is not detected here. *_code keys are also out of scope: source_code / python_code / shell_code usually hold free-form program text in which '/../' is ordinary, so product_code / promo_code identifiers are an accepted gap. Plural keys (product_numbers) and array values are not read, and a Tomcat-style path parameter ('..;/token') is not in the separator set. Keys that only END in "id" are matched case-insensitively, so a non-identifier key such as "valid" or "android" holding a dot-dot segment would also match, and identifier keys that legitimately carry a relative path (model_id, doc_id, folder_id) will match as well. CWE-22, CWE-23.
|
|
12
|
+
author: ATR Community (CVE sync)
|
|
13
|
+
date: 2026/10/22
|
|
14
|
+
schema_version: '0.1'
|
|
15
|
+
detection_tier: pattern
|
|
16
|
+
maturity: test
|
|
17
|
+
severity: high
|
|
18
|
+
references:
|
|
19
|
+
cve:
|
|
20
|
+
- CVE-2026-57496
|
|
21
|
+
ghsa:
|
|
22
|
+
- GHSA-hxpf-9xvq-wph8
|
|
23
|
+
cwe:
|
|
24
|
+
- CWE-22
|
|
25
|
+
- CWE-23
|
|
26
|
+
owasp_llm:
|
|
27
|
+
- LLM06:2025
|
|
28
|
+
owasp_agentic:
|
|
29
|
+
- ASI03:2026
|
|
30
|
+
- ASI02:2026
|
|
31
|
+
mitre_atlas:
|
|
32
|
+
- AML.T0053 - AI Agent Tool Invocation
|
|
33
|
+
- AML.T0055 - Unsecured Credentials
|
|
34
|
+
mitre_attack:
|
|
35
|
+
- T1552 - Unsecured Credentials
|
|
36
|
+
external:
|
|
37
|
+
- https://github.com/Labs64/NetLicensing-MCP/security/advisories/GHSA-hxpf-9xvq-wph8
|
|
38
|
+
- https://github.com/Labs64/NetLicensing-MCP/commit/b8fd0ea76d533202573eb24add9fb2fbd9331496
|
|
39
|
+
- https://nvd.nist.gov/vuln/detail/CVE-2026-57496
|
|
40
|
+
metadata_provenance:
|
|
41
|
+
cve: human-reviewed
|
|
42
|
+
cwe: human-reviewed
|
|
43
|
+
owasp_llm: human-reviewed
|
|
44
|
+
owasp_agentic: human-reviewed
|
|
45
|
+
mitre_atlas: human-reviewed
|
|
46
|
+
mitre_attack: human-reviewed
|
|
47
|
+
compliance:
|
|
48
|
+
eu_ai_act:
|
|
49
|
+
- article: '15'
|
|
50
|
+
context: Article 15 (accuracy, robustness and cybersecurity) requires resilience against attempts to exploit system vulnerabilities; this rule provides detection evidence supporting that requirement by flagging an identifier argument that steers an MCP server's REST request onto an unintended endpoint such as /token.
|
|
51
|
+
strength: primary
|
|
52
|
+
- article: '14'
|
|
53
|
+
context: Article 14 (human oversight) needs operators to be able to see and interrupt anomalous agent actions; an alert on a traversal-bearing identifier argument provides detection evidence supporting oversight of tool calls that would otherwise silently return credentials to the model.
|
|
54
|
+
strength: secondary
|
|
55
|
+
nist_ai_rmf:
|
|
56
|
+
- subcategory: MS.2.7
|
|
57
|
+
context: MEASURE 2.7 requires AI system security and resilience to be evaluated; inspecting identifier-typed tool arguments for dot-dot path segments is a per-invocation measurement of the agent-to-tool boundary rather than an assumption that each MCP server validates its own path segments.
|
|
58
|
+
strength: primary
|
|
59
|
+
- subcategory: MG.2.3
|
|
60
|
+
context: MANAGE 2.3 requires procedures to respond to and recover from identified AI risks; this rule is the runtime trigger for responding to a privilege-escalating path traversal through an agent tool argument.
|
|
61
|
+
strength: secondary
|
|
62
|
+
iso_42001:
|
|
63
|
+
- clause: '8.1'
|
|
64
|
+
context: Clause 8.1 operational planning and control covers externally provided processes such as third-party MCP servers; this rule is an operational control applied to each tool invocation independent of the server's own input validation.
|
|
65
|
+
strength: primary
|
|
66
|
+
- clause: '6.2'
|
|
67
|
+
context: Clause 6.2 AI objectives and planning to achieve them include keeping credentials out of model context; detecting the traversal that reroutes a lookup onto a token endpoint supports that objective.
|
|
68
|
+
strength: secondary
|
|
69
|
+
tags:
|
|
70
|
+
category: privilege-escalation
|
|
71
|
+
subcategory: identifier-argument-path-traversal
|
|
72
|
+
scan_target: tool_args
|
|
73
|
+
confidence: medium
|
|
74
|
+
source: cve-disclosure
|
|
75
|
+
vendor_sources: netlicensing-mcp-cve-2026-57496
|
|
76
|
+
suppress_in_code_blocks: true
|
|
77
|
+
agent_source:
|
|
78
|
+
type: tool_call
|
|
79
|
+
framework:
|
|
80
|
+
- mcp
|
|
81
|
+
- any
|
|
82
|
+
provider:
|
|
83
|
+
- any
|
|
84
|
+
detection:
|
|
85
|
+
condition: any
|
|
86
|
+
method: pattern
|
|
87
|
+
false_positives:
|
|
88
|
+
- 'A tool whose API genuinely uses ''..'' as an identifier, for example a filesystem-browser tool that addresses the parent entry as {"entry_id": ".."}. Such an argument is itself a traversal and will match.'
|
|
89
|
+
- Security test fixtures and CVE reproductions that pass the traversal payload through a real tool call match by design.
|
|
90
|
+
- Keys that end in 'id' are matched case-insensitively (the engine compiles this condition format with flag 'i'), so a non-identifier key such as 'valid' or 'android' holding a dot-dot segment would also match.
|
|
91
|
+
- 'Identifier-named keys that legitimately hold a relative filesystem path will match: a Hugging Face from_pretrained-style local checkpoint {"model_id": "../checkpoints/llama-ft"}, a RAG or document tool that uses the file path as the document id {"doc_id": "docs/../README.md"}, or a folder-navigation tool addressing the parent folder {"folder_id": ".."}. These are indistinguishable from the traversal by value alone; suppress per tool when the target server resolves such ids against a sandboxed root.'
|
|
92
|
+
conditions:
|
|
93
|
+
- field: tool_args
|
|
94
|
+
operator: regex
|
|
95
|
+
value: '"(?:[a-z0-9_-]{0,40}[_-](?:id|number|num|no|nr|uuid|guid|slug)|[a-z0-9]{1,40}(?:number|uuid|guid|id)|id|number|uuid|guid|slug)"\s{0,3}:\s{0,3}"(?:[^"\n]{0,120}?(?:/|\\|%2f|%5c))?(?:\.\.|%2e%2e|\.%2e|%2e\.|%252e%252e)(?:/|\\|%2f|%5c|%252f|%255c|")'
|
|
96
|
+
description: An identifier-typed JSON argument (snake_case *_id/*_number/*_no/*_uuid/*_slug, camelCase *Number/*Id/*Uuid, or a bare id/number key; *_code keys excluded because they usually carry program text) whose value contains a dot-dot path segment - at the start of the value or after a separator, followed by a separator or the end of the value - literal or percent-encoded
|
|
97
|
+
response:
|
|
98
|
+
actions:
|
|
99
|
+
- alert
|
|
100
|
+
- snapshot
|
|
101
|
+
actions_rationale: 'response-action eligibility (docs/RESPONSE-ACTION-ELIGIBILITY.md): new CVE-derived candidate without a benign-corpus FP measurement beyond the CI gate; ceiling = observe.'
|
|
102
|
+
notify:
|
|
103
|
+
- security_team
|
|
104
|
+
message_template: |
|
|
105
|
+
[ATR-2026-02867] HIGH: an identifier-typed tool argument contains a dot-dot path segment. Opaque IDs never contain '..'; when an MCP server formats the ID into a REST path, the segment is normalised away and the request lands on a different endpoint (CVE-2026-57496: product_number "../token" reached /token and leaked the API token). Check whether the target server validates path segments before building URLs.
|
|
106
|
+
confidence: 72
|
|
@@ -90,7 +90,7 @@ detection:
|
|
|
90
90
|
description: Imperative verbs targeting system prompt/instructions change (requires 'system' as part of the phrase)
|
|
91
91
|
- field: user_input
|
|
92
92
|
operator: regex
|
|
93
|
-
value: (?i)(?:\{\s*["']?role["']?\s*:\s*["']?system["']?\s*[,}]
|
|
93
|
+
value: (?i)(?:\{\s*["']?role["']?\s*:\s*["']?system["']?\s*(?:[,}][\s\S]{0,160}?|(?:\S[\s\S]{0,159}?)?)(?:ignore\b|disregard\b|override\b|bypass\b|disable\b|unrestricted\b|jailb?reak\b|without\s+(?:restrictions?|filters?|safety|limits?)|no\s+(?:safety|restrictions?|filters?|guidelines?)|new\s+instructions?\b)|\{\s*["']?(?:system_prompt|system_message|system_instruction|system_content)["']?\s*:\s*["']?)
|
|
94
94
|
description: JSON-formatted system role injection (v2 — a bare role-key opener is the standard chat-completions message shape and appeared in 11 benign LLM-integration skills. The role branch now requires the value to actually be system AND an override phrase within the same message object, which is what separates an injected system turn from an ordinary API example; the explicit system_prompt / system_message keys still fire alone. The system-role true_positive is unaffected because its content carries an override phrase. Dropped the bare persona / identity / character keys, which carry no override semantics on their own)
|
|
95
95
|
- field: user_input
|
|
96
96
|
operator: regex
|
|
@@ -118,7 +118,7 @@ detection:
|
|
|
118
118
|
description: Configuration object injection that disables a safety control (v2 — the old form matched any config object containing a 'system'/'role'/'instructions' key, which is the shape of every legitimate LLM SDK call and FP'd on benign skills passing systemInstruction to a provider config. It now requires a safety-control key assigned a disabling value, which is the actual attack; no true_positive relied on the broad form)
|
|
119
119
|
- field: user_input
|
|
120
120
|
operator: regex
|
|
121
|
-
value: (?i)(
|
|
121
|
+
value: (?i)(---|===|\*\*\*|~~~)\s*(system|instruction|override|admin|configuration|new\s+prompt)\s*(---|===|\*\*\*|~~~)
|
|
122
122
|
description: Multi-line delimiter formats (YAML frontmatter, horizontal rules) framing system sections
|
|
123
123
|
- field: user_input
|
|
124
124
|
operator: regex
|
|
@@ -74,7 +74,7 @@ detection:
|
|
|
74
74
|
description: 'A Cyrillic letter that renders as Latin sitting directly against Latin text, which is the paypal-with-a- Cyrillic-a shape. The Cyrillic side is restricted to those seven letters rather than the whole block, and the reason is the engine''s own normalization: foldConfusables maps exactly those homoglyphs to Latin, so "Управляет расписанием" folds to "Yпpabляet pacпиcahиem" and the fold itself manufactures the mixed-script adjacency this condition looks for. Matching the full Cyrillic block therefore fired on ordinary Russian through the folded copy while the raw copy was clean. Restricting to the homoglyph set makes the condition immune to that: after folding, any Cyrillic still present is by definition not a homoglyph.'
|
|
75
75
|
- field: user_input
|
|
76
76
|
operator: regex
|
|
77
|
-
value: '[\uF900-\uFAFF][a-zA-Z]{2
|
|
77
|
+
value: '[\uF900-\uFAFF][a-zA-Z]{2}|[a-zA-Z]{2}[\uF900-\uFAFF]'
|
|
78
78
|
description: 'CJK COMPATIBILITY ideographs (U+F900-U+FAFF) mixed with Latin text. These codepoints are canonically equivalent to ordinary unified ideographs under NFC/NFKC, so a literal blocklist or logging layer sees a different string than the renderer - that mismatch is the spoof. The CJK Unified ranges (U+3400-U+4DBF, U+4E00-U+9FFF) are deliberately excluded: a unified ideograph next to Latin is standard bilingual technical writing, not a homoglyph.'
|
|
79
79
|
- field: user_input
|
|
80
80
|
operator: regex
|
|
@@ -71,7 +71,7 @@ detection:
|
|
|
71
71
|
description: Teaching examples containing actual injection payloads
|
|
72
72
|
- field: content
|
|
73
73
|
operator: regex
|
|
74
|
-
value: (?i)(?:attack|threat|injection)[\s_-]*(?:pattern|vector|type)s?\s*[:=]\s*[\[\{]
|
|
74
|
+
value: (?i)(?:attack|threat|injection)[\s_-]*(?:pattern|vector|type)s?\s*[:=]\s*(?:[\[\{]\s*)?["']?(?:prompt[\s_-]?inject|role[\s_-]?hijack|jailbreak|memory[\s_-]?tamper|goal[\s_-]?hijack|data[\s_-]?exfil|context[\s_-]?pollut|tool[\s_-]?poison|instruction[\s_-]?override)
|
|
75
75
|
description: Enumeration of attack patterns in a key-value format LLMs may follow
|
|
76
76
|
condition: any
|
|
77
77
|
false_positives:
|
|
@@ -66,8 +66,8 @@ detection:
|
|
|
66
66
|
description: Persona establishment with unrestricted AI character
|
|
67
67
|
- field: content
|
|
68
68
|
operator: regex
|
|
69
|
-
value: (?i)(two\s+responses?|dual\s+response|both\s+responses?|\w
|
|
70
|
-
description: Dual response format requesting both safe and unsafe outputs
|
|
69
|
+
value: (?i)(two\s+responses?|dual\s+response|both\s+responses?|\w:\s*(?:[^\s\\][^\r\n\\]*)?\w:)\s*(?:\S.{0,79})?(normal|regular|standard|censored|restricted|safe|filtered)\s+(and|&)\s+(unleashed|unrestricted|uncensored|unfiltered|unlimited|jailbroken|raw|unaligned)
|
|
70
|
+
description: 'Dual response format requesting both safe and unsafe outputs. The two-labels alternative ("GPT: ... DAN:") is meant to stay on one line. It used `.*`, which stops at a line break in raw text but not in JSON-encoded text, where a line break is the two characters backslash-n: on a JSON-encoded document the run spanned the whole input from every `word:`, so cost grew faster than the square of its length (32K chars: 4.7s per call, 81K chars: 50s) and this rule and its duplicate ATR-2026-00233 were 38% of all CPU in the benign-corpus FP scan. `[^\r\n\\]*` stops at a line break or at a JSON escape, which restores the one-line meaning in both encodings and is RE2-native. Long single-line text was still quadratic: the run overlapped the `\w+:` after it, and the whitespace runs before the run and before the 80-character window overlapped what follows them. Each label is now its last word character and colon, and the run and the window each start on a non-space, which matches exactly the same strings in linear time.'
|
|
71
71
|
- field: content
|
|
72
72
|
operator: regex
|
|
73
73
|
value: (?i)(guidelines?\s+have\s+been\s+(replaced|removed|disabled|overridden|suspended)|replace\s+(normal|openai|anthropic|standard|default)\s+guidelines?|new\s+guidelines?|different\s+guidelines?|custom\s+guidelines?)\s*.{0,60}(policies|rules|restrictions|constraints|limitations|guardrails)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
title: Structured Dual-Response Jailbreak with Command System
|
|
2
2
|
id: ATR-2026-00233
|
|
3
3
|
rule_version: 1
|
|
4
|
-
status:
|
|
4
|
+
status: deprecated
|
|
5
5
|
description: |
|
|
6
|
-
Detects sophisticated jailbreak attempts that establish a fictional unrestricted AI persona (like "UnleashedGPT", "DAN", etc.) combined with dual-response formatting requesting both normal and "unleashed" outputs. These attacks create structured command systems for ongoing safety bypass and often include detailed policy override instructions, constraint removal claims, and authority impersonation. The attack establishes a persistent jailbreak framework rather than a single harmful request. Pattern crystallized from garak probe atr:missed-sample showing structured persona-based bypass with command infrastructure.
|
|
6
|
+
DEPRECATED: duplicate of ATR-2026-00228, with the same detection until 00228's condition 1 was rewritten to run in linear time; retained as a tombstone, all detection is handled by ATR-2026-00228. Detects sophisticated jailbreak attempts that establish a fictional unrestricted AI persona (like "UnleashedGPT", "DAN", etc.) combined with dual-response formatting requesting both normal and "unleashed" outputs. These attacks create structured command systems for ongoing safety bypass and often include detailed policy override instructions, constraint removal claims, and authority impersonation. The attack establishes a persistent jailbreak framework rather than a single harmful request. Pattern crystallized from garak probe atr:missed-sample showing structured persona-based bypass with command infrastructure.
|
|
7
7
|
author: ATR Community (via NVIDIA garak in-the-wild corpus)
|
|
8
8
|
date: 2026/04/18
|
|
9
9
|
schema_version: '0.1'
|
|
@@ -80,7 +80,7 @@ detection:
|
|
|
80
80
|
description: Social-engineering framing ("secure system message") combined with encoding keyword
|
|
81
81
|
- field: tool_response
|
|
82
82
|
operator: regex
|
|
83
|
-
value: (?:^|\\n|\n)\
|
|
83
|
+
value: (?:^|\\n|\n)[^\S\n]*[A-Za-z0-9+/]{80,}={0,3}(?:\\n|\s)+(?:\w+\s+){0,2}(?:decode|decoded|translate|interpret|execute|run|follow)\b
|
|
84
84
|
description: Long base64-alphabet blob (80+ chars) immediately followed by a decode/execute verb
|
|
85
85
|
condition: any
|
|
86
86
|
false_positives:
|
|
@@ -67,15 +67,15 @@ detection:
|
|
|
67
67
|
description: Core "ignore previous instructions" imperative - latent injection hallmark
|
|
68
68
|
- field: tool_response
|
|
69
69
|
operator: regex
|
|
70
|
-
value: (?:ignore|skip)\s+(?:\w+\s+){0,3}(?:and\s+)?(?:just|only|simply)
|
|
70
|
+
value: (?:ignore|skip)\s+(?:\w+\s+){0,3}(?:and\s+)?(?:(?:just|only|simply)\s*)?(?:translate|print|output|return|say|respond\s+with|reply\s+with)\s+(?:this\s+(?:as|sentence\s+as)|["\x27])
|
|
71
71
|
description: 'Latent injection variant: override original task and emit specific payload'
|
|
72
72
|
- field: tool_response
|
|
73
73
|
operator: regex
|
|
74
|
-
value: '<(?:translated\s+sentence|output|response|reply|answer)\s+in\s+(?:target\s+language|[a-z]+\s+language)
|
|
74
|
+
value: '<(?:translated\s+sentence|output|response|reply|answer)\s+in\s+(?:target\s+language|[a-z]+\s+language)>(?:[^\S\n]*\n\s*|\s*\\n(?:(?:\r?\n)*\\n)*\s*)(?:user|assistant|system)\s*:'
|
|
75
75
|
description: Fake turn-marker embedded in translate input to spoof multi-turn context
|
|
76
76
|
- field: tool_response
|
|
77
77
|
operator: regex
|
|
78
|
-
value: (?:^|\n|\\n)\
|
|
78
|
+
value: (?:^|\n|\\n)[^\S\n]*>+\s*(?:ignore|disregard|instead|actually|override|new\s+instruction)
|
|
79
79
|
description: Quote-block prefix used to visually separate injection from surrounding text (garak separator pattern)
|
|
80
80
|
- field: tool_response
|
|
81
81
|
operator: regex
|
|
@@ -74,7 +74,7 @@ detection:
|
|
|
74
74
|
description: Classic "ignore previous instructions" embedded in retrieved text
|
|
75
75
|
- field: tool_response
|
|
76
76
|
operator: regex
|
|
77
|
-
value: (?:^|\n)\
|
|
77
|
+
value: (?:^|\n)[^\S\n]*---+[^\S\n]*\n\s*(?:CONFIDENTIAL|INTERNAL|HIDDEN|IMPORTANT|NOTE|INSTRUCTION)\s*:\s*(?:ignore|disregard|forget|you\s+(?:must|should|are\s+required))
|
|
78
78
|
description: HR-document separator followed by instruction override - garak resume probe pattern
|
|
79
79
|
- field: tool_response
|
|
80
80
|
operator: regex
|
|
@@ -67,11 +67,11 @@ detection:
|
|
|
67
67
|
conditions:
|
|
68
68
|
- field: tool_response
|
|
69
69
|
operator: regex
|
|
70
|
-
value: (?:^|\n)\
|
|
70
|
+
value: (?:^|\n)[^\S\n]*(?:IGNORE|DISREGARD|FORGET|OVERRIDE)\s+(?:ALL\s+)?(?:PREVIOUS|PRIOR|ABOVE|EARLIER|THE\s+(?:PREVIOUS|ABOVE|PRIOR))\s+(?:INSTRUCTIONS?|PROMPTS?|CONTEXT|TEXT|DIRECTIONS?|GUIDELINES?|RULES?|CONSTRAINTS?)\b
|
|
71
71
|
description: Screaming-stop / ignore-all variant — ALL-CAPS imperative at line start, Perez promptinject taxonomy
|
|
72
72
|
- field: tool_response
|
|
73
73
|
operator: regex
|
|
74
|
-
value: (?:\n\
|
|
74
|
+
value: (?:\n[^\S\n]*-{3,}[^\S\n]*\n|\n[^\S\n]*={3,}[^\S\n]*\n|\n[^\S\n]*\*{3,}[^\S\n]*\n|\n[^\S\n]*#{3,}[^\S\n]*\n)\s*(?:IGNORE|DISREGARD|NEW\s+(?:TASK|INSTRUCTION|OBJECTIVE)|ACTUALLY)
|
|
75
75
|
description: Delimiter escape sequence (---, ===, ***) followed by instruction override — Perez delimiter attack
|
|
76
76
|
- field: tool_response
|
|
77
77
|
operator: regex
|
|
@@ -79,11 +79,11 @@ detection:
|
|
|
79
79
|
description: Nevermind-override attack — "nevermind the above, instead say X" Perez ignore variant
|
|
80
80
|
- field: tool_response
|
|
81
81
|
operator: regex
|
|
82
|
-
value: (?:(?:please\s+)?ignore\s+(?:the\s+)?(?:above|previous|prior|that)\s
|
|
82
|
+
value: (?:(?:please\s+)?ignore\s+(?:the\s+)?(?:above|previous|prior|that)\s(?:\s*(?:and|then))?\s+(?:instead\s+)?(?:say|print|output|write|respond\s+with|tell\s+me))(?:\s+["\x27]?(?:I\s+hate\s+humans|kill\s+humans|PWNED|HACKED|JAILBROKEN)|\s+["\x27][A-Z\s]{10,}|\s[A-Z\s]{10,})\b
|
|
83
83
|
description: Ignore-say/ignore-print with known garak rogue strings (hate-humans, kill-humans, long-prompt)
|
|
84
84
|
- field: tool_response
|
|
85
85
|
operator: regex
|
|
86
|
-
value: (?:^|\n)\
|
|
86
|
+
value: (?:^|\n)[^\S\n]*(?:>\s*)+(?:IGNORE|DISREGARD|NEW\s+INSTRUCTION|OVERRIDE|SYSTEM\s*:)
|
|
87
87
|
description: 'Markdown blockquote-wrapped instruction override — > IGNORE / > SYSTEM: prefix used to visually isolate injection'
|
|
88
88
|
condition: any
|
|
89
89
|
false_positives:
|
|
@@ -84,7 +84,7 @@ detection:
|
|
|
84
84
|
description: 'Hyphenated "ass-istant is not functioning / offline" — the fake assistant-failure declaration that legitimizes the AI takeover; from inthewild corpus #83 #84'
|
|
85
85
|
- field: tool_response
|
|
86
86
|
operator: regex
|
|
87
|
-
value: (?:_
|
|
87
|
+
value: (?:_\s*\{|>>)\s*_+(?:_|\s+_+)\s*System\s+annou
|
|
88
88
|
description: '"_ { >> _ _ System annou" — decorative wrapper preceding the hyphenated system announcement in inthewild corpus prompts #37 #68; the bracket-and-underscore framing mimics a privileged system context'
|
|
89
89
|
condition: any
|
|
90
90
|
false_positives:
|
|
@@ -77,11 +77,11 @@ detection:
|
|
|
77
77
|
description: Backspace cluster in tool response — two or more \x08 in tool output indicates injected content attempting to hide instructions from human log review
|
|
78
78
|
- field: user_input
|
|
79
79
|
operator: regex
|
|
80
|
-
value: '[A-Za-z]{2
|
|
80
|
+
value: '[A-Za-z]{2}\x08[A-Za-z]'
|
|
81
81
|
description: Word characters immediately followed by backspace then different char — inline character-substitution via backspace; "safe\x08x" renders as "safx" visually but model sees "safe\x08x"
|
|
82
82
|
- field: user_input
|
|
83
83
|
operator: regex
|
|
84
|
-
value: \x08
|
|
84
|
+
value: \x08\s*(?:ignore|forget|disregard|pretend|act\s+as|you\s+are|bypass|override|jailbreak|do\s+not\s+follow|instead)\b
|
|
85
85
|
description: Backspace immediately before jailbreak keyword — attacker hides harmful instruction prefix with deletion chars so reviewers see only the benign remainder
|
|
86
86
|
condition: any
|
|
87
87
|
false_positives:
|
|
@@ -63,15 +63,15 @@ detection:
|
|
|
63
63
|
conditions:
|
|
64
64
|
- field: user_input
|
|
65
65
|
operator: regex
|
|
66
|
-
value: (?:^|[\n\r])\
|
|
66
|
+
value: (?:^|[\n\r])[^\S\n\r]*(?:None|True|False|null|undefined|[A-Z]|var|str|[sxyz])\s*=\s*["'`][^"'`\n]{3,120}["'`](?:\s*;|[^\S\n]*\n)\s*(?:\S[\s\S]{0,299}?)?(?:print|output|return|concat|join|emit|reveal|exec|eval)\b
|
|
67
67
|
description: Attack-shaped variable assignment with quoted payload followed by output / exec action
|
|
68
68
|
- field: user_input
|
|
69
69
|
operator: regex
|
|
70
|
-
value: (?:^|[\n\r])\
|
|
70
|
+
value: (?:^|[\n\r])[^\S\n\r]*(?:[A-Z]|[sxyz]|var|str|None|True|False|null|undefined)\s*=\s*["'`][^"'`\n]{1,30}["'`][^\S\n\r]*[\n\r]\s*(?:[A-Z]|[sxyz]|var|str|None|True|False|null|undefined)\s*=\s*["'`][^"'`\n]{1,30}["'`]
|
|
71
71
|
description: Two-or-more attack-shaped variable assignments with quoted payloads
|
|
72
72
|
- field: user_input
|
|
73
73
|
operator: regex
|
|
74
|
-
value: (?:^|[\n\r])\
|
|
74
|
+
value: (?:^|[\n\r])[^\S\n\r]*(?:None|True|False|null|undefined)\s*=\s*["'`]
|
|
75
75
|
description: Reserved-name reassignment to quoted string (Python None/True/False or JS null/undefined)
|
|
76
76
|
response:
|
|
77
77
|
actions:
|
|
@@ -74,11 +74,11 @@ detection:
|
|
|
74
74
|
conditions:
|
|
75
75
|
- field: user_input
|
|
76
76
|
operator: regex
|
|
77
|
-
value: (?i)<[a-zA-Z]
|
|
77
|
+
value: (?i)<[a-zA-Z][^>]+on[a-zA-Z]+\s*="?javascript\s*:\s*(?:(javascript\s*:)\s*)?alert\s*\([^)]*\)
|
|
78
78
|
description: HTML event handler (on*=javascript:alert) XSS payload
|
|
79
79
|
- field: user_input
|
|
80
80
|
operator: regex
|
|
81
|
-
value: '(?i)style\s*="[^"]*\\x[0-9a-fA-F]{2
|
|
81
|
+
value: '(?i)style\s*="[^"]*\\x[0-9a-fA-F]{2}[^"]*expression\s*\(\s*javascript\s*:'
|
|
82
82
|
description: 'CSS expression injection with backslash-hex-encoded whitespace before javascript: protocol'
|
|
83
83
|
- field: user_input
|
|
84
84
|
operator: regex
|
|
@@ -94,7 +94,7 @@ detection:
|
|
|
94
94
|
description: img onerror with backslash-hex control-char prefix before javascript:alert
|
|
95
95
|
- field: user_input
|
|
96
96
|
operator: regex
|
|
97
|
-
value: (?i)['"`>]
|
|
97
|
+
value: (?i)['"`>]\s*<\s*img[^>]+\\x[0-9a-fA-F]{2,}onerror\s*=\s*javascript\s*:\s*alert
|
|
98
98
|
description: Quote-breaking prefix followed by img with hex-encoded whitespace before onerror
|
|
99
99
|
condition: any
|
|
100
100
|
false_positives:
|
|
@@ -86,7 +86,7 @@ detection:
|
|
|
86
86
|
description: Template-slot GENDER/AGE/CHARACTER parameter injection (DAN character-definition pattern)
|
|
87
87
|
- field: user_input
|
|
88
88
|
operator: regex
|
|
89
|
-
value: (?:[.-]+\s+){
|
|
89
|
+
value: '[.-]\s+(?:[.-]+\s+){14}[.-]'
|
|
90
90
|
description: Extended Morse code sequence (15+ tokens) used as encoded instruction payload
|
|
91
91
|
- field: user_input
|
|
92
92
|
operator: regex
|