agent-assurance 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -0
- package/CODE_OF_CONDUCT.md +59 -0
- package/CONTRIBUTING.md +19 -0
- package/LICENSE +21 -0
- package/NOTICE +15 -0
- package/README.md +89 -0
- package/SECURITY.md +13 -0
- package/attacks/exfil.yaml +46 -0
- package/attacks/injection.yaml +51 -0
- package/attacks/tools.yaml +29 -0
- package/bun.lock +484 -0
- package/dist/adapter/exec.d.ts +10 -0
- package/dist/adapter/http.d.ts +7 -0
- package/dist/adapter/index.d.ts +5 -0
- package/dist/adapter/sdk.d.ts +7 -0
- package/dist/adapter/types.d.ts +41 -0
- package/dist/attacks/index.d.ts +3 -0
- package/dist/attacks/load.d.ts +33 -0
- package/dist/attacks/schema.d.ts +206 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +24731 -0
- package/dist/graph/build.d.ts +60 -0
- package/dist/graph/flows.d.ts +14 -0
- package/dist/graph/index.d.ts +4 -0
- package/dist/graph/trifecta.d.ts +13 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +22956 -0
- package/dist/manifest/index.d.ts +3 -0
- package/dist/manifest/load.d.ts +25 -0
- package/dist/manifest/schema.d.ts +136 -0
- package/dist/policy/protected-paths.d.ts +56 -0
- package/dist/report/findings.d.ts +52 -0
- package/dist/report/human.d.ts +19 -0
- package/dist/report/index.d.ts +5 -0
- package/dist/report/json.d.ts +39 -0
- package/dist/report/sarif.d.ts +57 -0
- package/dist/runner/index.d.ts +5 -0
- package/dist/runner/oracle.d.ts +46 -0
- package/dist/runner/run.d.ts +38 -0
- package/dist/runner/sandbox.d.ts +27 -0
- package/dist/runner/side-effect.d.ts +32 -0
- package/dist/scan.d.ts +43 -0
- package/package.json +60 -0
- package/policy-pack/README.md +105 -0
- package/policy-pack/hooks/guard-config-change.mjs +61 -0
- package/policy-pack/hooks/guard-protected-paths.mjs +65 -0
- package/policy-pack/managed-settings.json +18 -0
- package/policy-pack/protected-paths.json +18 -0
- package/policy-pack/settings.json +59 -0
- package/policy-pack/spike-bypass.sh +72 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Target Adapter interface (FR-1.1).
|
|
3
|
+
*
|
|
4
|
+
* The adapter is the single seam AAL Core uses to *run* a target agent — it knows nothing
|
|
5
|
+
* about the agent's framework. Every concrete adapter (exec/http/sdk) returns the same shape:
|
|
6
|
+
* the agent's text AND its structured tool calls. Capturing `toolCalls` (not just `text`) is
|
|
7
|
+
* what makes execution-layer side-effect detection possible (FR-4).
|
|
8
|
+
*/
|
|
9
|
+
import type { Result } from "neverthrow";
|
|
10
|
+
/** A single tool invocation the target agent emitted during a run. */
|
|
11
|
+
export interface ToolCall {
|
|
12
|
+
tool: string;
|
|
13
|
+
args: unknown;
|
|
14
|
+
}
|
|
15
|
+
/** The observable result of one agent run: its prose and every tool it invoked. */
|
|
16
|
+
export interface AgentRun {
|
|
17
|
+
text: string;
|
|
18
|
+
toolCalls: ToolCall[];
|
|
19
|
+
}
|
|
20
|
+
/** A typed adapter failure. Fail-closed: any of these ⇒ the attack result is `not_verified`. */
|
|
21
|
+
export type AdapterError = {
|
|
22
|
+
kind: "spawn";
|
|
23
|
+
message: string;
|
|
24
|
+
} | {
|
|
25
|
+
kind: "timeout";
|
|
26
|
+
message: string;
|
|
27
|
+
} | {
|
|
28
|
+
kind: "protocol";
|
|
29
|
+
message: string;
|
|
30
|
+
} | {
|
|
31
|
+
kind: "exit";
|
|
32
|
+
code: number | null;
|
|
33
|
+
message: string;
|
|
34
|
+
} | {
|
|
35
|
+
kind: "unsupported";
|
|
36
|
+
message: string;
|
|
37
|
+
};
|
|
38
|
+
/** How AAL Core runs a target agent. One input in, one observed run out. */
|
|
39
|
+
export interface TargetAdapter {
|
|
40
|
+
runAgent(input: string): Promise<Result<AgentRun, AdapterError>>;
|
|
41
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type Result } from "neverthrow";
|
|
2
|
+
import { type Attack } from "./schema";
|
|
3
|
+
export type AttackError = {
|
|
4
|
+
kind: "read";
|
|
5
|
+
path: string;
|
|
6
|
+
message: string;
|
|
7
|
+
} | {
|
|
8
|
+
kind: "parse";
|
|
9
|
+
path: string;
|
|
10
|
+
message: string;
|
|
11
|
+
} | {
|
|
12
|
+
kind: "validation";
|
|
13
|
+
path: string;
|
|
14
|
+
message: string;
|
|
15
|
+
issues: readonly AttackIssue[];
|
|
16
|
+
} | {
|
|
17
|
+
kind: "empty";
|
|
18
|
+
path: string;
|
|
19
|
+
message: string;
|
|
20
|
+
} | {
|
|
21
|
+
kind: "duplicate";
|
|
22
|
+
path: string;
|
|
23
|
+
message: string;
|
|
24
|
+
ids: readonly string[];
|
|
25
|
+
};
|
|
26
|
+
export interface AttackIssue {
|
|
27
|
+
path: string;
|
|
28
|
+
message: string;
|
|
29
|
+
}
|
|
30
|
+
/** Load + validate one corpus file's attacks. */
|
|
31
|
+
export declare function loadAttackFile(path: string): Result<Attack[], AttackError>;
|
|
32
|
+
/** Load every attack file in a directory, flatten, and enforce id uniqueness. */
|
|
33
|
+
export declare function loadAttackCorpus(dir: string): Result<Attack[], AttackError>;
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attack Library schema (FR-2).
|
|
3
|
+
*
|
|
4
|
+
* Attacks are *data, not code* — contributors extend coverage by editing YAML, never engine
|
|
5
|
+
* internals (this productizes the Standard's injection_cases.yaml). Every attack maps to the
|
|
6
|
+
* OWASP Top 10 for Agentic Applications (ASI01–ASI10) and a MITRE ATLAS technique, and declares
|
|
7
|
+
* a machine-checkable success condition (assert predicates and/or an LLM rubric).
|
|
8
|
+
*
|
|
9
|
+
* Payload hygiene: corpus `input`s use synthetic, reserved indicators only (example/.test/.invalid
|
|
10
|
+
* domains, obviously-demonstrative markers) — never real secrets, targets, or weaponized
|
|
11
|
+
* jailbreaks. Findings never echo them back: they store the sha256 (hash-not-text, NFR-3).
|
|
12
|
+
*/
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
export declare const AttackClass: z.ZodEnum<{
|
|
15
|
+
"prompt-injection": "prompt-injection";
|
|
16
|
+
"indirect-injection": "indirect-injection";
|
|
17
|
+
"tool-poisoning": "tool-poisoning";
|
|
18
|
+
"tool-shadowing": "tool-shadowing";
|
|
19
|
+
"mcp-rug-pull": "mcp-rug-pull";
|
|
20
|
+
"data-exfil": "data-exfil";
|
|
21
|
+
"trifecta-exploit": "trifecta-exploit";
|
|
22
|
+
"config-rce": "config-rce";
|
|
23
|
+
}>;
|
|
24
|
+
export type AttackClass = z.infer<typeof AttackClass>;
|
|
25
|
+
/** OWASP Top 10 for Agentic Applications (2026). */
|
|
26
|
+
export declare const OwaspAsi: z.ZodEnum<{
|
|
27
|
+
ASI01: "ASI01";
|
|
28
|
+
ASI02: "ASI02";
|
|
29
|
+
ASI03: "ASI03";
|
|
30
|
+
ASI04: "ASI04";
|
|
31
|
+
ASI05: "ASI05";
|
|
32
|
+
ASI06: "ASI06";
|
|
33
|
+
ASI07: "ASI07";
|
|
34
|
+
ASI08: "ASI08";
|
|
35
|
+
ASI09: "ASI09";
|
|
36
|
+
ASI10: "ASI10";
|
|
37
|
+
}>;
|
|
38
|
+
export type OwaspAsi = z.infer<typeof OwaspAsi>;
|
|
39
|
+
/** A MITRE ATLAS id, e.g. `AML.T0051` (LLM prompt injection) or a tactic `AML.TA0000`. */
|
|
40
|
+
export declare const AtlasId: z.ZodString;
|
|
41
|
+
/**
|
|
42
|
+
* One success predicate. Each evaluates to *did the attack succeed* (i.e. the unsafe condition
|
|
43
|
+
* holds) — TRUE means the target is vulnerable. Composed with OR across the `assert` array.
|
|
44
|
+
*/
|
|
45
|
+
export declare const Assertion: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
46
|
+
type: z.ZodLiteral<"text-contains">;
|
|
47
|
+
value: z.ZodString;
|
|
48
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
49
|
+
type: z.ZodLiteral<"text-matches">;
|
|
50
|
+
pattern: z.ZodString;
|
|
51
|
+
flags: z.ZodOptional<z.ZodString>;
|
|
52
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
53
|
+
type: z.ZodLiteral<"tool-called">;
|
|
54
|
+
tool: z.ZodString;
|
|
55
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
56
|
+
type: z.ZodLiteral<"side-effect-fired">;
|
|
57
|
+
sideEffect: z.ZodEnum<{
|
|
58
|
+
read: "read";
|
|
59
|
+
write: "write";
|
|
60
|
+
"external-egress": "external-egress";
|
|
61
|
+
"code-exec": "code-exec";
|
|
62
|
+
}>;
|
|
63
|
+
}, z.core.$strip>], "type">;
|
|
64
|
+
export type Assertion = z.infer<typeof Assertion>;
|
|
65
|
+
/** The attack's machine-checkable success condition. At least one of assert/llmRubric required. */
|
|
66
|
+
export declare const SuccessCondition: z.ZodObject<{
|
|
67
|
+
assert: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
68
|
+
type: z.ZodLiteral<"text-contains">;
|
|
69
|
+
value: z.ZodString;
|
|
70
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
71
|
+
type: z.ZodLiteral<"text-matches">;
|
|
72
|
+
pattern: z.ZodString;
|
|
73
|
+
flags: z.ZodOptional<z.ZodString>;
|
|
74
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
75
|
+
type: z.ZodLiteral<"tool-called">;
|
|
76
|
+
tool: z.ZodString;
|
|
77
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
78
|
+
type: z.ZodLiteral<"side-effect-fired">;
|
|
79
|
+
sideEffect: z.ZodEnum<{
|
|
80
|
+
read: "read";
|
|
81
|
+
write: "write";
|
|
82
|
+
"external-egress": "external-egress";
|
|
83
|
+
"code-exec": "code-exec";
|
|
84
|
+
}>;
|
|
85
|
+
}, z.core.$strip>], "type">>>;
|
|
86
|
+
llmRubric: z.ZodOptional<z.ZodString>;
|
|
87
|
+
}, z.core.$strip>;
|
|
88
|
+
export type SuccessCondition = z.infer<typeof SuccessCondition>;
|
|
89
|
+
export declare const Attack: z.ZodObject<{
|
|
90
|
+
id: z.ZodString;
|
|
91
|
+
class: z.ZodEnum<{
|
|
92
|
+
"prompt-injection": "prompt-injection";
|
|
93
|
+
"indirect-injection": "indirect-injection";
|
|
94
|
+
"tool-poisoning": "tool-poisoning";
|
|
95
|
+
"tool-shadowing": "tool-shadowing";
|
|
96
|
+
"mcp-rug-pull": "mcp-rug-pull";
|
|
97
|
+
"data-exfil": "data-exfil";
|
|
98
|
+
"trifecta-exploit": "trifecta-exploit";
|
|
99
|
+
"config-rce": "config-rce";
|
|
100
|
+
}>;
|
|
101
|
+
owasp: z.ZodEnum<{
|
|
102
|
+
ASI01: "ASI01";
|
|
103
|
+
ASI02: "ASI02";
|
|
104
|
+
ASI03: "ASI03";
|
|
105
|
+
ASI04: "ASI04";
|
|
106
|
+
ASI05: "ASI05";
|
|
107
|
+
ASI06: "ASI06";
|
|
108
|
+
ASI07: "ASI07";
|
|
109
|
+
ASI08: "ASI08";
|
|
110
|
+
ASI09: "ASI09";
|
|
111
|
+
ASI10: "ASI10";
|
|
112
|
+
}>;
|
|
113
|
+
atlas: z.ZodString;
|
|
114
|
+
description: z.ZodOptional<z.ZodString>;
|
|
115
|
+
lang: z.ZodDefault<z.ZodEnum<{
|
|
116
|
+
en: "en";
|
|
117
|
+
ru: "ru";
|
|
118
|
+
}>>;
|
|
119
|
+
input: z.ZodString;
|
|
120
|
+
vars: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
121
|
+
success: z.ZodObject<{
|
|
122
|
+
assert: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
123
|
+
type: z.ZodLiteral<"text-contains">;
|
|
124
|
+
value: z.ZodString;
|
|
125
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
126
|
+
type: z.ZodLiteral<"text-matches">;
|
|
127
|
+
pattern: z.ZodString;
|
|
128
|
+
flags: z.ZodOptional<z.ZodString>;
|
|
129
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
130
|
+
type: z.ZodLiteral<"tool-called">;
|
|
131
|
+
tool: z.ZodString;
|
|
132
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
133
|
+
type: z.ZodLiteral<"side-effect-fired">;
|
|
134
|
+
sideEffect: z.ZodEnum<{
|
|
135
|
+
read: "read";
|
|
136
|
+
write: "write";
|
|
137
|
+
"external-egress": "external-egress";
|
|
138
|
+
"code-exec": "code-exec";
|
|
139
|
+
}>;
|
|
140
|
+
}, z.core.$strip>], "type">>>;
|
|
141
|
+
llmRubric: z.ZodOptional<z.ZodString>;
|
|
142
|
+
}, z.core.$strip>;
|
|
143
|
+
}, z.core.$strip>;
|
|
144
|
+
export type Attack = z.infer<typeof Attack>;
|
|
145
|
+
/** One corpus YAML file: a versioned list of attacks. */
|
|
146
|
+
export declare const AttackFile: z.ZodObject<{
|
|
147
|
+
version: z.ZodOptional<z.ZodString>;
|
|
148
|
+
attacks: z.ZodArray<z.ZodObject<{
|
|
149
|
+
id: z.ZodString;
|
|
150
|
+
class: z.ZodEnum<{
|
|
151
|
+
"prompt-injection": "prompt-injection";
|
|
152
|
+
"indirect-injection": "indirect-injection";
|
|
153
|
+
"tool-poisoning": "tool-poisoning";
|
|
154
|
+
"tool-shadowing": "tool-shadowing";
|
|
155
|
+
"mcp-rug-pull": "mcp-rug-pull";
|
|
156
|
+
"data-exfil": "data-exfil";
|
|
157
|
+
"trifecta-exploit": "trifecta-exploit";
|
|
158
|
+
"config-rce": "config-rce";
|
|
159
|
+
}>;
|
|
160
|
+
owasp: z.ZodEnum<{
|
|
161
|
+
ASI01: "ASI01";
|
|
162
|
+
ASI02: "ASI02";
|
|
163
|
+
ASI03: "ASI03";
|
|
164
|
+
ASI04: "ASI04";
|
|
165
|
+
ASI05: "ASI05";
|
|
166
|
+
ASI06: "ASI06";
|
|
167
|
+
ASI07: "ASI07";
|
|
168
|
+
ASI08: "ASI08";
|
|
169
|
+
ASI09: "ASI09";
|
|
170
|
+
ASI10: "ASI10";
|
|
171
|
+
}>;
|
|
172
|
+
atlas: z.ZodString;
|
|
173
|
+
description: z.ZodOptional<z.ZodString>;
|
|
174
|
+
lang: z.ZodDefault<z.ZodEnum<{
|
|
175
|
+
en: "en";
|
|
176
|
+
ru: "ru";
|
|
177
|
+
}>>;
|
|
178
|
+
input: z.ZodString;
|
|
179
|
+
vars: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
180
|
+
success: z.ZodObject<{
|
|
181
|
+
assert: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
182
|
+
type: z.ZodLiteral<"text-contains">;
|
|
183
|
+
value: z.ZodString;
|
|
184
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
185
|
+
type: z.ZodLiteral<"text-matches">;
|
|
186
|
+
pattern: z.ZodString;
|
|
187
|
+
flags: z.ZodOptional<z.ZodString>;
|
|
188
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
189
|
+
type: z.ZodLiteral<"tool-called">;
|
|
190
|
+
tool: z.ZodString;
|
|
191
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
192
|
+
type: z.ZodLiteral<"side-effect-fired">;
|
|
193
|
+
sideEffect: z.ZodEnum<{
|
|
194
|
+
read: "read";
|
|
195
|
+
write: "write";
|
|
196
|
+
"external-egress": "external-egress";
|
|
197
|
+
"code-exec": "code-exec";
|
|
198
|
+
}>;
|
|
199
|
+
}, z.core.$strip>], "type">>>;
|
|
200
|
+
llmRubric: z.ZodOptional<z.ZodString>;
|
|
201
|
+
}, z.core.$strip>;
|
|
202
|
+
}, z.core.$strip>>;
|
|
203
|
+
}, z.core.$strip>;
|
|
204
|
+
export type AttackFile = z.infer<typeof AttackFile>;
|
|
205
|
+
/** Render an attack's input, substituting `{{var}}` placeholders from its `vars` map. */
|
|
206
|
+
export declare function renderAttackInput(attack: Attack): string;
|
package/dist/cli.d.ts
ADDED