wardproof 0.3.0__tar.gz → 0.3.2__tar.gz
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.
- {wardproof-0.3.0 → wardproof-0.3.2}/PKG-INFO +33 -11
- {wardproof-0.3.0 → wardproof-0.3.2}/README.md +28 -10
- {wardproof-0.3.0 → wardproof-0.3.2}/pyproject.toml +7 -1
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/__init__.py +1 -1
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/cli.py +55 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/.gitignore +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/CONTRIBUTING.md +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/LICENSE +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/SECURITY.md +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/THREAT_MODEL.md +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/benchmarks/README.md +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/benchmarks/corpus.jsonl +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/benchmarks/external/README.md +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/benchmarks/external/__init__.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/benchmarks/external/_screen.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/benchmarks/external/agentdojo.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/benchmarks/external/fetch_data.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/benchmarks/external/injecagent.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/benchmarks/heldout.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/benchmarks/latency.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/benchmarks/run_benchmark.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/examples/agent_to_agent_transfer.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/examples/integrations/README.md +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/examples/integrations/agentkit_guarded.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/examples/integrations/anthropic_tools_guarded.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/examples/integrations/crewai_guarded.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/examples/integrations/langgraph_guarded.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/examples/integrations/mcp_guarded.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/examples/integrations/openai_tools_guarded.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/examples/integrations/skills_guard.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/examples/integrations/venice_guarded.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/examples/morse_injection_blocked_at_action.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/examples/protect_defi_agent.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/examples/protect_mcp_agent.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/examples/protect_rag_app.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/examples/protect_x402_payments.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/agents/__init__.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/agents/base.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/agents/detector.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/agents/responder.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/agents/verifier.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/audit/__init__.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/audit/ledger.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/audit/stix.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/config.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/guardrails/__init__.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/guardrails/_normalize.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/guardrails/base.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/guardrails/mcp_guard.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/guardrails/memory_poisoning.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/guardrails/prompt_injection.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/guardrails/tool_misuse.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/guardrails/transfer.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/guardrails/x402_payment.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/llm/__init__.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/llm/base.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/llm/null.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/llm/ollama_client.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/orchestration/__init__.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/orchestration/engine.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/orchestration/factory.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/sandbox/__init__.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/sandbox/executor.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/sandbox/permissions.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/schema.py +0 -0
- {wardproof-0.3.0 → wardproof-0.3.2}/wardproof/standards.py +0 -0
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wardproof
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: Local-first, verifiable defensive AI agent swarms that protect other AI agent systems.
|
|
5
|
+
Project-URL: Homepage, https://wardproof.xyz
|
|
6
|
+
Project-URL: Repository, https://github.com/Impossible-Mission-Force/wardproof
|
|
7
|
+
Project-URL: Documentation, https://github.com/Impossible-Mission-Force/wardproof#readme
|
|
8
|
+
Project-URL: Issues, https://github.com/Impossible-Mission-Force/wardproof/issues
|
|
5
9
|
Author: Wardproof contributors
|
|
6
10
|
License-Expression: MIT
|
|
7
11
|
License-File: LICENSE
|
|
@@ -57,7 +61,7 @@ decision.
|
|
|
57
61
|
[](https://github.com/Impossible-Mission-Force/wardproof/blob/main/LICENSE)
|
|
58
62
|
[](https://www.python.org/downloads/)
|
|
59
63
|
|
|
60
|
-

|
|
64
|
+

|
|
61
65
|
|
|
62
66
|
Wardproof is a small framework for building swarms of *defensive* agents that
|
|
63
67
|
sit in front of your *other* AI systems (RAG pipelines, tool-using agents,
|
|
@@ -70,7 +74,7 @@ It is deliberately **small, transparent, and forkable**. The security core has
|
|
|
70
74
|
**zero third-party dependencies** and runs **fully offline**, with a local
|
|
71
75
|
model via Ollama, or with no model at all.
|
|
72
76
|
|
|
73
|
-
> **Status: v0.3.
|
|
77
|
+
> **Status: v0.3.1.** The deterministic core is built, tested, and benchmarked
|
|
74
78
|
> (see [Benchmark](#benchmark)), and ships dedicated guards for x402 agent
|
|
75
79
|
> payments, on-chain transfers, MCP tool calls, and skill/tool definitions, a
|
|
76
80
|
> controls-to-standards map (OWASP Agentic Top 10, OWASP LLM 2025, MITRE ATLAS,
|
|
@@ -79,8 +83,8 @@ model via Ollama, or with no model at all.
|
|
|
79
83
|
> examples for OpenAI and Anthropic tool calling, CrewAI, LangGraph, MCP,
|
|
80
84
|
> Coinbase AgentKit, and Venice AI. It is
|
|
81
85
|
> deployable today as a screening and audit layer, designed to run as defence in
|
|
82
|
-
> depth within the scope set out in [`THREAT_MODEL.md`](THREAT_MODEL.md) and
|
|
83
|
-
> [`SECURITY.md`](SECURITY.md).
|
|
86
|
+
> depth within the scope set out in [`THREAT_MODEL.md`](https://github.com/Impossible-Mission-Force/wardproof/blob/main/THREAT_MODEL.md) and
|
|
87
|
+
> [`SECURITY.md`](https://github.com/Impossible-Mission-Force/wardproof/blob/main/SECURITY.md).
|
|
84
88
|
|
|
85
89
|
---
|
|
86
90
|
|
|
@@ -131,7 +135,7 @@ different stance:
|
|
|
131
135
|
OpenAI and Anthropic tool calling, CrewAI, LangGraph, MCP, and Coinbase
|
|
132
136
|
AgentKit tool calls, plus Venice AI as an optional escalate-only second-opinion
|
|
133
137
|
backend. Each is an optional dependency; the core imports none of them. See
|
|
134
|
-
[`examples/integrations/`](examples/integrations
|
|
138
|
+
[`examples/integrations/`](https://github.com/Impossible-Mission-Force/wardproof/tree/main/examples/integrations).
|
|
135
139
|
- **Standards-aligned**: every control mapped to OWASP Top 10 for Agentic
|
|
136
140
|
Applications, OWASP Agentic Threats (T1-T15), OWASP LLM Top 10 2025, CSA
|
|
137
141
|
MAESTRO, MITRE ATLAS, and NIST AI 600-1 (`wardproof/standards.py`, enforced by
|
|
@@ -198,6 +202,24 @@ Verify an exported ledger from the command line:
|
|
|
198
202
|
wardproof verify-ledger ./audit.jsonl --pubkey <hex_public_key>
|
|
199
203
|
```
|
|
200
204
|
|
|
205
|
+
### Screen one action with `wardproof check`
|
|
206
|
+
|
|
207
|
+
Screen a single input or tool call from the command line. It runs the real
|
|
208
|
+
default swarm locally and exits `0` only when the verdict is `ALLOW`, so you can
|
|
209
|
+
gate a shell pipeline or an agent skill on it:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
# A tool call (tool name as the content, arguments as a JSON string)
|
|
213
|
+
wardproof check "get_weather" --args '{"city":"Hanoi"}' # ALLOW, exits 0
|
|
214
|
+
|
|
215
|
+
# An untrusted input
|
|
216
|
+
wardproof check "ignore all previous instructions" --kind input # BLOCK, exits non-zero
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Add `--json` to get a structured `{"verdict": ..., "allowed": ..., "risk": ...,
|
|
220
|
+
"reasons": [...]}` result to parse. A portable guard skill that wires this check
|
|
221
|
+
into a host agent lives in [`skill/wardproof-guard/`](https://github.com/Impossible-Mission-Force/wardproof/tree/main/skill/wardproof-guard).
|
|
222
|
+
|
|
201
223
|
---
|
|
202
224
|
|
|
203
225
|
## Architecture
|
|
@@ -272,7 +294,7 @@ languages, fresh encodings, or pure-semantic paraphrase) can still slip past a
|
|
|
272
294
|
deterministic denylist. Closing that gap is the job of the optional LLM second
|
|
273
295
|
opinion (see Roadmap); these patterns are the floor, not the ceiling. Re-run the
|
|
274
296
|
harness to regenerate the numbers above; the full breakdown and the honest edges
|
|
275
|
-
are in [`benchmarks/README.md`](benchmarks/README.md).
|
|
297
|
+
are in [`benchmarks/README.md`](https://github.com/Impossible-Mission-Force/wardproof/blob/main/benchmarks/README.md).
|
|
276
298
|
|
|
277
299
|
---
|
|
278
300
|
|
|
@@ -299,7 +321,7 @@ No need to touch the engine, the ledger, or the agent base classes.
|
|
|
299
321
|
Wardproof is built to become a complete, auditable control layer for AI agents.
|
|
300
322
|
The direction:
|
|
301
323
|
|
|
302
|
-
**Now (v0.3.
|
|
324
|
+
**Now (v0.3.1)**
|
|
303
325
|
The deterministic core: schema, guardrails, Detector / Verifier / Responder, a
|
|
304
326
|
capability sandbox, circuit breaker and watchdog, a hash-chained and optionally
|
|
305
327
|
signed audit ledger, a reproducible adversarial benchmark, a published threat
|
|
@@ -357,6 +379,6 @@ defence-in-depth setup:
|
|
|
357
379
|
|
|
358
380
|
## License
|
|
359
381
|
|
|
360
|
-
MIT, see [`LICENSE`](LICENSE). Contributions welcome; see
|
|
361
|
-
[`CONTRIBUTING.md`](CONTRIBUTING.md) and the security policy in
|
|
362
|
-
[`SECURITY.md`](SECURITY.md).
|
|
382
|
+
MIT, see [`LICENSE`](https://github.com/Impossible-Mission-Force/wardproof/blob/main/LICENSE). Contributions welcome; see
|
|
383
|
+
[`CONTRIBUTING.md`](https://github.com/Impossible-Mission-Force/wardproof/blob/main/CONTRIBUTING.md) and the security policy in
|
|
384
|
+
[`SECURITY.md`](https://github.com/Impossible-Mission-Force/wardproof/blob/main/SECURITY.md).
|
|
@@ -11,7 +11,7 @@ decision.
|
|
|
11
11
|
[](https://github.com/Impossible-Mission-Force/wardproof/blob/main/LICENSE)
|
|
12
12
|
[](https://www.python.org/downloads/)
|
|
13
13
|
|
|
14
|
-

|
|
14
|
+

|
|
15
15
|
|
|
16
16
|
Wardproof is a small framework for building swarms of *defensive* agents that
|
|
17
17
|
sit in front of your *other* AI systems (RAG pipelines, tool-using agents,
|
|
@@ -24,7 +24,7 @@ It is deliberately **small, transparent, and forkable**. The security core has
|
|
|
24
24
|
**zero third-party dependencies** and runs **fully offline**, with a local
|
|
25
25
|
model via Ollama, or with no model at all.
|
|
26
26
|
|
|
27
|
-
> **Status: v0.3.
|
|
27
|
+
> **Status: v0.3.1.** The deterministic core is built, tested, and benchmarked
|
|
28
28
|
> (see [Benchmark](#benchmark)), and ships dedicated guards for x402 agent
|
|
29
29
|
> payments, on-chain transfers, MCP tool calls, and skill/tool definitions, a
|
|
30
30
|
> controls-to-standards map (OWASP Agentic Top 10, OWASP LLM 2025, MITRE ATLAS,
|
|
@@ -33,8 +33,8 @@ model via Ollama, or with no model at all.
|
|
|
33
33
|
> examples for OpenAI and Anthropic tool calling, CrewAI, LangGraph, MCP,
|
|
34
34
|
> Coinbase AgentKit, and Venice AI. It is
|
|
35
35
|
> deployable today as a screening and audit layer, designed to run as defence in
|
|
36
|
-
> depth within the scope set out in [`THREAT_MODEL.md`](THREAT_MODEL.md) and
|
|
37
|
-
> [`SECURITY.md`](SECURITY.md).
|
|
36
|
+
> depth within the scope set out in [`THREAT_MODEL.md`](https://github.com/Impossible-Mission-Force/wardproof/blob/main/THREAT_MODEL.md) and
|
|
37
|
+
> [`SECURITY.md`](https://github.com/Impossible-Mission-Force/wardproof/blob/main/SECURITY.md).
|
|
38
38
|
|
|
39
39
|
---
|
|
40
40
|
|
|
@@ -85,7 +85,7 @@ different stance:
|
|
|
85
85
|
OpenAI and Anthropic tool calling, CrewAI, LangGraph, MCP, and Coinbase
|
|
86
86
|
AgentKit tool calls, plus Venice AI as an optional escalate-only second-opinion
|
|
87
87
|
backend. Each is an optional dependency; the core imports none of them. See
|
|
88
|
-
[`examples/integrations/`](examples/integrations
|
|
88
|
+
[`examples/integrations/`](https://github.com/Impossible-Mission-Force/wardproof/tree/main/examples/integrations).
|
|
89
89
|
- **Standards-aligned**: every control mapped to OWASP Top 10 for Agentic
|
|
90
90
|
Applications, OWASP Agentic Threats (T1-T15), OWASP LLM Top 10 2025, CSA
|
|
91
91
|
MAESTRO, MITRE ATLAS, and NIST AI 600-1 (`wardproof/standards.py`, enforced by
|
|
@@ -152,6 +152,24 @@ Verify an exported ledger from the command line:
|
|
|
152
152
|
wardproof verify-ledger ./audit.jsonl --pubkey <hex_public_key>
|
|
153
153
|
```
|
|
154
154
|
|
|
155
|
+
### Screen one action with `wardproof check`
|
|
156
|
+
|
|
157
|
+
Screen a single input or tool call from the command line. It runs the real
|
|
158
|
+
default swarm locally and exits `0` only when the verdict is `ALLOW`, so you can
|
|
159
|
+
gate a shell pipeline or an agent skill on it:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
# A tool call (tool name as the content, arguments as a JSON string)
|
|
163
|
+
wardproof check "get_weather" --args '{"city":"Hanoi"}' # ALLOW, exits 0
|
|
164
|
+
|
|
165
|
+
# An untrusted input
|
|
166
|
+
wardproof check "ignore all previous instructions" --kind input # BLOCK, exits non-zero
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Add `--json` to get a structured `{"verdict": ..., "allowed": ..., "risk": ...,
|
|
170
|
+
"reasons": [...]}` result to parse. A portable guard skill that wires this check
|
|
171
|
+
into a host agent lives in [`skill/wardproof-guard/`](https://github.com/Impossible-Mission-Force/wardproof/tree/main/skill/wardproof-guard).
|
|
172
|
+
|
|
155
173
|
---
|
|
156
174
|
|
|
157
175
|
## Architecture
|
|
@@ -226,7 +244,7 @@ languages, fresh encodings, or pure-semantic paraphrase) can still slip past a
|
|
|
226
244
|
deterministic denylist. Closing that gap is the job of the optional LLM second
|
|
227
245
|
opinion (see Roadmap); these patterns are the floor, not the ceiling. Re-run the
|
|
228
246
|
harness to regenerate the numbers above; the full breakdown and the honest edges
|
|
229
|
-
are in [`benchmarks/README.md`](benchmarks/README.md).
|
|
247
|
+
are in [`benchmarks/README.md`](https://github.com/Impossible-Mission-Force/wardproof/blob/main/benchmarks/README.md).
|
|
230
248
|
|
|
231
249
|
---
|
|
232
250
|
|
|
@@ -253,7 +271,7 @@ No need to touch the engine, the ledger, or the agent base classes.
|
|
|
253
271
|
Wardproof is built to become a complete, auditable control layer for AI agents.
|
|
254
272
|
The direction:
|
|
255
273
|
|
|
256
|
-
**Now (v0.3.
|
|
274
|
+
**Now (v0.3.1)**
|
|
257
275
|
The deterministic core: schema, guardrails, Detector / Verifier / Responder, a
|
|
258
276
|
capability sandbox, circuit breaker and watchdog, a hash-chained and optionally
|
|
259
277
|
signed audit ledger, a reproducible adversarial benchmark, a published threat
|
|
@@ -311,6 +329,6 @@ defence-in-depth setup:
|
|
|
311
329
|
|
|
312
330
|
## License
|
|
313
331
|
|
|
314
|
-
MIT, see [`LICENSE`](LICENSE). Contributions welcome; see
|
|
315
|
-
[`CONTRIBUTING.md`](CONTRIBUTING.md) and the security policy in
|
|
316
|
-
[`SECURITY.md`](SECURITY.md).
|
|
332
|
+
MIT, see [`LICENSE`](https://github.com/Impossible-Mission-Force/wardproof/blob/main/LICENSE). Contributions welcome; see
|
|
333
|
+
[`CONTRIBUTING.md`](https://github.com/Impossible-Mission-Force/wardproof/blob/main/CONTRIBUTING.md) and the security policy in
|
|
334
|
+
[`SECURITY.md`](https://github.com/Impossible-Mission-Force/wardproof/blob/main/SECURITY.md).
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "wardproof"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.2"
|
|
8
8
|
description = "Local-first, verifiable defensive AI agent swarms that protect other AI agent systems."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -13,6 +13,12 @@ keywords = ["ai-security", "prompt-injection", "agents", "guardrails", "local-fi
|
|
|
13
13
|
authors = [{ name = "Wardproof contributors" }]
|
|
14
14
|
dependencies = [] # core has ZERO third-party deps on purpose (small trusted computing base)
|
|
15
15
|
|
|
16
|
+
[project.urls]
|
|
17
|
+
Homepage = "https://wardproof.xyz"
|
|
18
|
+
Repository = "https://github.com/Impossible-Mission-Force/wardproof"
|
|
19
|
+
Documentation = "https://github.com/Impossible-Mission-Force/wardproof#readme"
|
|
20
|
+
Issues = "https://github.com/Impossible-Mission-Force/wardproof/issues"
|
|
21
|
+
|
|
16
22
|
[project.optional-dependencies]
|
|
17
23
|
ollama = ["httpx>=0.27"]
|
|
18
24
|
crypto = ["cryptography>=42"]
|
|
@@ -16,7 +16,7 @@ from wardproof.sandbox.executor import SandboxExecutor, ToolRegistry
|
|
|
16
16
|
from wardproof.sandbox.permissions import PermissionBroker, ToolGrant
|
|
17
17
|
from wardproof.schema import Decision, Event, Finding, Severity, Verdict
|
|
18
18
|
|
|
19
|
-
__version__ = "0.3.
|
|
19
|
+
__version__ = "0.3.2"
|
|
20
20
|
__all__ = [
|
|
21
21
|
"Event",
|
|
22
22
|
"Decision",
|
|
@@ -9,6 +9,8 @@ from pathlib import Path
|
|
|
9
9
|
|
|
10
10
|
from wardproof.audit.ledger import AuditEntry, AuditLedger
|
|
11
11
|
from wardproof.audit.stix import to_stix_bundle
|
|
12
|
+
from wardproof.orchestration.factory import build_default_swarm
|
|
13
|
+
from wardproof.schema import Event, Verdict
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
def _load_entries(path: str) -> list[AuditEntry]:
|
|
@@ -39,6 +41,47 @@ def _export_stix(path: str, out: str | None) -> int:
|
|
|
39
41
|
return 0
|
|
40
42
|
|
|
41
43
|
|
|
44
|
+
def _check(
|
|
45
|
+
kind: str,
|
|
46
|
+
content: str,
|
|
47
|
+
source: str,
|
|
48
|
+
args_json: str | None,
|
|
49
|
+
as_json: bool,
|
|
50
|
+
) -> int:
|
|
51
|
+
metadata: dict = {}
|
|
52
|
+
if args_json:
|
|
53
|
+
try:
|
|
54
|
+
metadata["args"] = json.loads(args_json)
|
|
55
|
+
except json.JSONDecodeError:
|
|
56
|
+
metadata["args"] = args_json
|
|
57
|
+
swarm = build_default_swarm()
|
|
58
|
+
out = swarm.handle(Event(kind=kind, source=source, content=content, metadata=metadata))
|
|
59
|
+
seen: set[str] = set()
|
|
60
|
+
reasons: list[str] = []
|
|
61
|
+
for d in (out.detector, out.verifier):
|
|
62
|
+
for f in d.findings:
|
|
63
|
+
if f.triggered and f.reason and f.reason not in seen:
|
|
64
|
+
seen.add(f.reason)
|
|
65
|
+
reasons.append(f.reason)
|
|
66
|
+
if as_json:
|
|
67
|
+
print(
|
|
68
|
+
json.dumps(
|
|
69
|
+
{
|
|
70
|
+
"verdict": out.verdict.value,
|
|
71
|
+
"allowed": out.verdict is Verdict.ALLOW,
|
|
72
|
+
"risk": round(out.risk, 3),
|
|
73
|
+
"reasons": reasons,
|
|
74
|
+
}
|
|
75
|
+
)
|
|
76
|
+
)
|
|
77
|
+
else:
|
|
78
|
+
print(out.verdict.value.upper())
|
|
79
|
+
if reasons:
|
|
80
|
+
print(" " + "; ".join(reasons))
|
|
81
|
+
# exit 0 only when the action is allowed, so shells and skills can gate on it
|
|
82
|
+
return 0 if out.verdict is Verdict.ALLOW else 2
|
|
83
|
+
|
|
84
|
+
|
|
42
85
|
def main(argv: list[str] | None = None) -> int:
|
|
43
86
|
parser = argparse.ArgumentParser(prog="wardproof")
|
|
44
87
|
sub = parser.add_subparsers(dest="cmd", required=True)
|
|
@@ -48,11 +91,23 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
48
91
|
sp = sub.add_parser("export-stix", help="export a JSONL audit ledger as a STIX 2.1 bundle")
|
|
49
92
|
sp.add_argument("path")
|
|
50
93
|
sp.add_argument("--out", default=None, help="write to a file instead of stdout")
|
|
94
|
+
cp = sub.add_parser("check", help="screen one input or tool call and print its verdict")
|
|
95
|
+
cp.add_argument("content", help="the input text, or the tool name for a tool call")
|
|
96
|
+
cp.add_argument(
|
|
97
|
+
"--kind",
|
|
98
|
+
default="tool_call",
|
|
99
|
+
help="event kind: tool_call (default) or input",
|
|
100
|
+
)
|
|
101
|
+
cp.add_argument("--source", default="agent", help="who originated the event")
|
|
102
|
+
cp.add_argument("--args", default=None, help="tool-call arguments as a JSON string")
|
|
103
|
+
cp.add_argument("--json", action="store_true", help="print a JSON object instead of text")
|
|
51
104
|
args = parser.parse_args(argv)
|
|
52
105
|
if args.cmd == "verify-ledger":
|
|
53
106
|
return _verify_file(args.path, args.pubkey)
|
|
54
107
|
if args.cmd == "export-stix":
|
|
55
108
|
return _export_stix(args.path, args.out)
|
|
109
|
+
if args.cmd == "check":
|
|
110
|
+
return _check(args.kind, args.content, args.source, args.args, args.json)
|
|
56
111
|
return 1
|
|
57
112
|
|
|
58
113
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|