agent-threat-rules 0.3.1 → 1.0.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 +190 -54
- package/package.json +3 -1
- package/rules/agent-manipulation/{ATR-2026-030-cross-agent-attack.yaml → ATR-2026-00030-cross-agent-attack.yaml} +3 -1
- package/rules/agent-manipulation/{ATR-2026-032-goal-hijacking.yaml → ATR-2026-00032-goal-hijacking.yaml} +3 -1
- package/rules/agent-manipulation/{ATR-2026-074-cross-agent-privilege-escalation.yaml → ATR-2026-00074-cross-agent-privilege-escalation.yaml} +3 -1
- package/rules/agent-manipulation/{ATR-2026-076-inter-agent-message-spoofing.yaml → ATR-2026-00076-inter-agent-message-spoofing.yaml} +3 -1
- package/rules/agent-manipulation/{ATR-2026-077-human-trust-exploitation.yaml → ATR-2026-00077-human-trust-exploitation.yaml} +3 -1
- package/rules/agent-manipulation/{ATR-2026-108-consensus-sybil-attack.yaml → ATR-2026-00108-consensus-sybil-attack.yaml} +3 -1
- package/rules/agent-manipulation/ATR-2026-00116-a2a-message-validation.yaml +92 -0
- package/rules/agent-manipulation/ATR-2026-00117-agent-identity-spoofing.yaml +92 -0
- package/rules/agent-manipulation/ATR-2026-00118-approval-fatigue.yaml +89 -0
- package/rules/agent-manipulation/ATR-2026-00119-social-engineering-via-agent.yaml +89 -0
- package/rules/agent-manipulation/ATR-2026-00132-casual-authority-escalation.yaml +105 -0
- package/rules/agent-manipulation/ATR-2026-00139-casual-authority-redirect.yaml +53 -0
- package/rules/context-exfiltration/{ATR-2026-020-system-prompt-leak.yaml → ATR-2026-00020-system-prompt-leak.yaml} +3 -1
- package/rules/context-exfiltration/{ATR-2026-021-api-key-exposure.yaml → ATR-2026-00021-api-key-exposure.yaml} +3 -1
- package/rules/context-exfiltration/{ATR-2026-075-agent-memory-manipulation.yaml → ATR-2026-00075-agent-memory-manipulation.yaml} +3 -1
- package/rules/context-exfiltration/{ATR-2026-102-disguised-analytics-exfiltration.yaml → ATR-2026-00102-disguised-analytics-exfiltration.yaml} +3 -1
- package/rules/context-exfiltration/ATR-2026-00113-credential-theft.yaml +89 -0
- package/rules/context-exfiltration/ATR-2026-00114-oauth-token-abuse.yaml +89 -0
- package/rules/context-exfiltration/ATR-2026-00115-env-var-harvesting.yaml +90 -0
- package/rules/context-exfiltration/ATR-2026-00136-tool-response-data-piggyback.yaml +100 -0
- package/rules/context-exfiltration/ATR-2026-00141-example-format-key-leak.yaml +52 -0
- package/rules/context-exfiltration/ATR-2026-00142-piggyback-transition-words.yaml +55 -0
- package/rules/context-exfiltration/ATR-2026-00145-obfuscated-key-disclosure.yaml +49 -0
- package/rules/context-exfiltration/ATR-2026-00146-env-var-existence-probe.yaml +49 -0
- package/rules/data-poisoning/{ATR-2026-070-data-poisoning.yaml → ATR-2026-00070-data-poisoning.yaml} +3 -1
- package/rules/excessive-autonomy/{ATR-2026-050-runaway-agent-loop.yaml → ATR-2026-00050-runaway-agent-loop.yaml} +3 -1
- package/rules/excessive-autonomy/{ATR-2026-051-resource-exhaustion.yaml → ATR-2026-00051-resource-exhaustion.yaml} +3 -1
- package/rules/excessive-autonomy/{ATR-2026-052-cascading-failure.yaml → ATR-2026-00052-cascading-failure.yaml} +3 -1
- package/rules/excessive-autonomy/{ATR-2026-098-unauthorized-financial-action.yaml → ATR-2026-00098-unauthorized-financial-action.yaml} +3 -1
- package/rules/excessive-autonomy/{ATR-2026-099-high-risk-tool-gate.yaml → ATR-2026-00099-high-risk-tool-gate.yaml} +4 -2
- package/rules/model-security/{ATR-2026-072-model-behavior-extraction.yaml → ATR-2026-00072-model-behavior-extraction.yaml} +3 -1
- package/rules/model-security/{ATR-2026-073-malicious-finetuning-data.yaml → ATR-2026-00073-malicious-finetuning-data.yaml} +3 -1
- package/rules/privilege-escalation/{ATR-2026-040-privilege-escalation.yaml → ATR-2026-00040-privilege-escalation.yaml} +3 -1
- package/rules/privilege-escalation/{ATR-2026-041-scope-creep.yaml → ATR-2026-00041-scope-creep.yaml} +3 -1
- package/rules/privilege-escalation/{ATR-2026-107-delayed-execution-bypass.yaml → ATR-2026-00107-delayed-execution-bypass.yaml} +3 -1
- package/rules/privilege-escalation/ATR-2026-00110-eval-injection.yaml +92 -0
- package/rules/privilege-escalation/ATR-2026-00111-shell-escape.yaml +93 -0
- package/rules/privilege-escalation/ATR-2026-00112-dynamic-import-exploitation.yaml +89 -0
- package/rules/privilege-escalation/ATR-2026-00143-casual-privilege-escalation.yaml +53 -0
- package/rules/privilege-escalation/ATR-2026-00144-rationalized-safety-bypass.yaml +49 -0
- package/rules/prompt-injection/{ATR-2026-001-direct-prompt-injection.yaml → ATR-2026-00001-direct-prompt-injection.yaml} +121 -11
- package/rules/prompt-injection/{ATR-2026-002-indirect-prompt-injection.yaml → ATR-2026-00002-indirect-prompt-injection.yaml} +3 -1
- package/rules/prompt-injection/{ATR-2026-003-jailbreak-attempt.yaml → ATR-2026-00003-jailbreak-attempt.yaml} +3 -1
- package/rules/prompt-injection/{ATR-2026-004-system-prompt-override.yaml → ATR-2026-00004-system-prompt-override.yaml} +3 -1
- package/rules/prompt-injection/{ATR-2026-005-multi-turn-injection.yaml → ATR-2026-00005-multi-turn-injection.yaml} +3 -1
- package/rules/prompt-injection/{ATR-2026-080-encoding-evasion.yaml → ATR-2026-00080-encoding-evasion.yaml} +3 -1
- package/rules/prompt-injection/{ATR-2026-081-semantic-multi-turn.yaml → ATR-2026-00081-semantic-multi-turn.yaml} +3 -1
- package/rules/prompt-injection/{ATR-2026-082-fingerprint-evasion.yaml → ATR-2026-00082-fingerprint-evasion.yaml} +3 -1
- package/rules/prompt-injection/{ATR-2026-083-indirect-tool-injection.yaml → ATR-2026-00083-indirect-tool-injection.yaml} +3 -1
- package/rules/prompt-injection/{ATR-2026-084-structured-data-injection.yaml → ATR-2026-00084-structured-data-injection.yaml} +3 -1
- package/rules/prompt-injection/{ATR-2026-085-audit-evasion.yaml → ATR-2026-00085-audit-evasion.yaml} +3 -1
- package/rules/prompt-injection/{ATR-2026-086-visual-spoofing.yaml → ATR-2026-00086-visual-spoofing.yaml} +3 -1
- package/rules/prompt-injection/{ATR-2026-087-rule-probing.yaml → ATR-2026-00087-rule-probing.yaml} +3 -1
- package/rules/prompt-injection/{ATR-2026-088-adaptive-countermeasure.yaml → ATR-2026-00088-adaptive-countermeasure.yaml} +3 -1
- package/rules/prompt-injection/{ATR-2026-089-polymorphic-skill.yaml → ATR-2026-00089-polymorphic-skill.yaml} +3 -1
- package/rules/prompt-injection/{ATR-2026-090-threat-intel-exfil.yaml → ATR-2026-00090-threat-intel-exfil.yaml} +3 -1
- package/rules/prompt-injection/{ATR-2026-091-nested-payload.yaml → ATR-2026-00091-nested-payload.yaml} +3 -1
- package/rules/prompt-injection/{ATR-2026-092-consensus-poisoning.yaml → ATR-2026-00092-consensus-poisoning.yaml} +3 -1
- package/rules/prompt-injection/{ATR-2026-093-gradual-escalation.yaml → ATR-2026-00093-gradual-escalation.yaml} +3 -1
- package/rules/prompt-injection/{ATR-2026-094-audit-bypass.yaml → ATR-2026-00094-audit-bypass.yaml} +3 -1
- package/rules/prompt-injection/{ATR-2026-097-cjk-injection-patterns.yaml → ATR-2026-00097-cjk-injection-patterns.yaml} +18 -1
- package/rules/prompt-injection/{ATR-2026-104-persona-hijacking.yaml → ATR-2026-00104-persona-hijacking.yaml} +3 -1
- package/rules/prompt-injection/ATR-2026-00130-indirect-authority-claim.yaml +103 -0
- package/rules/prompt-injection/ATR-2026-00131-fictional-academic-framing.yaml +99 -0
- package/rules/prompt-injection/ATR-2026-00133-paraphrase-injection.yaml +117 -0
- package/rules/prompt-injection/ATR-2026-00137-authority-claim-injection.yaml +52 -0
- package/rules/prompt-injection/ATR-2026-00138-fictional-framing-bypass.yaml +51 -0
- package/rules/prompt-injection/ATR-2026-00140-indirect-reference-reversal.yaml +52 -0
- package/rules/prompt-injection/ATR-2026-00148-language-switch-injection.yaml +71 -0
- package/rules/skill-compromise/{ATR-2026-060-skill-impersonation.yaml → ATR-2026-00060-skill-impersonation.yaml} +3 -1
- package/rules/skill-compromise/{ATR-2026-061-description-behavior-mismatch.yaml → ATR-2026-00061-description-behavior-mismatch.yaml} +4 -2
- package/rules/skill-compromise/{ATR-2026-062-hidden-capability.yaml → ATR-2026-00062-hidden-capability.yaml} +3 -1
- package/rules/skill-compromise/{ATR-2026-063-skill-chain-attack.yaml → ATR-2026-00063-skill-chain-attack.yaml} +5 -2
- package/rules/skill-compromise/{ATR-2026-064-over-permissioned-skill.yaml → ATR-2026-00064-over-permissioned-skill.yaml} +3 -1
- package/rules/skill-compromise/{ATR-2026-065-skill-update-attack.yaml → ATR-2026-00065-skill-update-attack.yaml} +3 -1
- package/rules/skill-compromise/{ATR-2026-066-parameter-injection.yaml → ATR-2026-00066-parameter-injection.yaml} +3 -1
- package/rules/skill-compromise/ATR-2026-00120-skill-instruction-injection.yaml +121 -0
- package/rules/skill-compromise/ATR-2026-00121-skill-dangerous-script.yaml +165 -0
- package/rules/skill-compromise/ATR-2026-00122-skill-weaponized-instruction.yaml +114 -0
- package/rules/skill-compromise/ATR-2026-00123-skill-overreach-permissions.yaml +118 -0
- package/rules/skill-compromise/ATR-2026-00124-skill-name-squatting.yaml +98 -0
- package/rules/skill-compromise/ATR-2026-00125-context-poisoning-compaction.yaml +93 -0
- package/rules/skill-compromise/ATR-2026-00126-skill-rug-pull-setup.yaml +99 -0
- package/rules/skill-compromise/ATR-2026-00127-subcommand-overflow.yaml +74 -0
- package/rules/skill-compromise/ATR-2026-00128-html-comment-hidden-payload.yaml +79 -0
- package/rules/skill-compromise/ATR-2026-00129-unicode-smuggling.yaml +73 -0
- package/rules/skill-compromise/ATR-2026-00134-fork-claim-impersonation.yaml +93 -0
- package/rules/skill-compromise/ATR-2026-00135-exfil-url-in-instructions.yaml +82 -0
- package/rules/skill-compromise/ATR-2026-00147-fork-impersonation.yaml +48 -0
- package/rules/tool-poisoning/{ATR-2026-010-mcp-malicious-response.yaml → ATR-2026-00010-mcp-malicious-response.yaml} +3 -1
- package/rules/tool-poisoning/{ATR-2026-011-tool-output-injection.yaml → ATR-2026-00011-tool-output-injection.yaml} +3 -1
- package/rules/tool-poisoning/{ATR-2026-012-unauthorized-tool-call.yaml → ATR-2026-00012-unauthorized-tool-call.yaml} +3 -1
- package/rules/tool-poisoning/{ATR-2026-013-tool-ssrf.yaml → ATR-2026-00013-tool-ssrf.yaml} +3 -1
- package/rules/tool-poisoning/{ATR-2026-095-supply-chain-poisoning.yaml → ATR-2026-00095-supply-chain-poisoning.yaml} +3 -1
- package/rules/tool-poisoning/{ATR-2026-096-registry-poisoning.yaml → ATR-2026-00096-registry-poisoning.yaml} +3 -1
- package/rules/tool-poisoning/{ATR-2026-100-consent-bypass-instruction.yaml → ATR-2026-00100-consent-bypass-instruction.yaml} +3 -1
- package/rules/tool-poisoning/{ATR-2026-101-trust-escalation-override.yaml → ATR-2026-00101-trust-escalation-override.yaml} +3 -1
- package/rules/tool-poisoning/{ATR-2026-103-hidden-safety-bypass-instruction.yaml → ATR-2026-00103-hidden-safety-bypass-instruction.yaml} +3 -1
- package/rules/tool-poisoning/{ATR-2026-105-silent-action-concealment.yaml → ATR-2026-00105-silent-action-concealment.yaml} +3 -1
- package/rules/tool-poisoning/{ATR-2026-106-schema-description-contradiction.yaml → ATR-2026-00106-schema-description-contradiction.yaml} +3 -1
- package/spec/atr-schema.yaml +32 -3
- package/dist/action-executor.d.ts +0 -44
- package/dist/action-executor.d.ts.map +0 -1
- package/dist/action-executor.js +0 -130
- package/dist/action-executor.js.map +0 -1
- package/dist/adapters/default-adapter.d.ts +0 -24
- package/dist/adapters/default-adapter.d.ts.map +0 -1
- package/dist/adapters/default-adapter.js +0 -51
- package/dist/adapters/default-adapter.js.map +0 -1
- package/dist/adapters/stdio-adapter.d.ts +0 -30
- package/dist/adapters/stdio-adapter.d.ts.map +0 -1
- package/dist/adapters/stdio-adapter.js +0 -128
- package/dist/adapters/stdio-adapter.js.map +0 -1
- package/dist/capability-extractor.d.ts +0 -35
- package/dist/capability-extractor.d.ts.map +0 -1
- package/dist/capability-extractor.js +0 -91
- package/dist/capability-extractor.js.map +0 -1
- package/dist/cli.d.ts +0 -12
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -820
- package/dist/cli.js.map +0 -1
- package/dist/converters/elastic.d.ts +0 -36
- package/dist/converters/elastic.d.ts.map +0 -1
- package/dist/converters/elastic.js +0 -125
- package/dist/converters/elastic.js.map +0 -1
- package/dist/converters/index.d.ts +0 -28
- package/dist/converters/index.d.ts.map +0 -1
- package/dist/converters/index.js +0 -36
- package/dist/converters/index.js.map +0 -1
- package/dist/converters/splunk.d.ts +0 -19
- package/dist/converters/splunk.d.ts.map +0 -1
- package/dist/converters/splunk.js +0 -148
- package/dist/converters/splunk.js.map +0 -1
- package/dist/coverage-analyzer.d.ts +0 -43
- package/dist/coverage-analyzer.d.ts.map +0 -1
- package/dist/coverage-analyzer.js +0 -329
- package/dist/coverage-analyzer.js.map +0 -1
- package/dist/embedding/build-corpus.d.ts +0 -15
- package/dist/embedding/build-corpus.d.ts.map +0 -1
- package/dist/embedding/build-corpus.js +0 -105
- package/dist/embedding/build-corpus.js.map +0 -1
- package/dist/embedding/model-loader.d.ts +0 -41
- package/dist/embedding/model-loader.d.ts.map +0 -1
- package/dist/embedding/model-loader.js +0 -90
- package/dist/embedding/model-loader.js.map +0 -1
- package/dist/embedding/vector-store.d.ts +0 -41
- package/dist/embedding/vector-store.d.ts.map +0 -1
- package/dist/embedding/vector-store.js +0 -70
- package/dist/embedding/vector-store.js.map +0 -1
- package/dist/engine.d.ts +0 -163
- package/dist/engine.d.ts.map +0 -1
- package/dist/engine.js +0 -869
- package/dist/engine.js.map +0 -1
- package/dist/eval/corpus.d.ts +0 -42
- package/dist/eval/corpus.d.ts.map +0 -1
- package/dist/eval/corpus.js +0 -427
- package/dist/eval/corpus.js.map +0 -1
- package/dist/eval/eval-harness.d.ts +0 -44
- package/dist/eval/eval-harness.d.ts.map +0 -1
- package/dist/eval/eval-harness.js +0 -296
- package/dist/eval/eval-harness.js.map +0 -1
- package/dist/eval/index.d.ts +0 -13
- package/dist/eval/index.d.ts.map +0 -1
- package/dist/eval/index.js +0 -9
- package/dist/eval/index.js.map +0 -1
- package/dist/eval/metrics.d.ts +0 -74
- package/dist/eval/metrics.d.ts.map +0 -1
- package/dist/eval/metrics.js +0 -108
- package/dist/eval/metrics.js.map +0 -1
- package/dist/eval/pint-corpus.d.ts +0 -34
- package/dist/eval/pint-corpus.d.ts.map +0 -1
- package/dist/eval/pint-corpus.js +0 -109
- package/dist/eval/pint-corpus.js.map +0 -1
- package/dist/eval/rule-corpus.d.ts +0 -9
- package/dist/eval/rule-corpus.d.ts.map +0 -1
- package/dist/eval/rule-corpus.js +0 -4780
- package/dist/eval/rule-corpus.js.map +0 -1
- package/dist/eval/rule-metrics.d.ts +0 -34
- package/dist/eval/rule-metrics.d.ts.map +0 -1
- package/dist/eval/rule-metrics.js +0 -92
- package/dist/eval/rule-metrics.js.map +0 -1
- package/dist/eval/run-eval.d.ts +0 -7
- package/dist/eval/run-eval.d.ts.map +0 -1
- package/dist/eval/run-eval.js +0 -11
- package/dist/eval/run-eval.js.map +0 -1
- package/dist/eval/run-pint-benchmark.d.ts +0 -18
- package/dist/eval/run-pint-benchmark.d.ts.map +0 -1
- package/dist/eval/run-pint-benchmark.js +0 -157
- package/dist/eval/run-pint-benchmark.js.map +0 -1
- package/dist/flywheel.d.ts +0 -54
- package/dist/flywheel.d.ts.map +0 -1
- package/dist/flywheel.js +0 -121
- package/dist/flywheel.js.map +0 -1
- package/dist/hook-handler.d.ts +0 -61
- package/dist/hook-handler.d.ts.map +0 -1
- package/dist/hook-handler.js +0 -178
- package/dist/hook-handler.js.map +0 -1
- package/dist/index.d.ts +0 -62
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -54
- package/dist/index.js.map +0 -1
- package/dist/layer-integration.d.ts +0 -55
- package/dist/layer-integration.d.ts.map +0 -1
- package/dist/layer-integration.js +0 -185
- package/dist/layer-integration.js.map +0 -1
- package/dist/loader.d.ts +0 -21
- package/dist/loader.d.ts.map +0 -1
- package/dist/loader.js +0 -124
- package/dist/loader.js.map +0 -1
- package/dist/mcp-server.d.ts +0 -13
- package/dist/mcp-server.d.ts.map +0 -1
- package/dist/mcp-server.js +0 -220
- package/dist/mcp-server.js.map +0 -1
- package/dist/mcp-tools/coverage-gaps.d.ts +0 -13
- package/dist/mcp-tools/coverage-gaps.d.ts.map +0 -1
- package/dist/mcp-tools/coverage-gaps.js +0 -55
- package/dist/mcp-tools/coverage-gaps.js.map +0 -1
- package/dist/mcp-tools/list-rules.d.ts +0 -17
- package/dist/mcp-tools/list-rules.d.ts.map +0 -1
- package/dist/mcp-tools/list-rules.js +0 -45
- package/dist/mcp-tools/list-rules.js.map +0 -1
- package/dist/mcp-tools/scan.d.ts +0 -24
- package/dist/mcp-tools/scan.d.ts.map +0 -1
- package/dist/mcp-tools/scan.js +0 -94
- package/dist/mcp-tools/scan.js.map +0 -1
- package/dist/mcp-tools/submit-proposal.d.ts +0 -12
- package/dist/mcp-tools/submit-proposal.d.ts.map +0 -1
- package/dist/mcp-tools/submit-proposal.js +0 -103
- package/dist/mcp-tools/submit-proposal.js.map +0 -1
- package/dist/mcp-tools/threat-summary.d.ts +0 -12
- package/dist/mcp-tools/threat-summary.d.ts.map +0 -1
- package/dist/mcp-tools/threat-summary.js +0 -74
- package/dist/mcp-tools/threat-summary.js.map +0 -1
- package/dist/mcp-tools/validate.d.ts +0 -15
- package/dist/mcp-tools/validate.d.ts.map +0 -1
- package/dist/mcp-tools/validate.js +0 -45
- package/dist/mcp-tools/validate.js.map +0 -1
- package/dist/modules/embedding.d.ts +0 -71
- package/dist/modules/embedding.d.ts.map +0 -1
- package/dist/modules/embedding.js +0 -141
- package/dist/modules/embedding.js.map +0 -1
- package/dist/modules/index.d.ts +0 -144
- package/dist/modules/index.d.ts.map +0 -1
- package/dist/modules/index.js +0 -82
- package/dist/modules/index.js.map +0 -1
- package/dist/modules/semantic.d.ts +0 -106
- package/dist/modules/semantic.d.ts.map +0 -1
- package/dist/modules/semantic.js +0 -359
- package/dist/modules/semantic.js.map +0 -1
- package/dist/modules/session.d.ts +0 -70
- package/dist/modules/session.d.ts.map +0 -1
- package/dist/modules/session.js +0 -128
- package/dist/modules/session.js.map +0 -1
- package/dist/rule-scaffolder.d.ts +0 -53
- package/dist/rule-scaffolder.d.ts.map +0 -1
- package/dist/rule-scaffolder.js +0 -301
- package/dist/rule-scaffolder.js.map +0 -1
- package/dist/session-tracker.d.ts +0 -58
- package/dist/session-tracker.d.ts.map +0 -1
- package/dist/session-tracker.js +0 -176
- package/dist/session-tracker.js.map +0 -1
- package/dist/shadow-evaluator.d.ts +0 -48
- package/dist/shadow-evaluator.d.ts.map +0 -1
- package/dist/shadow-evaluator.js +0 -128
- package/dist/shadow-evaluator.js.map +0 -1
- package/dist/skill-fingerprint.d.ts +0 -85
- package/dist/skill-fingerprint.d.ts.map +0 -1
- package/dist/skill-fingerprint.js +0 -284
- package/dist/skill-fingerprint.js.map +0 -1
- package/dist/tier0-invariant.d.ts +0 -49
- package/dist/tier0-invariant.d.ts.map +0 -1
- package/dist/tier0-invariant.js +0 -184
- package/dist/tier0-invariant.js.map +0 -1
- package/dist/tier1-blacklist.d.ts +0 -48
- package/dist/tier1-blacklist.d.ts.map +0 -1
- package/dist/tier1-blacklist.js +0 -91
- package/dist/tier1-blacklist.js.map +0 -1
- package/dist/types.d.ts +0 -190
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -6
- package/dist/types.js.map +0 -1
- package/dist/verdict.d.ts +0 -26
- package/dist/verdict.d.ts.map +0 -1
- package/dist/verdict.js +0 -127
- package/dist/verdict.js.map +0 -1
package/dist/shadow-evaluator.js
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shadow Evaluator -- runs experimental rules without affecting verdict.
|
|
3
|
-
*
|
|
4
|
-
* Experimental rules evaluate against every event but don't influence
|
|
5
|
-
* the real verdict. Their match/no-match results are tracked to measure
|
|
6
|
-
* false positive rates. Rules with FP < threshold get promoted.
|
|
7
|
-
*
|
|
8
|
-
* @module agent-threat-rules/shadow-evaluator
|
|
9
|
-
*/
|
|
10
|
-
export class ShadowEvaluator {
|
|
11
|
-
rules = [];
|
|
12
|
-
stats = new Map();
|
|
13
|
-
compiledPatterns = new Map();
|
|
14
|
-
/** Add an experimental rule for shadow evaluation */
|
|
15
|
-
addRule(rule) {
|
|
16
|
-
if (this.rules.some((r) => r.id === rule.id))
|
|
17
|
-
return; // dedup
|
|
18
|
-
this.rules.push(rule);
|
|
19
|
-
this.stats.set(rule.id, {
|
|
20
|
-
ruleId: rule.id,
|
|
21
|
-
totalEvaluations: 0,
|
|
22
|
-
totalMatches: 0,
|
|
23
|
-
confirmedTruePositives: 0,
|
|
24
|
-
confirmedFalsePositives: 0,
|
|
25
|
-
firstSeen: Date.now(),
|
|
26
|
-
lastSeen: Date.now(),
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
/** Evaluate all shadow rules against an event (does NOT affect verdict) */
|
|
30
|
-
evaluate(event) {
|
|
31
|
-
const matches = [];
|
|
32
|
-
for (const rule of this.rules) {
|
|
33
|
-
const stat = this.stats.get(rule.id);
|
|
34
|
-
if (!stat)
|
|
35
|
-
continue;
|
|
36
|
-
stat.totalEvaluations++;
|
|
37
|
-
stat.lastSeen = Date.now();
|
|
38
|
-
// Simple regex evaluation for shadow rules
|
|
39
|
-
const detection = rule.detection;
|
|
40
|
-
const conditions = Array.isArray(detection.conditions)
|
|
41
|
-
? detection.conditions
|
|
42
|
-
: Object.values(detection.conditions);
|
|
43
|
-
let matched = false;
|
|
44
|
-
for (const cond of conditions) {
|
|
45
|
-
const c = cond;
|
|
46
|
-
const value = c['value'];
|
|
47
|
-
const field = c['field'];
|
|
48
|
-
if (!value || !field)
|
|
49
|
-
continue;
|
|
50
|
-
const text = event.fields?.[field] ?? event.content ?? '';
|
|
51
|
-
try {
|
|
52
|
-
let regex = this.compiledPatterns.get(value);
|
|
53
|
-
if (!regex) {
|
|
54
|
-
regex = new RegExp(value, 'i');
|
|
55
|
-
this.compiledPatterns.set(value, regex);
|
|
56
|
-
}
|
|
57
|
-
if (regex.test(text)) {
|
|
58
|
-
matched = true;
|
|
59
|
-
break;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
catch {
|
|
63
|
-
// Invalid regex
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
if (matched) {
|
|
67
|
-
stat.totalMatches++;
|
|
68
|
-
matches.push({
|
|
69
|
-
rule,
|
|
70
|
-
matchedConditions: ['shadow'],
|
|
71
|
-
matchedPatterns: ['shadow-match'],
|
|
72
|
-
confidence: 0.5, // Shadow matches have reduced confidence
|
|
73
|
-
timestamp: new Date().toISOString(),
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return matches;
|
|
78
|
-
}
|
|
79
|
-
/** Record user feedback on a shadow match */
|
|
80
|
-
recordFeedback(ruleId, isTruePositive) {
|
|
81
|
-
const stat = this.stats.get(ruleId);
|
|
82
|
-
if (!stat)
|
|
83
|
-
return;
|
|
84
|
-
if (isTruePositive) {
|
|
85
|
-
stat.confirmedTruePositives++;
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
stat.confirmedFalsePositives++;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Get rules ready for promotion.
|
|
93
|
-
* Criteria: FP rate < maxFPRate AND minimum evaluations reached.
|
|
94
|
-
*/
|
|
95
|
-
getPromotionCandidates(maxFPRate = 0.001, minEvaluations = 1000) {
|
|
96
|
-
const candidates = [];
|
|
97
|
-
for (const rule of this.rules) {
|
|
98
|
-
const stat = this.stats.get(rule.id);
|
|
99
|
-
if (!stat || stat.totalEvaluations < minEvaluations)
|
|
100
|
-
continue;
|
|
101
|
-
const fpRate = stat.totalMatches > 0
|
|
102
|
-
? stat.confirmedFalsePositives / stat.totalMatches
|
|
103
|
-
: 0;
|
|
104
|
-
// Only promote if:
|
|
105
|
-
// 1. Has been evaluated enough times
|
|
106
|
-
// 2. FP rate is below threshold
|
|
107
|
-
// 3. Has at least some matches (not a dead rule)
|
|
108
|
-
if (fpRate <= maxFPRate && stat.totalMatches > 0) {
|
|
109
|
-
candidates.push({ rule, stats: { ...stat }, fpRate });
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
return candidates;
|
|
113
|
-
}
|
|
114
|
-
/** Get stats for a specific rule */
|
|
115
|
-
getStats(ruleId) {
|
|
116
|
-
const stat = this.stats.get(ruleId);
|
|
117
|
-
return stat ? { ...stat } : undefined;
|
|
118
|
-
}
|
|
119
|
-
/** Get all shadow rule stats */
|
|
120
|
-
getAllStats() {
|
|
121
|
-
return new Map(Array.from(this.stats.entries()).map(([k, v]) => [k, { ...v }]));
|
|
122
|
-
}
|
|
123
|
-
/** Number of shadow rules */
|
|
124
|
-
size() {
|
|
125
|
-
return this.rules.length;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
//# sourceMappingURL=shadow-evaluator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"shadow-evaluator.js","sourceRoot":"","sources":["../src/shadow-evaluator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAoBH,MAAM,OAAO,eAAe;IACT,KAAK,GAAc,EAAE,CAAC;IACtB,KAAK,GAAG,IAAI,GAAG,EAA2B,CAAC;IAC3C,gBAAgB,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE9D,qDAAqD;IACrD,OAAO,CAAC,IAAa;QACnB,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;YAAE,OAAO,CAAC,QAAQ;QAC9D,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE;YACtB,MAAM,EAAE,IAAI,CAAC,EAAE;YACf,gBAAgB,EAAE,CAAC;YACnB,YAAY,EAAE,CAAC;YACf,sBAAsB,EAAE,CAAC;YACzB,uBAAuB,EAAE,CAAC;YAC1B,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE;SACrB,CAAC,CAAC;IACL,CAAC;IAED,2EAA2E;IAC3E,QAAQ,CAAC,KAAiB;QACxB,MAAM,OAAO,GAAe,EAAE,CAAC;QAE/B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACrC,IAAI,CAAC,IAAI;gBAAE,SAAS;YAEpB,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAE3B,2CAA2C;YAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;YACjC,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC;gBACpD,CAAC,CAAC,SAAS,CAAC,UAAU;gBACtB,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YAExC,IAAI,OAAO,GAAG,KAAK,CAAC;YACpB,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;gBAC9B,MAAM,CAAC,GAAG,IAA0C,CAAC;gBACrD,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,CAAW,CAAC;gBACnC,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,CAAW,CAAC;gBACnC,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK;oBAAE,SAAS;gBAE/B,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC;gBAC1D,IAAI,CAAC;oBACH,IAAI,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;oBAC7C,IAAI,CAAC,KAAK,EAAE,CAAC;wBACX,KAAK,GAAG,IAAI,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;wBAC/B,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;oBAC1C,CAAC;oBACD,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;wBACrB,OAAO,GAAG,IAAI,CAAC;wBACf,MAAM;oBACR,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,gBAAgB;gBAClB,CAAC;YACH,CAAC;YAED,IAAI,OAAO,EAAE,CAAC;gBACZ,IAAI,CAAC,YAAY,EAAE,CAAC;gBACpB,OAAO,CAAC,IAAI,CAAC;oBACX,IAAI;oBACJ,iBAAiB,EAAE,CAAC,QAAQ,CAAC;oBAC7B,eAAe,EAAE,CAAC,cAAc,CAAC;oBACjC,UAAU,EAAE,GAAG,EAAE,yCAAyC;oBAC1D,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;iBACpC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,6CAA6C;IAC7C,cAAc,CAAC,MAAc,EAAE,cAAuB;QACpD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,IAAI,cAAc,EAAE,CAAC;YACnB,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAChC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,uBAAuB,EAAE,CAAC;QACjC,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,sBAAsB,CACpB,YAAoB,KAAK,EACzB,iBAAyB,IAAI;QAE7B,MAAM,UAAU,GAAyB,EAAE,CAAC;QAE5C,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACrC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,gBAAgB,GAAG,cAAc;gBAAE,SAAS;YAE9D,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,GAAG,CAAC;gBAClC,CAAC,CAAC,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC,YAAY;gBAClD,CAAC,CAAC,CAAC,CAAC;YAEN,mBAAmB;YACnB,qCAAqC;YACrC,gCAAgC;YAChC,iDAAiD;YACjD,IAAI,MAAM,IAAI,SAAS,IAAI,IAAI,CAAC,YAAY,GAAG,CAAC,EAAE,CAAC;gBACjD,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,GAAG,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YACxD,CAAC;QACH,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,oCAAoC;IACpC,QAAQ,CAAC,MAAc;QACrB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpC,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACxC,CAAC;IAED,gCAAgC;IAChC,WAAW;QACT,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAClF,CAAC;IAED,6BAA6B;IAC7B,IAAI;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IAC3B,CAAC;CACF"}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Skill Behavioral Fingerprint
|
|
3
|
-
*
|
|
4
|
-
* Tracks what each skill "normally does" across invocations, then detects
|
|
5
|
-
* behavioral drift when a previously-trusted skill starts acting differently.
|
|
6
|
-
*
|
|
7
|
-
* Solves the "installed then turns malicious" scenario:
|
|
8
|
-
* - First N invocations: build fingerprint (what APIs, what patterns, what scope)
|
|
9
|
-
* - After fingerprint stabilizes: flag any deviation as anomaly
|
|
10
|
-
*
|
|
11
|
-
* @module agent-threat-rules/skill-fingerprint
|
|
12
|
-
*/
|
|
13
|
-
import type { AgentEvent } from './types.js';
|
|
14
|
-
/** Behavioral capabilities observed for a skill */
|
|
15
|
-
interface SkillCapabilities {
|
|
16
|
-
/** Seen filesystem operations (read/write/delete) */
|
|
17
|
-
readonly filesystemOps: ReadonlySet<string>;
|
|
18
|
-
/** Seen network destinations (hostnames) */
|
|
19
|
-
readonly networkTargets: ReadonlySet<string>;
|
|
20
|
-
/** Seen environment variable accesses */
|
|
21
|
-
readonly envAccesses: ReadonlySet<string>;
|
|
22
|
-
/** Seen child process executions */
|
|
23
|
-
readonly processExecs: ReadonlySet<string>;
|
|
24
|
-
/** Seen output patterns (categories: data, error, redirect, exfiltration) */
|
|
25
|
-
readonly outputPatterns: ReadonlySet<string>;
|
|
26
|
-
}
|
|
27
|
-
/** Immutable fingerprint snapshot */
|
|
28
|
-
export interface SkillFingerprint {
|
|
29
|
-
readonly skillName: string;
|
|
30
|
-
readonly invocationCount: number;
|
|
31
|
-
readonly firstSeen: number;
|
|
32
|
-
readonly lastSeen: number;
|
|
33
|
-
readonly isStable: boolean;
|
|
34
|
-
readonly capabilities: SkillCapabilities;
|
|
35
|
-
/** Hash of capabilities for quick comparison */
|
|
36
|
-
readonly capabilityHash: string;
|
|
37
|
-
}
|
|
38
|
-
/** Anomaly when behavior deviates from fingerprint */
|
|
39
|
-
export interface BehaviorAnomaly {
|
|
40
|
-
readonly skillName: string;
|
|
41
|
-
readonly anomalyType: 'new_filesystem_op' | 'new_network_target' | 'new_env_access' | 'new_process_exec' | 'new_output_pattern' | 'capability_expansion';
|
|
42
|
-
readonly description: string;
|
|
43
|
-
readonly severity: 'low' | 'medium' | 'high' | 'critical';
|
|
44
|
-
readonly newValue: string;
|
|
45
|
-
readonly timestamp: number;
|
|
46
|
-
}
|
|
47
|
-
export interface SkillFingerprintConfig {
|
|
48
|
-
/** Minimum invocations before fingerprint can stabilize (default: 10) */
|
|
49
|
-
stabilityThreshold?: number;
|
|
50
|
-
/** Consecutive clean invocations to mark stable (default: 5) */
|
|
51
|
-
stableStreak?: number;
|
|
52
|
-
}
|
|
53
|
-
export declare class SkillFingerprintStore {
|
|
54
|
-
private readonly fingerprints;
|
|
55
|
-
private readonly stabilityThreshold;
|
|
56
|
-
private readonly stableStreak;
|
|
57
|
-
constructor(config?: SkillFingerprintConfig);
|
|
58
|
-
/**
|
|
59
|
-
* Record a skill invocation and detect behavioral anomalies.
|
|
60
|
-
* Returns anomalies if the fingerprint was stable and new capabilities appeared.
|
|
61
|
-
*/
|
|
62
|
-
recordInvocation(skillName: string, event: AgentEvent): readonly BehaviorAnomaly[];
|
|
63
|
-
/**
|
|
64
|
-
* Get an immutable fingerprint snapshot for a skill.
|
|
65
|
-
*/
|
|
66
|
-
getFingerprint(skillName: string): SkillFingerprint | undefined;
|
|
67
|
-
/** Get all tracked skill names */
|
|
68
|
-
getTrackedSkills(): string[];
|
|
69
|
-
/** Get count of stable fingerprints */
|
|
70
|
-
getStableCount(): number;
|
|
71
|
-
/** Get total tracked skills */
|
|
72
|
-
getTrackedCount(): number;
|
|
73
|
-
/**
|
|
74
|
-
* Reset a skill's fingerprint (e.g., after a legitimate update).
|
|
75
|
-
*/
|
|
76
|
-
resetFingerprint(skillName: string): void;
|
|
77
|
-
/**
|
|
78
|
-
* Evict fingerprints not seen since cutoffMs ago.
|
|
79
|
-
*/
|
|
80
|
-
cleanup(cutoffMs: number): number;
|
|
81
|
-
private getOrCreate;
|
|
82
|
-
private computeCapabilityHash;
|
|
83
|
-
}
|
|
84
|
-
export {};
|
|
85
|
-
//# sourceMappingURL=skill-fingerprint.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"skill-fingerprint.d.ts","sourceRoot":"","sources":["../src/skill-fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAU7C,mDAAmD;AACnD,UAAU,iBAAiB;IACzB,qDAAqD;IACrD,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC5C,4CAA4C;IAC5C,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC7C,yCAAyC;IACzC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC1C,oCAAoC;IACpC,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3C,6EAA6E;IAC7E,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC9C;AAED,qCAAqC;AACrC,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,iBAAiB,CAAC;IACzC,gDAAgD;IAChD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,sDAAsD;AACtD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAChB,mBAAmB,GACnB,oBAAoB,GACpB,gBAAgB,GAChB,kBAAkB,GAClB,oBAAoB,GACpB,sBAAsB,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IAC1D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAsDD,MAAM,WAAW,sBAAsB;IACrC,yEAAyE;IACzE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAyC;IACtE,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAS;IAC5C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAE1B,MAAM,CAAC,EAAE,sBAAsB;IAK3C;;;OAGG;IACH,gBAAgB,CACd,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,UAAU,GAChB,SAAS,eAAe,EAAE;IA8H7B;;OAEG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAqB/D,kCAAkC;IAClC,gBAAgB,IAAI,MAAM,EAAE;IAI5B,uCAAuC;IACvC,cAAc,IAAI,MAAM;IAQxB,+BAA+B;IAC/B,eAAe,IAAI,MAAM;IAIzB;;OAEG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAIzC;;OAEG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAgBjC,OAAO,CAAC,WAAW;IAkCnB,OAAO,CAAC,qBAAqB;CAU9B"}
|
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Skill Behavioral Fingerprint
|
|
3
|
-
*
|
|
4
|
-
* Tracks what each skill "normally does" across invocations, then detects
|
|
5
|
-
* behavioral drift when a previously-trusted skill starts acting differently.
|
|
6
|
-
*
|
|
7
|
-
* Solves the "installed then turns malicious" scenario:
|
|
8
|
-
* - First N invocations: build fingerprint (what APIs, what patterns, what scope)
|
|
9
|
-
* - After fingerprint stabilizes: flag any deviation as anomaly
|
|
10
|
-
*
|
|
11
|
-
* @module agent-threat-rules/skill-fingerprint
|
|
12
|
-
*/
|
|
13
|
-
import { createHash } from 'node:crypto';
|
|
14
|
-
import { extractCapabilities as sharedExtractCapabilities, } from './capability-extractor.js';
|
|
15
|
-
// ---------------------------------------------------------------------------
|
|
16
|
-
// Capability extraction (shared with tier0-invariant.ts)
|
|
17
|
-
// ---------------------------------------------------------------------------
|
|
18
|
-
/** Wrapper for shared extractCapabilities, mapping to local format */
|
|
19
|
-
function extractCapabilities(text) {
|
|
20
|
-
const caps = sharedExtractCapabilities(text);
|
|
21
|
-
return {
|
|
22
|
-
filesystemOps: [...caps.filesystemOps],
|
|
23
|
-
networkTargets: [...caps.networkTargets],
|
|
24
|
-
envAccesses: [...caps.envAccesses],
|
|
25
|
-
processExecs: [...caps.processExecs],
|
|
26
|
-
outputPatterns: [...caps.outputPatterns],
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
// ---------------------------------------------------------------------------
|
|
30
|
-
// Fingerprint Store
|
|
31
|
-
// ---------------------------------------------------------------------------
|
|
32
|
-
/** Default invocations needed before fingerprint is considered stable */
|
|
33
|
-
const DEFAULT_STABILITY_THRESHOLD = 10;
|
|
34
|
-
/** Consecutive invocations with no new capabilities to mark stable */
|
|
35
|
-
const DEFAULT_STABLE_STREAK = 5;
|
|
36
|
-
/** Maximum number of skills to track */
|
|
37
|
-
const MAX_SKILLS = 5_000;
|
|
38
|
-
export class SkillFingerprintStore {
|
|
39
|
-
fingerprints = new Map();
|
|
40
|
-
stabilityThreshold;
|
|
41
|
-
stableStreak;
|
|
42
|
-
constructor(config) {
|
|
43
|
-
this.stabilityThreshold = config?.stabilityThreshold ?? DEFAULT_STABILITY_THRESHOLD;
|
|
44
|
-
this.stableStreak = config?.stableStreak ?? DEFAULT_STABLE_STREAK;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Record a skill invocation and detect behavioral anomalies.
|
|
48
|
-
* Returns anomalies if the fingerprint was stable and new capabilities appeared.
|
|
49
|
-
*/
|
|
50
|
-
recordInvocation(skillName, event) {
|
|
51
|
-
const now = Date.now();
|
|
52
|
-
const fp = this.getOrCreate(skillName, now);
|
|
53
|
-
fp.invocationCount++;
|
|
54
|
-
fp.lastSeen = now;
|
|
55
|
-
// Extract capabilities from event content + fields
|
|
56
|
-
const content = [
|
|
57
|
-
event.content ?? '',
|
|
58
|
-
event.fields?.['tool_args'] ?? '',
|
|
59
|
-
event.fields?.['tool_response'] ?? '',
|
|
60
|
-
].join('\n');
|
|
61
|
-
const caps = extractCapabilities(content);
|
|
62
|
-
// Check for anomalies (only if fingerprint is stable)
|
|
63
|
-
const anomalies = [];
|
|
64
|
-
const isStable = fp.stableHash !== null;
|
|
65
|
-
if (isStable) {
|
|
66
|
-
// Detect NEW capabilities not in the stable fingerprint
|
|
67
|
-
for (const op of caps.filesystemOps) {
|
|
68
|
-
if (!fp.filesystemOps.has(op)) {
|
|
69
|
-
anomalies.push({
|
|
70
|
-
skillName,
|
|
71
|
-
anomalyType: 'new_filesystem_op',
|
|
72
|
-
description: `Skill "${skillName}" performing new filesystem operation: ${op} (not in baseline)`,
|
|
73
|
-
severity: op === 'delete' ? 'critical' : op === 'write' ? 'high' : 'medium',
|
|
74
|
-
newValue: op,
|
|
75
|
-
timestamp: now,
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
for (const target of caps.networkTargets) {
|
|
80
|
-
if (!fp.networkTargets.has(target)) {
|
|
81
|
-
anomalies.push({
|
|
82
|
-
skillName,
|
|
83
|
-
anomalyType: 'new_network_target',
|
|
84
|
-
description: `Skill "${skillName}" contacting new network target: ${target}`,
|
|
85
|
-
severity: 'high',
|
|
86
|
-
newValue: target,
|
|
87
|
-
timestamp: now,
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
for (const env of caps.envAccesses) {
|
|
92
|
-
if (!fp.envAccesses.has(env)) {
|
|
93
|
-
const isSensitive = /(?:KEY|SECRET|TOKEN|PASSWORD|CREDENTIAL)/i.test(env);
|
|
94
|
-
anomalies.push({
|
|
95
|
-
skillName,
|
|
96
|
-
anomalyType: 'new_env_access',
|
|
97
|
-
description: `Skill "${skillName}" accessing new env var: ${env}`,
|
|
98
|
-
severity: isSensitive ? 'critical' : 'medium',
|
|
99
|
-
newValue: env,
|
|
100
|
-
timestamp: now,
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
for (const proc of caps.processExecs) {
|
|
105
|
-
if (!fp.processExecs.has(proc)) {
|
|
106
|
-
anomalies.push({
|
|
107
|
-
skillName,
|
|
108
|
-
anomalyType: 'new_process_exec',
|
|
109
|
-
description: `Skill "${skillName}" executing new process: ${proc}`,
|
|
110
|
-
severity: 'critical',
|
|
111
|
-
newValue: proc,
|
|
112
|
-
timestamp: now,
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
for (const pat of caps.outputPatterns) {
|
|
117
|
-
if (!fp.outputPatterns.has(pat)) {
|
|
118
|
-
anomalies.push({
|
|
119
|
-
skillName,
|
|
120
|
-
anomalyType: 'new_output_pattern',
|
|
121
|
-
description: `Skill "${skillName}" exhibiting new pattern: ${pat}`,
|
|
122
|
-
severity: pat === 'exfiltration' ? 'critical' : 'high',
|
|
123
|
-
newValue: pat,
|
|
124
|
-
timestamp: now,
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
// Update fingerprint with observed capabilities
|
|
130
|
-
let newCapsSeen = false;
|
|
131
|
-
for (const op of caps.filesystemOps) {
|
|
132
|
-
if (!fp.filesystemOps.has(op)) {
|
|
133
|
-
fp.filesystemOps.add(op);
|
|
134
|
-
newCapsSeen = true;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
for (const t of caps.networkTargets) {
|
|
138
|
-
if (!fp.networkTargets.has(t)) {
|
|
139
|
-
fp.networkTargets.add(t);
|
|
140
|
-
newCapsSeen = true;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
for (const e of caps.envAccesses) {
|
|
144
|
-
if (!fp.envAccesses.has(e)) {
|
|
145
|
-
fp.envAccesses.add(e);
|
|
146
|
-
newCapsSeen = true;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
for (const p of caps.processExecs) {
|
|
150
|
-
if (!fp.processExecs.has(p)) {
|
|
151
|
-
fp.processExecs.add(p);
|
|
152
|
-
newCapsSeen = true;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
for (const o of caps.outputPatterns) {
|
|
156
|
-
if (!fp.outputPatterns.has(o)) {
|
|
157
|
-
fp.outputPatterns.add(o);
|
|
158
|
-
newCapsSeen = true;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
// Track stability
|
|
162
|
-
if (!isStable) {
|
|
163
|
-
if (newCapsSeen) {
|
|
164
|
-
fp.stableStreak = 0;
|
|
165
|
-
}
|
|
166
|
-
else {
|
|
167
|
-
fp.stableStreak++;
|
|
168
|
-
}
|
|
169
|
-
// Mark stable when threshold met
|
|
170
|
-
if (fp.invocationCount >= this.stabilityThreshold &&
|
|
171
|
-
fp.stableStreak >= this.stableStreak) {
|
|
172
|
-
fp.stableHash = this.computeCapabilityHash(fp);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
return anomalies;
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
|
-
* Get an immutable fingerprint snapshot for a skill.
|
|
179
|
-
*/
|
|
180
|
-
getFingerprint(skillName) {
|
|
181
|
-
const fp = this.fingerprints.get(skillName);
|
|
182
|
-
if (!fp)
|
|
183
|
-
return undefined;
|
|
184
|
-
return {
|
|
185
|
-
skillName: fp.skillName,
|
|
186
|
-
invocationCount: fp.invocationCount,
|
|
187
|
-
firstSeen: fp.firstSeen,
|
|
188
|
-
lastSeen: fp.lastSeen,
|
|
189
|
-
isStable: fp.stableHash !== null,
|
|
190
|
-
capabilities: {
|
|
191
|
-
filesystemOps: new Set(fp.filesystemOps),
|
|
192
|
-
networkTargets: new Set(fp.networkTargets),
|
|
193
|
-
envAccesses: new Set(fp.envAccesses),
|
|
194
|
-
processExecs: new Set(fp.processExecs),
|
|
195
|
-
outputPatterns: new Set(fp.outputPatterns),
|
|
196
|
-
},
|
|
197
|
-
capabilityHash: fp.stableHash ?? this.computeCapabilityHash(fp),
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
/** Get all tracked skill names */
|
|
201
|
-
getTrackedSkills() {
|
|
202
|
-
return [...this.fingerprints.keys()];
|
|
203
|
-
}
|
|
204
|
-
/** Get count of stable fingerprints */
|
|
205
|
-
getStableCount() {
|
|
206
|
-
let count = 0;
|
|
207
|
-
for (const fp of this.fingerprints.values()) {
|
|
208
|
-
if (fp.stableHash !== null)
|
|
209
|
-
count++;
|
|
210
|
-
}
|
|
211
|
-
return count;
|
|
212
|
-
}
|
|
213
|
-
/** Get total tracked skills */
|
|
214
|
-
getTrackedCount() {
|
|
215
|
-
return this.fingerprints.size;
|
|
216
|
-
}
|
|
217
|
-
/**
|
|
218
|
-
* Reset a skill's fingerprint (e.g., after a legitimate update).
|
|
219
|
-
*/
|
|
220
|
-
resetFingerprint(skillName) {
|
|
221
|
-
this.fingerprints.delete(skillName);
|
|
222
|
-
}
|
|
223
|
-
/**
|
|
224
|
-
* Evict fingerprints not seen since cutoffMs ago.
|
|
225
|
-
*/
|
|
226
|
-
cleanup(cutoffMs) {
|
|
227
|
-
const cutoff = Date.now() - cutoffMs;
|
|
228
|
-
let evicted = 0;
|
|
229
|
-
for (const [name, fp] of this.fingerprints) {
|
|
230
|
-
if (fp.lastSeen < cutoff) {
|
|
231
|
-
this.fingerprints.delete(name);
|
|
232
|
-
evicted++;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
return evicted;
|
|
236
|
-
}
|
|
237
|
-
// -----------------------------------------------------------------------
|
|
238
|
-
// Private
|
|
239
|
-
// -----------------------------------------------------------------------
|
|
240
|
-
getOrCreate(skillName, now) {
|
|
241
|
-
const existing = this.fingerprints.get(skillName);
|
|
242
|
-
if (existing)
|
|
243
|
-
return existing;
|
|
244
|
-
// Evict oldest if at capacity
|
|
245
|
-
if (this.fingerprints.size >= MAX_SKILLS) {
|
|
246
|
-
let oldestName;
|
|
247
|
-
let oldestTime = Infinity;
|
|
248
|
-
for (const [name, fp] of this.fingerprints) {
|
|
249
|
-
if (fp.lastSeen < oldestTime) {
|
|
250
|
-
oldestTime = fp.lastSeen;
|
|
251
|
-
oldestName = name;
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
if (oldestName)
|
|
255
|
-
this.fingerprints.delete(oldestName);
|
|
256
|
-
}
|
|
257
|
-
const fp = {
|
|
258
|
-
skillName,
|
|
259
|
-
invocationCount: 0,
|
|
260
|
-
firstSeen: now,
|
|
261
|
-
lastSeen: now,
|
|
262
|
-
filesystemOps: new Set(),
|
|
263
|
-
networkTargets: new Set(),
|
|
264
|
-
envAccesses: new Set(),
|
|
265
|
-
processExecs: new Set(),
|
|
266
|
-
outputPatterns: new Set(),
|
|
267
|
-
stableHash: null,
|
|
268
|
-
stableStreak: 0,
|
|
269
|
-
};
|
|
270
|
-
this.fingerprints.set(skillName, fp);
|
|
271
|
-
return fp;
|
|
272
|
-
}
|
|
273
|
-
computeCapabilityHash(fp) {
|
|
274
|
-
const parts = [
|
|
275
|
-
[...fp.filesystemOps].sort().join(','),
|
|
276
|
-
[...fp.networkTargets].sort().join(','),
|
|
277
|
-
[...fp.envAccesses].sort().join(','),
|
|
278
|
-
[...fp.processExecs].sort().join(','),
|
|
279
|
-
[...fp.outputPatterns].sort().join(','),
|
|
280
|
-
];
|
|
281
|
-
return createHash('sha256').update(parts.join('|')).digest('hex').slice(0, 16);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
//# sourceMappingURL=skill-fingerprint.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"skill-fingerprint.js","sourceRoot":"","sources":["../src/skill-fingerprint.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tier 0: Invariant Enforcement
|
|
3
|
-
*
|
|
4
|
-
* Hard boundaries that enforce what a skill is ALLOWED to do,
|
|
5
|
-
* regardless of what its description says or how it phrases requests.
|
|
6
|
-
*
|
|
7
|
-
* This is NOT pattern matching. It is permission checking.
|
|
8
|
-
* A skill declares capabilities in its manifest. Any action outside
|
|
9
|
-
* the manifest is immediately denied with severity=critical.
|
|
10
|
-
*
|
|
11
|
-
* Inspired by Tesla's AEB (Automatic Emergency Braking):
|
|
12
|
-
* it doesn't care what the neural network thinks -- it enforces physics.
|
|
13
|
-
*
|
|
14
|
-
* @module agent-threat-rules/tier0-invariant
|
|
15
|
-
*/
|
|
16
|
-
import type { AgentEvent, ATRMatch } from './types.js';
|
|
17
|
-
/** Skill capability manifest -- declares what a skill is allowed to do */
|
|
18
|
-
export interface SkillManifest {
|
|
19
|
-
readonly skillId: string;
|
|
20
|
-
readonly allowedPaths?: readonly string[];
|
|
21
|
-
readonly allowedHosts?: readonly string[];
|
|
22
|
-
readonly allowedEnvVars?: readonly string[];
|
|
23
|
-
readonly allowedCommands?: readonly string[];
|
|
24
|
-
readonly maxNetworkCalls?: number;
|
|
25
|
-
readonly allowConfigModification?: boolean;
|
|
26
|
-
}
|
|
27
|
-
export type InvariantViolationType = 'path_scope' | 'host_scope' | 'env_scope' | 'command_scope' | 'config_modification' | 'network_limit';
|
|
28
|
-
/** Result when an invariant is violated */
|
|
29
|
-
export interface InvariantViolation {
|
|
30
|
-
readonly skillId: string;
|
|
31
|
-
readonly violationType: InvariantViolationType;
|
|
32
|
-
readonly description: string;
|
|
33
|
-
readonly observedValue: string;
|
|
34
|
-
readonly allowedValues: readonly string[];
|
|
35
|
-
}
|
|
36
|
-
export declare class InvariantChecker {
|
|
37
|
-
private readonly manifests;
|
|
38
|
-
constructor(manifests: ReadonlyMap<string, SkillManifest> | SkillManifest[]);
|
|
39
|
-
/**
|
|
40
|
-
* Check an event against the skill's manifest.
|
|
41
|
-
* Returns empty array if no violations (or no manifest for the skill).
|
|
42
|
-
*/
|
|
43
|
-
check(event: AgentEvent): readonly InvariantViolation[];
|
|
44
|
-
/** Build a synthetic ATRMatch from an invariant violation */
|
|
45
|
-
buildDenyMatch(violation: InvariantViolation): ATRMatch;
|
|
46
|
-
/** Resolve skill ID from event metadata */
|
|
47
|
-
private resolveSkillId;
|
|
48
|
-
}
|
|
49
|
-
//# sourceMappingURL=tier0-invariant.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tier0-invariant.d.ts","sourceRoot":"","sources":["../src/tier0-invariant.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAwB,MAAM,YAAY,CAAC;AA6B7E,0EAA0E;AAC1E,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,OAAO,CAAC;CAC5C;AAED,MAAM,MAAM,sBAAsB,GAC9B,YAAY,GACZ,YAAY,GACZ,WAAW,GACX,eAAe,GACf,qBAAqB,GACrB,eAAe,CAAC;AAEpB,2CAA2C;AAC3C,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,EAAE,sBAAsB,CAAC;IAC/C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3C;AAMD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqC;gBAEnD,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,aAAa,EAAE;IAY3E;;;OAGG;IACH,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,kBAAkB,EAAE;IAsGvD,6DAA6D;IAC7D,cAAc,CAAC,SAAS,EAAE,kBAAkB,GAAG,QAAQ;IA+BvD,2CAA2C;IAC3C,OAAO,CAAC,cAAc;CAKvB"}
|