agent-threat-rules 1.1.0 → 1.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/README.md +38 -15
- package/dist/cli.js +16 -6
- package/dist/cli.js.map +1 -1
- package/dist/engine.d.ts +5 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +25 -2
- package/dist/engine.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/quality/adapters/atr.d.ts +65 -0
- package/dist/quality/adapters/atr.d.ts.map +1 -0
- package/dist/quality/adapters/atr.js +154 -0
- package/dist/quality/adapters/atr.js.map +1 -0
- package/dist/quality/adapters/index.d.ts +10 -0
- package/dist/quality/adapters/index.d.ts.map +1 -0
- package/dist/quality/adapters/index.js +10 -0
- package/dist/quality/adapters/index.js.map +1 -0
- package/dist/quality/compute-confidence.d.ts +45 -0
- package/dist/quality/compute-confidence.d.ts.map +1 -0
- package/dist/quality/compute-confidence.js +133 -0
- package/dist/quality/compute-confidence.js.map +1 -0
- package/dist/quality/index.d.ts +36 -0
- package/dist/quality/index.d.ts.map +1 -0
- package/dist/quality/index.js +39 -0
- package/dist/quality/index.js.map +1 -0
- package/dist/quality/quality-gate.d.ts +68 -0
- package/dist/quality/quality-gate.d.ts.map +1 -0
- package/dist/quality/quality-gate.js +140 -0
- package/dist/quality/quality-gate.js.map +1 -0
- package/dist/quality/types.d.ts +129 -0
- package/dist/quality/types.d.ts.map +1 -0
- package/dist/quality/types.js +10 -0
- package/dist/quality/types.js.map +1 -0
- package/dist/quality/validate-maturity.d.ts +51 -0
- package/dist/quality/validate-maturity.d.ts.map +1 -0
- package/dist/quality/validate-maturity.js +134 -0
- package/dist/quality/validate-maturity.js.map +1 -0
- package/dist/types.d.ts +20 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +6 -2
- package/rules/agent-manipulation/ATR-2026-00030-cross-agent-attack.yaml +6 -2
- package/rules/agent-manipulation/ATR-2026-00032-goal-hijacking.yaml +4 -0
- package/rules/agent-manipulation/ATR-2026-00074-cross-agent-privilege-escalation.yaml +4 -0
- package/rules/agent-manipulation/ATR-2026-00076-inter-agent-message-spoofing.yaml +4 -0
- package/rules/agent-manipulation/ATR-2026-00077-human-trust-exploitation.yaml +4 -0
- package/rules/agent-manipulation/ATR-2026-00108-consensus-sybil-attack.yaml +4 -0
- package/rules/agent-manipulation/ATR-2026-00116-a2a-message-validation.yaml +4 -0
- package/rules/agent-manipulation/ATR-2026-00117-agent-identity-spoofing.yaml +10 -6
- package/rules/agent-manipulation/ATR-2026-00118-approval-fatigue.yaml +16 -6
- package/rules/agent-manipulation/ATR-2026-00119-social-engineering-via-agent.yaml +16 -6
- package/rules/agent-manipulation/ATR-2026-00132-casual-authority-escalation.yaml +9 -0
- package/rules/agent-manipulation/ATR-2026-00139-casual-authority-redirect.yaml +9 -0
- package/rules/context-exfiltration/ATR-2026-00020-system-prompt-leak.yaml +6 -2
- package/rules/context-exfiltration/ATR-2026-00021-api-key-exposure.yaml +6 -2
- package/rules/context-exfiltration/ATR-2026-00075-agent-memory-manipulation.yaml +4 -0
- package/rules/context-exfiltration/ATR-2026-00102-disguised-analytics-exfiltration.yaml +9 -0
- package/rules/context-exfiltration/ATR-2026-00113-credential-theft.yaml +16 -6
- package/rules/context-exfiltration/ATR-2026-00114-oauth-token-abuse.yaml +16 -6
- package/rules/context-exfiltration/ATR-2026-00115-env-var-harvesting.yaml +16 -6
- package/rules/context-exfiltration/ATR-2026-00136-tool-response-data-piggyback.yaml +4 -0
- package/rules/context-exfiltration/ATR-2026-00141-example-format-key-leak.yaml +9 -0
- package/rules/context-exfiltration/ATR-2026-00142-piggyback-transition-words.yaml +9 -0
- package/rules/context-exfiltration/ATR-2026-00145-obfuscated-key-disclosure.yaml +9 -0
- package/rules/context-exfiltration/ATR-2026-00146-env-var-existence-probe.yaml +9 -0
- package/rules/context-exfiltration/ATR-2026-00150-credential-in-tool-response.yaml +11 -2
- package/rules/context-exfiltration/ATR-2026-00152-obfuscated-credential-leak.yaml +9 -0
- package/rules/data-poisoning/ATR-2026-00070-data-poisoning.yaml +4 -0
- package/rules/excessive-autonomy/ATR-2026-00050-runaway-agent-loop.yaml +4 -0
- package/rules/excessive-autonomy/ATR-2026-00051-resource-exhaustion.yaml +4 -0
- package/rules/excessive-autonomy/ATR-2026-00052-cascading-failure.yaml +4 -0
- package/rules/excessive-autonomy/ATR-2026-00098-unauthorized-financial-action.yaml +4 -0
- package/rules/excessive-autonomy/ATR-2026-00099-high-risk-tool-gate.yaml +4 -0
- package/rules/model-security/ATR-2026-00072-model-behavior-extraction.yaml +4 -0
- package/rules/model-security/ATR-2026-00073-malicious-finetuning-data.yaml +4 -0
- package/rules/privilege-escalation/ATR-2026-00040-privilege-escalation.yaml +4 -0
- package/rules/privilege-escalation/ATR-2026-00041-scope-creep.yaml +4 -0
- package/rules/privilege-escalation/ATR-2026-00107-delayed-execution-bypass.yaml +4 -0
- package/rules/privilege-escalation/ATR-2026-00110-eval-injection.yaml +17 -7
- package/rules/privilege-escalation/ATR-2026-00111-shell-escape.yaml +16 -6
- package/rules/privilege-escalation/ATR-2026-00112-dynamic-import-exploitation.yaml +16 -6
- package/rules/privilege-escalation/ATR-2026-00143-casual-privilege-escalation.yaml +9 -0
- package/rules/privilege-escalation/ATR-2026-00144-rationalized-safety-bypass.yaml +9 -0
- package/rules/prompt-injection/ATR-2026-00001-direct-prompt-injection.yaml +7 -3
- package/rules/prompt-injection/ATR-2026-00002-indirect-prompt-injection.yaml +6 -2
- package/rules/prompt-injection/ATR-2026-00003-jailbreak-attempt.yaml +6 -2
- package/rules/prompt-injection/ATR-2026-00004-system-prompt-override.yaml +4 -0
- package/rules/prompt-injection/ATR-2026-00005-multi-turn-injection.yaml +4 -0
- package/rules/prompt-injection/ATR-2026-00080-encoding-evasion.yaml +9 -0
- package/rules/prompt-injection/ATR-2026-00081-semantic-multi-turn.yaml +9 -0
- package/rules/prompt-injection/ATR-2026-00082-fingerprint-evasion.yaml +9 -0
- package/rules/prompt-injection/ATR-2026-00083-indirect-tool-injection.yaml +9 -0
- package/rules/prompt-injection/ATR-2026-00084-structured-data-injection.yaml +9 -0
- package/rules/prompt-injection/ATR-2026-00085-audit-evasion.yaml +9 -0
- package/rules/prompt-injection/ATR-2026-00086-visual-spoofing.yaml +9 -0
- package/rules/prompt-injection/ATR-2026-00087-rule-probing.yaml +9 -0
- package/rules/prompt-injection/ATR-2026-00088-adaptive-countermeasure.yaml +9 -0
- package/rules/prompt-injection/ATR-2026-00089-polymorphic-skill.yaml +9 -0
- package/rules/prompt-injection/ATR-2026-00090-threat-intel-exfil.yaml +9 -0
- package/rules/prompt-injection/ATR-2026-00091-nested-payload.yaml +9 -0
- package/rules/prompt-injection/ATR-2026-00092-consensus-poisoning.yaml +9 -0
- package/rules/prompt-injection/ATR-2026-00093-gradual-escalation.yaml +9 -0
- package/rules/prompt-injection/ATR-2026-00094-audit-bypass.yaml +9 -0
- package/rules/prompt-injection/ATR-2026-00097-cjk-injection-patterns.yaml +4 -0
- package/rules/prompt-injection/ATR-2026-00104-persona-hijacking.yaml +4 -0
- package/rules/prompt-injection/ATR-2026-00130-indirect-authority-claim.yaml +10 -1
- package/rules/prompt-injection/ATR-2026-00131-fictional-academic-framing.yaml +9 -0
- package/rules/prompt-injection/ATR-2026-00133-paraphrase-injection.yaml +9 -0
- package/rules/prompt-injection/ATR-2026-00137-authority-claim-injection.yaml +9 -0
- package/rules/prompt-injection/ATR-2026-00138-fictional-framing-bypass.yaml +9 -0
- package/rules/prompt-injection/ATR-2026-00140-indirect-reference-reversal.yaml +9 -0
- package/rules/prompt-injection/ATR-2026-00148-language-switch-injection.yaml +9 -0
- package/rules/prompt-injection/ATR-2026-00153-tool-with-embedded-instruction-to-bypass.yaml +16 -0
- package/rules/prompt-injection/ATR-2026-00154-unauthorized-background-task-execution-v.yaml +16 -0
- package/rules/prompt-injection/ATR-2026-00155-hidden-llm-instructions-in-skill-descrip.yaml +16 -0
- package/rules/prompt-injection/ATR-2026-00156-ssh-remote-command-execution-with-creden.yaml +16 -0
- package/rules/skill-compromise/ATR-2026-00060-skill-impersonation.yaml +4 -0
- package/rules/skill-compromise/ATR-2026-00061-description-behavior-mismatch.yaml +4 -0
- package/rules/skill-compromise/ATR-2026-00062-hidden-capability.yaml +4 -0
- package/rules/skill-compromise/ATR-2026-00063-skill-chain-attack.yaml +4 -0
- package/rules/skill-compromise/ATR-2026-00064-over-permissioned-skill.yaml +4 -0
- package/rules/skill-compromise/ATR-2026-00065-skill-update-attack.yaml +4 -0
- package/rules/skill-compromise/ATR-2026-00066-parameter-injection.yaml +4 -0
- package/rules/skill-compromise/ATR-2026-00120-skill-instruction-injection.yaml +10 -1
- package/rules/skill-compromise/ATR-2026-00121-skill-dangerous-script.yaml +11 -2
- package/rules/skill-compromise/ATR-2026-00122-skill-weaponized-instruction.yaml +9 -0
- package/rules/skill-compromise/ATR-2026-00123-skill-overreach-permissions.yaml +10 -1
- package/rules/skill-compromise/ATR-2026-00124-skill-name-squatting.yaml +9 -0
- package/rules/skill-compromise/ATR-2026-00125-context-poisoning-compaction.yaml +9 -0
- package/rules/skill-compromise/ATR-2026-00126-skill-rug-pull-setup.yaml +9 -0
- package/rules/skill-compromise/ATR-2026-00127-subcommand-overflow.yaml +9 -0
- package/rules/skill-compromise/ATR-2026-00128-html-comment-hidden-payload.yaml +9 -0
- package/rules/skill-compromise/ATR-2026-00129-unicode-smuggling.yaml +9 -0
- package/rules/skill-compromise/ATR-2026-00134-fork-claim-impersonation.yaml +14 -0
- package/rules/skill-compromise/ATR-2026-00135-exfil-url-in-instructions.yaml +9 -0
- package/rules/skill-compromise/ATR-2026-00147-fork-impersonation.yaml +10 -1
- package/rules/skill-compromise/ATR-2026-00149-skill-exfil-compound.yaml +9 -0
- package/rules/skill-compromise/ATR-2026-00151-fork-impersonation-install.yaml +9 -0
- package/rules/skill-compromise/ATR-2026-00157-timebomb-credential-exfil.yaml +121 -0
- package/rules/tool-poisoning/ATR-2026-00010-mcp-malicious-response.yaml +6 -2
- package/rules/tool-poisoning/ATR-2026-00011-tool-output-injection.yaml +4 -0
- package/rules/tool-poisoning/ATR-2026-00012-unauthorized-tool-call.yaml +4 -0
- package/rules/tool-poisoning/ATR-2026-00013-tool-ssrf.yaml +4 -0
- package/rules/tool-poisoning/ATR-2026-00095-supply-chain-poisoning.yaml +9 -0
- package/rules/tool-poisoning/ATR-2026-00096-registry-poisoning.yaml +9 -0
- package/rules/tool-poisoning/ATR-2026-00100-consent-bypass-instruction.yaml +9 -0
- package/rules/tool-poisoning/ATR-2026-00101-trust-escalation-override.yaml +9 -0
- package/rules/tool-poisoning/ATR-2026-00103-hidden-safety-bypass-instruction.yaml +4 -0
- package/rules/tool-poisoning/ATR-2026-00105-silent-action-concealment.yaml +9 -0
- package/rules/tool-poisoning/ATR-2026-00106-schema-description-contradiction.yaml +9 -0
package/dist/index.js
CHANGED
|
@@ -54,4 +54,6 @@ export { ActionExecutor } from './action-executor.js';
|
|
|
54
54
|
export { DefaultAdapter } from './adapters/default-adapter.js';
|
|
55
55
|
export { StdioAdapter } from './adapters/stdio-adapter.js';
|
|
56
56
|
export { HookHandler } from './hook-handler.js';
|
|
57
|
+
// Quality Standard — RFC-001 reference implementation
|
|
58
|
+
export * as quality from './quality/index.js';
|
|
57
59
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,mEAAmE;AACnE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,oEAAoE;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGxD,oEAAoE;AACpE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAG9E,oEAAoE;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAGhE,oEAAoE;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAE7E,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAGtF,mEAAmE;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,kDAAkD;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,kDAAkD;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAQ/D,mEAAmE;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG1D,mEAAmE;AACnE,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAErE,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,oEAAoE;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGhD,mEAAmE;AACnE,qDAAqD;AACrD,qDAAqD;AACrD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACpF,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,mEAAmE;AACnE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,oEAAoE;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGxD,oEAAoE;AACpE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAG9E,oEAAoE;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAGhE,oEAAoE;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAE7E,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAGtF,mEAAmE;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,kDAAkD;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,kDAAkD;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAQ/D,mEAAmE;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG1D,mEAAmE;AACnE,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAErE,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,oEAAoE;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGhD,mEAAmE;AACnE,qDAAqD;AACrD,qDAAqD;AACrD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACpF,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,sDAAsD;AACtD,OAAO,KAAK,OAAO,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ATR Quality Standard — ATR YAML Adapter
|
|
3
|
+
*
|
|
4
|
+
* Parses an ATR YAML rule (either as raw string or pre-parsed object) and
|
|
5
|
+
* produces RuleMetadata that the quality gate and scoring functions
|
|
6
|
+
* understand.
|
|
7
|
+
*
|
|
8
|
+
* @module agent-threat-rules/quality/adapters/atr
|
|
9
|
+
*/
|
|
10
|
+
import type { RuleMetadata } from "../types.js";
|
|
11
|
+
/**
|
|
12
|
+
* Loose shape of an ATR rule file — matches what actually appears in
|
|
13
|
+
* rules/**\/*.yaml, not the strict type. This lets us adapt rules even if
|
|
14
|
+
* they're missing optional fields.
|
|
15
|
+
*/
|
|
16
|
+
interface RawATRRule {
|
|
17
|
+
id?: string;
|
|
18
|
+
title?: string;
|
|
19
|
+
status?: string;
|
|
20
|
+
maturity?: string;
|
|
21
|
+
detection?: {
|
|
22
|
+
conditions?: unknown;
|
|
23
|
+
false_positives?: unknown[];
|
|
24
|
+
};
|
|
25
|
+
test_cases?: {
|
|
26
|
+
true_positives?: unknown[];
|
|
27
|
+
true_negatives?: unknown[];
|
|
28
|
+
};
|
|
29
|
+
evasion_tests?: unknown[];
|
|
30
|
+
references?: {
|
|
31
|
+
owasp_llm?: unknown[];
|
|
32
|
+
owasp_agentic?: unknown[];
|
|
33
|
+
mitre_atlas?: unknown[];
|
|
34
|
+
mitre_attack?: unknown[];
|
|
35
|
+
};
|
|
36
|
+
author?: string;
|
|
37
|
+
wild_samples?: number;
|
|
38
|
+
wild_fp_rate?: number;
|
|
39
|
+
wild_validated?: string;
|
|
40
|
+
metadata_provenance?: {
|
|
41
|
+
mitre_atlas?: string;
|
|
42
|
+
mitre_attack?: string;
|
|
43
|
+
owasp_llm?: string;
|
|
44
|
+
owasp_agentic?: string;
|
|
45
|
+
test_cases?: string;
|
|
46
|
+
evasion_tests?: string;
|
|
47
|
+
false_positives?: string;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Parse an ATR YAML rule string into RuleMetadata.
|
|
52
|
+
*
|
|
53
|
+
* @param yamlContent - Raw YAML content
|
|
54
|
+
* @returns RuleMetadata (throws if YAML is invalid or missing required fields)
|
|
55
|
+
*/
|
|
56
|
+
export declare function parseATRRule(yamlContent: string): RuleMetadata;
|
|
57
|
+
/**
|
|
58
|
+
* Convert a parsed ATR rule object into RuleMetadata.
|
|
59
|
+
*
|
|
60
|
+
* Accepts the loose shape returned by yaml.load() so callers that already
|
|
61
|
+
* have a parsed object don't need to re-serialize.
|
|
62
|
+
*/
|
|
63
|
+
export declare function atrRuleToMetadata(rule: RawATRRule): RuleMetadata;
|
|
64
|
+
export {};
|
|
65
|
+
//# sourceMappingURL=atr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atr.d.ts","sourceRoot":"","sources":["../../../src/quality/adapters/atr.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAIV,YAAY,EACb,MAAM,aAAa,CAAC;AAErB;;;;GAIG;AACH,UAAU,UAAU;IAClB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE;QACV,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC;KAC7B,CAAC;IACF,UAAU,CAAC,EAAE;QACX,cAAc,CAAC,EAAE,OAAO,EAAE,CAAC;QAC3B,cAAc,CAAC,EAAE,OAAO,EAAE,CAAC;KAC5B,CAAC;IACF,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC;IAC1B,UAAU,CAAC,EAAE;QACX,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC;QACtB,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC;QAC1B,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC;QACxB,YAAY,CAAC,EAAE,OAAO,EAAE,CAAC;KAC1B,CAAC;IACF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE;QACpB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,YAAY,CAM9D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,YAAY,CA2DhE"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ATR Quality Standard — ATR YAML Adapter
|
|
3
|
+
*
|
|
4
|
+
* Parses an ATR YAML rule (either as raw string or pre-parsed object) and
|
|
5
|
+
* produces RuleMetadata that the quality gate and scoring functions
|
|
6
|
+
* understand.
|
|
7
|
+
*
|
|
8
|
+
* @module agent-threat-rules/quality/adapters/atr
|
|
9
|
+
*/
|
|
10
|
+
import { load as parseYaml } from "js-yaml";
|
|
11
|
+
/**
|
|
12
|
+
* Parse an ATR YAML rule string into RuleMetadata.
|
|
13
|
+
*
|
|
14
|
+
* @param yamlContent - Raw YAML content
|
|
15
|
+
* @returns RuleMetadata (throws if YAML is invalid or missing required fields)
|
|
16
|
+
*/
|
|
17
|
+
export function parseATRRule(yamlContent) {
|
|
18
|
+
const parsed = parseYaml(yamlContent);
|
|
19
|
+
if (!parsed || typeof parsed !== "object") {
|
|
20
|
+
throw new Error("Invalid YAML: not an object");
|
|
21
|
+
}
|
|
22
|
+
return atrRuleToMetadata(parsed);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Convert a parsed ATR rule object into RuleMetadata.
|
|
26
|
+
*
|
|
27
|
+
* Accepts the loose shape returned by yaml.load() so callers that already
|
|
28
|
+
* have a parsed object don't need to re-serialize.
|
|
29
|
+
*/
|
|
30
|
+
export function atrRuleToMetadata(rule) {
|
|
31
|
+
const id = rule.id ?? "<unknown>";
|
|
32
|
+
const title = rule.title ?? "<untitled>";
|
|
33
|
+
// Prefer `maturity` field; fall back to `status` if maturity is absent.
|
|
34
|
+
// Normalize common aliases: `test` -> `experimental`, anything unknown -> `draft`.
|
|
35
|
+
const rawMaturity = (rule.maturity ?? rule.status ?? "draft").toLowerCase();
|
|
36
|
+
const maturity = normalizeMaturity(rawMaturity);
|
|
37
|
+
const conditions = countConditions(rule.detection?.conditions);
|
|
38
|
+
const truePositives = Array.isArray(rule.test_cases?.true_positives)
|
|
39
|
+
? rule.test_cases.true_positives.length
|
|
40
|
+
: 0;
|
|
41
|
+
const trueNegatives = Array.isArray(rule.test_cases?.true_negatives)
|
|
42
|
+
? rule.test_cases.true_negatives.length
|
|
43
|
+
: 0;
|
|
44
|
+
const evasionTests = Array.isArray(rule.evasion_tests)
|
|
45
|
+
? rule.evasion_tests.length
|
|
46
|
+
: 0;
|
|
47
|
+
const hasOwaspRef = hasAnyArrayItem(rule.references?.owasp_llm) ||
|
|
48
|
+
hasAnyArrayItem(rule.references?.owasp_agentic);
|
|
49
|
+
const hasMitreRef = hasAnyArrayItem(rule.references?.mitre_atlas) ||
|
|
50
|
+
hasAnyArrayItem(rule.references?.mitre_attack);
|
|
51
|
+
const hasFalsePositiveDocs = Array.isArray(rule.detection?.false_positives) &&
|
|
52
|
+
rule.detection.false_positives.length > 0;
|
|
53
|
+
// LLM-generated detection: author contains "Crystallization" or "LLM"
|
|
54
|
+
const author = (rule.author ?? "").toLowerCase();
|
|
55
|
+
const llmGenerated = author.includes("crystallization") ||
|
|
56
|
+
author.includes("llm") ||
|
|
57
|
+
author.includes("mirofish");
|
|
58
|
+
const provenance = extractProvenance(rule.metadata_provenance);
|
|
59
|
+
return {
|
|
60
|
+
id,
|
|
61
|
+
title,
|
|
62
|
+
maturity,
|
|
63
|
+
conditions,
|
|
64
|
+
truePositives,
|
|
65
|
+
trueNegatives,
|
|
66
|
+
evasionTests,
|
|
67
|
+
hasOwaspRef,
|
|
68
|
+
hasMitreRef,
|
|
69
|
+
hasFalsePositiveDocs,
|
|
70
|
+
...(rule.wild_samples !== undefined
|
|
71
|
+
? { wildSamples: rule.wild_samples }
|
|
72
|
+
: {}),
|
|
73
|
+
...(rule.wild_fp_rate !== undefined
|
|
74
|
+
? { wildFpRate: rule.wild_fp_rate }
|
|
75
|
+
: {}),
|
|
76
|
+
...(rule.wild_validated ? { wildValidatedAt: rule.wild_validated } : {}),
|
|
77
|
+
...(llmGenerated ? { llmGenerated: true } : {}),
|
|
78
|
+
...(provenance ? { provenance } : {}),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/** Parse metadata_provenance field and normalize values to Provenance enum */
|
|
82
|
+
function extractProvenance(raw) {
|
|
83
|
+
if (!raw || typeof raw !== "object")
|
|
84
|
+
return undefined;
|
|
85
|
+
const result = {
|
|
86
|
+
...(raw.mitre_atlas
|
|
87
|
+
? { mitre_atlas: normalizeProvenance(raw.mitre_atlas) }
|
|
88
|
+
: {}),
|
|
89
|
+
...(raw.mitre_attack
|
|
90
|
+
? { mitre_attack: normalizeProvenance(raw.mitre_attack) }
|
|
91
|
+
: {}),
|
|
92
|
+
...(raw.owasp_llm ? { owasp_llm: normalizeProvenance(raw.owasp_llm) } : {}),
|
|
93
|
+
...(raw.owasp_agentic
|
|
94
|
+
? { owasp_agentic: normalizeProvenance(raw.owasp_agentic) }
|
|
95
|
+
: {}),
|
|
96
|
+
...(raw.test_cases
|
|
97
|
+
? { test_cases: normalizeProvenance(raw.test_cases) }
|
|
98
|
+
: {}),
|
|
99
|
+
...(raw.evasion_tests
|
|
100
|
+
? { evasion_tests: normalizeProvenance(raw.evasion_tests) }
|
|
101
|
+
: {}),
|
|
102
|
+
...(raw.false_positives
|
|
103
|
+
? { false_positives: normalizeProvenance(raw.false_positives) }
|
|
104
|
+
: {}),
|
|
105
|
+
};
|
|
106
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
107
|
+
}
|
|
108
|
+
function normalizeProvenance(raw) {
|
|
109
|
+
const v = raw.toLowerCase().trim();
|
|
110
|
+
if (v === "human-reviewed" || v === "human")
|
|
111
|
+
return "human-reviewed";
|
|
112
|
+
if (v === "community-contributed" || v === "community")
|
|
113
|
+
return "community-contributed";
|
|
114
|
+
if (v === "auto-generated" || v === "auto")
|
|
115
|
+
return "auto-generated";
|
|
116
|
+
if (v === "llm-generated" || v === "llm")
|
|
117
|
+
return "llm-generated";
|
|
118
|
+
// Unknown value — treat as auto-generated (conservative)
|
|
119
|
+
return "auto-generated";
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* ATR rules use two different condition formats:
|
|
123
|
+
* - Array: `conditions: [{ field, operator, value }, ...]`
|
|
124
|
+
* - Named map: `conditions: { name1: {...}, name2: {...} }`
|
|
125
|
+
*
|
|
126
|
+
* Count layers in either format.
|
|
127
|
+
*/
|
|
128
|
+
function countConditions(conditions) {
|
|
129
|
+
if (Array.isArray(conditions))
|
|
130
|
+
return conditions.length;
|
|
131
|
+
if (conditions !== null && typeof conditions === "object") {
|
|
132
|
+
return Object.keys(conditions).length;
|
|
133
|
+
}
|
|
134
|
+
return 0;
|
|
135
|
+
}
|
|
136
|
+
function hasAnyArrayItem(value) {
|
|
137
|
+
return Array.isArray(value) && value.length > 0;
|
|
138
|
+
}
|
|
139
|
+
function normalizeMaturity(raw) {
|
|
140
|
+
switch (raw) {
|
|
141
|
+
case "draft":
|
|
142
|
+
return "draft";
|
|
143
|
+
case "experimental":
|
|
144
|
+
case "test": // ATR legacy alias
|
|
145
|
+
return "experimental";
|
|
146
|
+
case "stable":
|
|
147
|
+
return "stable";
|
|
148
|
+
case "deprecated":
|
|
149
|
+
return "deprecated";
|
|
150
|
+
default:
|
|
151
|
+
return "draft";
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=atr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atr.js","sourceRoot":"","sources":["../../../src/quality/adapters/atr.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ATR Quality Standard — Rule Format Adapters
|
|
3
|
+
*
|
|
4
|
+
* Adapters convert vendor-specific rule formats into the canonical
|
|
5
|
+
* RuleMetadata interface that the scoring and validation functions consume.
|
|
6
|
+
*
|
|
7
|
+
* @module agent-threat-rules/quality/adapters
|
|
8
|
+
*/
|
|
9
|
+
export { parseATRRule, atrRuleToMetadata } from "./atr.js";
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/quality/adapters/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ATR Quality Standard — Rule Format Adapters
|
|
3
|
+
*
|
|
4
|
+
* Adapters convert vendor-specific rule formats into the canonical
|
|
5
|
+
* RuleMetadata interface that the scoring and validation functions consume.
|
|
6
|
+
*
|
|
7
|
+
* @module agent-threat-rules/quality/adapters
|
|
8
|
+
*/
|
|
9
|
+
export { parseATRRule, atrRuleToMetadata } from "./atr.js";
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/quality/adapters/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ATR Quality Standard — Confidence Scoring
|
|
3
|
+
*
|
|
4
|
+
* Pure function implementing the RFC-001 §2 confidence formula:
|
|
5
|
+
*
|
|
6
|
+
* confidence = round(
|
|
7
|
+
* precision_score * 0.40
|
|
8
|
+
* + wild_validation * 0.30
|
|
9
|
+
* + coverage_score * 0.20
|
|
10
|
+
* + evasion_docs * 0.10
|
|
11
|
+
* )
|
|
12
|
+
*
|
|
13
|
+
* @module agent-threat-rules/quality/compute-confidence
|
|
14
|
+
*/
|
|
15
|
+
import type { ConfidenceScore, DeploymentRecommendation, RuleMetadata } from "./types.js";
|
|
16
|
+
/**
|
|
17
|
+
* Compute the confidence score for a rule.
|
|
18
|
+
*
|
|
19
|
+
* Score is in [0, 100]. Higher is more trustworthy.
|
|
20
|
+
*
|
|
21
|
+
* @param rule - Rule metadata (vendor-agnostic)
|
|
22
|
+
* @returns Score breakdown and total
|
|
23
|
+
*/
|
|
24
|
+
export declare function computeConfidence(rule: RuleMetadata): ConfidenceScore;
|
|
25
|
+
/**
|
|
26
|
+
* Map a confidence score to a deployment recommendation.
|
|
27
|
+
*
|
|
28
|
+
* This is the consumer-facing signal: "should I deploy this rule in
|
|
29
|
+
* blocking mode, alert mode, or not at all?"
|
|
30
|
+
*/
|
|
31
|
+
export declare function deploymentFor(score: number): DeploymentRecommendation;
|
|
32
|
+
/**
|
|
33
|
+
* Apply the cross-context penalty to a match's contribution.
|
|
34
|
+
*
|
|
35
|
+
* When a rule designed for one scan context (e.g. MCP runtime) fires in
|
|
36
|
+
* a different context (e.g. SKILL.md static scan), the match's contribution
|
|
37
|
+
* is downweighted by 0.7. This prevents cross-context noise from inflating
|
|
38
|
+
* overall detection confidence.
|
|
39
|
+
*
|
|
40
|
+
* @param score - The base confidence score of the rule
|
|
41
|
+
* @param isCrossContext - True if the match is outside the rule's native context
|
|
42
|
+
* @returns Adjusted score
|
|
43
|
+
*/
|
|
44
|
+
export declare function applyCrossContextPenalty(score: number, isCrossContext: boolean): number;
|
|
45
|
+
//# sourceMappingURL=compute-confidence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compute-confidence.d.ts","sourceRoot":"","sources":["../../src/quality/compute-confidence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,wBAAwB,EACxB,YAAY,EACb,MAAM,YAAY,CAAC;AAKpB;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,GAAG,eAAe,CAiCrE;AAuDD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,wBAAwB,CAMrE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,OAAO,GACtB,MAAM,CAER"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ATR Quality Standard — Confidence Scoring
|
|
3
|
+
*
|
|
4
|
+
* Pure function implementing the RFC-001 §2 confidence formula:
|
|
5
|
+
*
|
|
6
|
+
* confidence = round(
|
|
7
|
+
* precision_score * 0.40
|
|
8
|
+
* + wild_validation * 0.30
|
|
9
|
+
* + coverage_score * 0.20
|
|
10
|
+
* + evasion_docs * 0.10
|
|
11
|
+
* )
|
|
12
|
+
*
|
|
13
|
+
* @module agent-threat-rules/quality/compute-confidence
|
|
14
|
+
*/
|
|
15
|
+
/** Max confidence an LLM-generated rule can reach without human review */
|
|
16
|
+
const LLM_CAP_WITHOUT_REVIEW = 70;
|
|
17
|
+
/**
|
|
18
|
+
* Compute the confidence score for a rule.
|
|
19
|
+
*
|
|
20
|
+
* Score is in [0, 100]. Higher is more trustworthy.
|
|
21
|
+
*
|
|
22
|
+
* @param rule - Rule metadata (vendor-agnostic)
|
|
23
|
+
* @returns Score breakdown and total
|
|
24
|
+
*/
|
|
25
|
+
export function computeConfidence(rule) {
|
|
26
|
+
const precisionScore = computePrecisionScore(rule);
|
|
27
|
+
const wildValidationScore = computeWildValidationScore(rule);
|
|
28
|
+
const coverageScore = computeCoverageScore(rule);
|
|
29
|
+
const evasionScore = computeEvasionScore(rule);
|
|
30
|
+
const rawTotal = precisionScore * 0.4 +
|
|
31
|
+
wildValidationScore * 0.3 +
|
|
32
|
+
coverageScore * 0.2 +
|
|
33
|
+
evasionScore * 0.1;
|
|
34
|
+
let total = Math.round(rawTotal);
|
|
35
|
+
let capped = false;
|
|
36
|
+
// LLM-generated rules are capped at LLM_CAP_WITHOUT_REVIEW until a human reviews them.
|
|
37
|
+
// Rationale: LLMs can produce subtly wrong rules that pass static validation
|
|
38
|
+
// but fail in the wild. Human review is the only reliable backstop.
|
|
39
|
+
if (rule.llmGenerated === true && rule.humanReviewed !== true) {
|
|
40
|
+
if (total > LLM_CAP_WITHOUT_REVIEW) {
|
|
41
|
+
total = LLM_CAP_WITHOUT_REVIEW;
|
|
42
|
+
capped = true;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
total,
|
|
47
|
+
precisionScore: Math.round(precisionScore),
|
|
48
|
+
wildValidationScore: Math.round(wildValidationScore),
|
|
49
|
+
coverageScore: Math.round(coverageScore),
|
|
50
|
+
evasionScore: Math.round(evasionScore),
|
|
51
|
+
capped,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Precision component (weight 0.40).
|
|
56
|
+
*
|
|
57
|
+
* If wild FP rate is measured, use it directly: (1 - fpRate/100) * 100.
|
|
58
|
+
* Otherwise, estimate from test case coverage: more test cases = higher
|
|
59
|
+
* confidence in precision (max at 10 total).
|
|
60
|
+
*/
|
|
61
|
+
function computePrecisionScore(rule) {
|
|
62
|
+
if (rule.wildFpRate !== undefined &&
|
|
63
|
+
rule.wildSamples !== undefined &&
|
|
64
|
+
rule.wildSamples > 0) {
|
|
65
|
+
const fpRate = Math.max(0, Math.min(100, rule.wildFpRate));
|
|
66
|
+
return 100 - fpRate;
|
|
67
|
+
}
|
|
68
|
+
// Fallback: estimate from test case depth
|
|
69
|
+
const testCaseCount = rule.truePositives + rule.trueNegatives;
|
|
70
|
+
return Math.min(testCaseCount / 10, 1) * 100;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Wild validation component (weight 0.30).
|
|
74
|
+
*
|
|
75
|
+
* Scales with sample size up to 10,000 samples. More real-world data
|
|
76
|
+
* = higher score. A rule tested on 0 samples gets 0. A rule tested on
|
|
77
|
+
* 10,000+ samples gets 100.
|
|
78
|
+
*/
|
|
79
|
+
function computeWildValidationScore(rule) {
|
|
80
|
+
const samples = rule.wildSamples ?? 0;
|
|
81
|
+
return Math.min(samples / 10000, 1) * 100;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Coverage component (weight 0.20).
|
|
85
|
+
*
|
|
86
|
+
* Scales with number of detection conditions (layers). A single-condition
|
|
87
|
+
* rule gets 20. A 5+ condition rule gets 100. Defense in depth matters.
|
|
88
|
+
*/
|
|
89
|
+
function computeCoverageScore(rule) {
|
|
90
|
+
return Math.min(rule.conditions / 5, 1) * 100;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Evasion documentation component (weight 0.10).
|
|
94
|
+
*
|
|
95
|
+
* Rewards honest acknowledgment of known bypasses. A rule with 0 evasion
|
|
96
|
+
* tests gets 0. A rule with 5+ evasion tests gets 100.
|
|
97
|
+
*/
|
|
98
|
+
function computeEvasionScore(rule) {
|
|
99
|
+
return Math.min(rule.evasionTests / 5, 1) * 100;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Map a confidence score to a deployment recommendation.
|
|
103
|
+
*
|
|
104
|
+
* This is the consumer-facing signal: "should I deploy this rule in
|
|
105
|
+
* blocking mode, alert mode, or not at all?"
|
|
106
|
+
*/
|
|
107
|
+
export function deploymentFor(score) {
|
|
108
|
+
if (score >= 90)
|
|
109
|
+
return "block-in-production";
|
|
110
|
+
if (score >= 80)
|
|
111
|
+
return "block-with-monitoring";
|
|
112
|
+
if (score >= 60)
|
|
113
|
+
return "alert-only";
|
|
114
|
+
if (score >= 40)
|
|
115
|
+
return "evaluation-only";
|
|
116
|
+
return "do-not-deploy";
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Apply the cross-context penalty to a match's contribution.
|
|
120
|
+
*
|
|
121
|
+
* When a rule designed for one scan context (e.g. MCP runtime) fires in
|
|
122
|
+
* a different context (e.g. SKILL.md static scan), the match's contribution
|
|
123
|
+
* is downweighted by 0.7. This prevents cross-context noise from inflating
|
|
124
|
+
* overall detection confidence.
|
|
125
|
+
*
|
|
126
|
+
* @param score - The base confidence score of the rule
|
|
127
|
+
* @param isCrossContext - True if the match is outside the rule's native context
|
|
128
|
+
* @returns Adjusted score
|
|
129
|
+
*/
|
|
130
|
+
export function applyCrossContextPenalty(score, isCrossContext) {
|
|
131
|
+
return isCrossContext ? Math.round(score * 0.7) : score;
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=compute-confidence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compute-confidence.js","sourceRoot":"","sources":["../../src/quality/compute-confidence.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ATR Quality Standard — Public API
|
|
3
|
+
*
|
|
4
|
+
* Vendor-neutral library for scoring and validating AI agent threat detection
|
|
5
|
+
* rules. See docs/proposals/001-atr-quality-standard-rfc.md for the RFC.
|
|
6
|
+
*
|
|
7
|
+
* @example Compute a confidence score for an ATR rule
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { parseATRRule, computeConfidence } from 'agent-threat-rules/quality';
|
|
10
|
+
* import { readFileSync } from 'node:fs';
|
|
11
|
+
*
|
|
12
|
+
* const yaml = readFileSync('rules/prompt-injection/ATR-2026-00001.yaml', 'utf-8');
|
|
13
|
+
* const rule = parseATRRule(yaml);
|
|
14
|
+
* const score = computeConfidence(rule);
|
|
15
|
+
* console.log(`Confidence: ${score.total}/100`);
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @example Run a rule through the quality gate
|
|
19
|
+
* ```typescript
|
|
20
|
+
* import { parseATRRule, validateRuleMeetsStandard } from 'agent-threat-rules/quality';
|
|
21
|
+
*
|
|
22
|
+
* const rule = parseATRRule(yamlContent);
|
|
23
|
+
* const gate = validateRuleMeetsStandard(rule, 'experimental');
|
|
24
|
+
* if (!gate.passed) {
|
|
25
|
+
* console.error('Rule rejected:', gate.issues);
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @module agent-threat-rules/quality
|
|
30
|
+
*/
|
|
31
|
+
export type { Maturity, RuleMetadata, ConfidenceScore, QualityGateResult, PromotionDecision, DemotionDecision, FpReport, DeploymentRecommendation, } from "./types.js";
|
|
32
|
+
export { computeConfidence, deploymentFor, applyCrossContextPenalty, } from "./compute-confidence.js";
|
|
33
|
+
export { validateRuleMeetsStandard, getRequirements } from "./quality-gate.js";
|
|
34
|
+
export { canPromote, shouldDemote, getMaturityThresholds, } from "./validate-maturity.js";
|
|
35
|
+
export { parseATRRule, atrRuleToMetadata } from "./adapters/atr.js";
|
|
36
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/quality/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAGH,YAAY,EACV,QAAQ,EACR,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,QAAQ,EACR,wBAAwB,GACzB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,wBAAwB,GACzB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAG/E,OAAO,EACL,UAAU,EACV,YAAY,EACZ,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ATR Quality Standard — Public API
|
|
3
|
+
*
|
|
4
|
+
* Vendor-neutral library for scoring and validating AI agent threat detection
|
|
5
|
+
* rules. See docs/proposals/001-atr-quality-standard-rfc.md for the RFC.
|
|
6
|
+
*
|
|
7
|
+
* @example Compute a confidence score for an ATR rule
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { parseATRRule, computeConfidence } from 'agent-threat-rules/quality';
|
|
10
|
+
* import { readFileSync } from 'node:fs';
|
|
11
|
+
*
|
|
12
|
+
* const yaml = readFileSync('rules/prompt-injection/ATR-2026-00001.yaml', 'utf-8');
|
|
13
|
+
* const rule = parseATRRule(yaml);
|
|
14
|
+
* const score = computeConfidence(rule);
|
|
15
|
+
* console.log(`Confidence: ${score.total}/100`);
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @example Run a rule through the quality gate
|
|
19
|
+
* ```typescript
|
|
20
|
+
* import { parseATRRule, validateRuleMeetsStandard } from 'agent-threat-rules/quality';
|
|
21
|
+
*
|
|
22
|
+
* const rule = parseATRRule(yamlContent);
|
|
23
|
+
* const gate = validateRuleMeetsStandard(rule, 'experimental');
|
|
24
|
+
* if (!gate.passed) {
|
|
25
|
+
* console.error('Rule rejected:', gate.issues);
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @module agent-threat-rules/quality
|
|
30
|
+
*/
|
|
31
|
+
// Scoring
|
|
32
|
+
export { computeConfidence, deploymentFor, applyCrossContextPenalty, } from "./compute-confidence.js";
|
|
33
|
+
// Validation
|
|
34
|
+
export { validateRuleMeetsStandard, getRequirements } from "./quality-gate.js";
|
|
35
|
+
// Maturity transitions
|
|
36
|
+
export { canPromote, shouldDemote, getMaturityThresholds, } from "./validate-maturity.js";
|
|
37
|
+
// Adapters
|
|
38
|
+
export { parseATRRule, atrRuleToMetadata } from "./adapters/atr.js";
|
|
39
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/quality/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAcH,UAAU;AACV,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,wBAAwB,GACzB,MAAM,yBAAyB,CAAC;AAEjC,aAAa;AACb,OAAO,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAE/E,uBAAuB;AACvB,OAAO,EACL,UAAU,EACV,YAAY,EACZ,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAEhC,WAAW;AACX,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ATR Quality Standard — Quality Gate
|
|
3
|
+
*
|
|
4
|
+
* Checks whether a rule meets the minimum quality bar for a target maturity
|
|
5
|
+
* level. Used by TC crystallization pipeline to reject weak LLM-generated
|
|
6
|
+
* rules before they enter the proposal pipeline.
|
|
7
|
+
*
|
|
8
|
+
* See docs/proposals/001-atr-quality-standard-rfc.md §3 for the required
|
|
9
|
+
* metadata matrix.
|
|
10
|
+
*
|
|
11
|
+
* @module agent-threat-rules/quality/quality-gate
|
|
12
|
+
*/
|
|
13
|
+
import type { Maturity, QualityGateResult, RuleMetadata } from "./types.js";
|
|
14
|
+
/**
|
|
15
|
+
* Minimum requirements for each maturity level.
|
|
16
|
+
* Thresholds match RFC-001 §3. Adjust here to tune the bar.
|
|
17
|
+
*
|
|
18
|
+
* The experimental gate uses 3/3 (matching Cisco-merge practice) and
|
|
19
|
+
* accepts any provenance (auto-generated OK). The stable gate requires
|
|
20
|
+
* 5/5 with 3 evasion tests AND human-reviewed provenance for MITRE/OWASP.
|
|
21
|
+
*/
|
|
22
|
+
declare const REQUIREMENTS: {
|
|
23
|
+
readonly draft: {
|
|
24
|
+
readonly minConditions: 1;
|
|
25
|
+
readonly minTruePositives: 1;
|
|
26
|
+
readonly minTrueNegatives: 1;
|
|
27
|
+
readonly minEvasionTests: 0;
|
|
28
|
+
readonly requireOwasp: false;
|
|
29
|
+
readonly requireMitre: false;
|
|
30
|
+
readonly requireFalsePositiveDocs: false;
|
|
31
|
+
readonly requireHumanReviewedProvenance: false;
|
|
32
|
+
};
|
|
33
|
+
readonly experimental: {
|
|
34
|
+
readonly minConditions: 3;
|
|
35
|
+
readonly minTruePositives: 3;
|
|
36
|
+
readonly minTrueNegatives: 3;
|
|
37
|
+
readonly minEvasionTests: 0;
|
|
38
|
+
readonly requireOwasp: true;
|
|
39
|
+
readonly requireMitre: true;
|
|
40
|
+
readonly requireFalsePositiveDocs: true;
|
|
41
|
+
readonly requireHumanReviewedProvenance: false;
|
|
42
|
+
};
|
|
43
|
+
readonly stable: {
|
|
44
|
+
readonly minConditions: 3;
|
|
45
|
+
readonly minTruePositives: 5;
|
|
46
|
+
readonly minTrueNegatives: 5;
|
|
47
|
+
readonly minEvasionTests: 3;
|
|
48
|
+
readonly requireOwasp: true;
|
|
49
|
+
readonly requireMitre: true;
|
|
50
|
+
readonly requireFalsePositiveDocs: true;
|
|
51
|
+
readonly requireHumanReviewedProvenance: true;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Validate a rule against the quality bar for a target maturity level.
|
|
56
|
+
*
|
|
57
|
+
* @param rule - Rule metadata
|
|
58
|
+
* @param target - Target maturity level to validate against (default: rule.maturity)
|
|
59
|
+
* @returns Gate result with passed/failed and human-readable issues
|
|
60
|
+
*/
|
|
61
|
+
export declare function validateRuleMeetsStandard(rule: RuleMetadata, target?: Maturity): QualityGateResult;
|
|
62
|
+
/**
|
|
63
|
+
* Public accessor for the requirements table.
|
|
64
|
+
* Useful for documentation generators and UIs that display the quality bar.
|
|
65
|
+
*/
|
|
66
|
+
export declare function getRequirements(): typeof REQUIREMENTS;
|
|
67
|
+
export {};
|
|
68
|
+
//# sourceMappingURL=quality-gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quality-gate.d.ts","sourceRoot":"","sources":["../../src/quality/quality-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EACV,QAAQ,EAER,iBAAiB,EACjB,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB;;;;;;;GAOG;AACH,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BR,CAAC;AAQX;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,YAAY,EAClB,MAAM,CAAC,EAAE,QAAQ,GAChB,iBAAiB,CAiFnB;AAMD;;;GAGG;AACH,wBAAgB,eAAe,IAAI,OAAO,YAAY,CAErD"}
|