@attested-intelligence/aga-mcp-server 2.2.1 → 3.0.0-rc.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/DEPLOYMENT.md +111 -0
- package/LICENSE +21 -21
- package/README.md +60 -48
- package/SECURITY.md +59 -0
- package/THREAT_BOUNDARY.md +77 -0
- package/dist/core/behavioral.d.ts.map +1 -1
- package/dist/core/behavioral.js +11 -3
- package/dist/core/behavioral.js.map +1 -1
- package/dist/core/index.d.ts +0 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +2 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/types.d.ts +1 -22
- package/dist/core/types.d.ts.map +1 -1
- package/dist/crypto/index.d.ts +0 -1
- package/dist/crypto/index.d.ts.map +1 -1
- package/dist/crypto/index.js +1 -1
- package/dist/crypto/index.js.map +1 -1
- package/dist/crypto/sign.d.ts.map +1 -1
- package/dist/crypto/sign.js +24 -23
- package/dist/crypto/sign.js.map +1 -1
- package/dist/middleware/governance.d.ts +22 -3
- package/dist/middleware/governance.d.ts.map +1 -1
- package/dist/middleware/governance.js +36 -28
- package/dist/middleware/governance.js.map +1 -1
- package/dist/proxy/index.d.ts.map +1 -1
- package/dist/proxy/index.js +26 -15
- package/dist/proxy/index.js.map +1 -1
- package/dist/proxy/server.d.ts +18 -45
- package/dist/proxy/server.d.ts.map +1 -1
- package/dist/proxy/server.js +77 -131
- package/dist/proxy/server.js.map +1 -1
- package/dist/sep/bundle.d.ts +60 -0
- package/dist/sep/bundle.d.ts.map +1 -0
- package/dist/sep/bundle.js +74 -0
- package/dist/sep/bundle.js.map +1 -0
- package/dist/sep/canonical.d.ts +28 -0
- package/dist/sep/canonical.d.ts.map +1 -0
- package/dist/sep/canonical.js +62 -0
- package/dist/sep/canonical.js.map +1 -0
- package/dist/sep/checkpoint.d.ts +15 -0
- package/dist/sep/checkpoint.d.ts.map +1 -0
- package/dist/sep/checkpoint.js +28 -0
- package/dist/sep/checkpoint.js.map +1 -0
- package/dist/sep/crypto.d.ts +20 -0
- package/dist/sep/crypto.d.ts.map +1 -0
- package/dist/sep/crypto.js +104 -0
- package/dist/sep/crypto.js.map +1 -0
- package/dist/sep/index.d.ts +14 -0
- package/dist/sep/index.d.ts.map +1 -0
- package/dist/sep/index.js +14 -0
- package/dist/sep/index.js.map +1 -0
- package/dist/sep/merkle.d.ts +11 -0
- package/dist/sep/merkle.d.ts.map +1 -0
- package/dist/sep/merkle.js +51 -0
- package/dist/sep/merkle.js.map +1 -0
- package/dist/sep/receipt.d.ts +64 -0
- package/dist/sep/receipt.d.ts.map +1 -0
- package/dist/sep/receipt.js +0 -0
- package/dist/sep/receipt.js.map +1 -0
- package/dist/sep/verify.d.ts +14 -0
- package/dist/sep/verify.d.ts.map +1 -0
- package/dist/sep/verify.js +158 -0
- package/dist/sep/verify.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +83 -39
- package/dist/server.js.map +1 -1
- package/dist/storage/interface.d.ts +1 -4
- package/dist/storage/interface.d.ts.map +1 -1
- package/dist/storage/memory.d.ts +1 -5
- package/dist/storage/memory.d.ts.map +1 -1
- package/dist/storage/memory.js +0 -4
- package/dist/storage/memory.js.map +1 -1
- package/dist/storage/sqlite.d.ts +1 -4
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +0 -4
- package/dist/storage/sqlite.js.map +1 -1
- package/dist/utils/canonical.d.ts.map +1 -1
- package/dist/utils/canonical.js +11 -1
- package/dist/utils/canonical.js.map +1 -1
- package/dist/utils/timestamp.d.ts.map +1 -1
- package/dist/utils/timestamp.js +4 -1
- package/dist/utils/timestamp.js.map +1 -1
- package/dist/utils/uuid.d.ts +1 -0
- package/dist/utils/uuid.d.ts.map +1 -1
- package/dist/utils/uuid.js +3 -2
- package/dist/utils/uuid.js.map +1 -1
- package/package.json +87 -92
- package/dist/core/bundle.d.ts +0 -20
- package/dist/core/bundle.d.ts.map +0 -1
- package/dist/core/bundle.js +0 -45
- package/dist/core/bundle.js.map +0 -1
- package/dist/core/checkpoint.d.ts +0 -8
- package/dist/core/checkpoint.d.ts.map +0 -1
- package/dist/core/checkpoint.js +0 -21
- package/dist/core/checkpoint.js.map +0 -1
- package/dist/crypto/merkle.d.ts +0 -8
- package/dist/crypto/merkle.d.ts.map +0 -1
- package/dist/crypto/merkle.js +0 -42
- package/dist/crypto/merkle.js.map +0 -1
- package/dist/proxy/verify.d.ts +0 -28
- package/dist/proxy/verify.d.ts.map +0 -1
- package/dist/proxy/verify.js +0 -182
- package/dist/proxy/verify.js.map +0 -1
package/DEPLOYMENT.md
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# AGA MCP Server — Deployment & Hardening Guide
|
|
2
|
+
|
|
3
|
+
Practical guidance for running `@attested-intelligence/aga-mcp-server` (3.0.0-rc) in a defensible configuration. Scope is the **MCP server boundary** — see `THREAT_BOUNDARY.md` for the full claim/limitation surface this guide operationalizes.
|
|
4
|
+
|
|
5
|
+
The hardened posture in one line: **stdio upstream + a persisted, well-protected gateway key + network isolation + verifiers that pin the gateway key.**
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Upstream mode — stdio (recommended) vs HTTP
|
|
10
|
+
|
|
11
|
+
The governance proxy (`aga-proxy`) sits between an MCP client and an upstream MCP server and produces a signed receipt for every governed `tools/call`. How you connect the upstream determines whether that mediation can be bypassed.
|
|
12
|
+
|
|
13
|
+
### ✅ stdio upstream — the hardened default
|
|
14
|
+
```bash
|
|
15
|
+
npx -p @attested-intelligence/aga-mcp-server aga-proxy start \
|
|
16
|
+
--upstream "npx -y @modelcontextprotocol/server-filesystem /tmp/data" --profile standard
|
|
17
|
+
```
|
|
18
|
+
The upstream is a **child process** the proxy spawns and talks to over stdio. It is **not network-reachable**, so the agent has no route to the tools except through the proxy. This closes the direct-reach bypass (`THREAT_BOUNDARY.md` §3.1) by construction. **Prefer this mode.**
|
|
19
|
+
|
|
20
|
+
### ⚠️ HTTP upstream — only behind strict network isolation
|
|
21
|
+
```bash
|
|
22
|
+
# Bypassable unless the agent CANNOT reach the upstream URL directly.
|
|
23
|
+
aga-proxy start --upstream-url "http://127.0.0.1:9000" --profile standard
|
|
24
|
+
```
|
|
25
|
+
With an HTTP upstream, **anything that can reach the upstream URL bypasses governance entirely** (no receipt). This is a deployment property the server cannot enforce in code. If you must use HTTP upstream:
|
|
26
|
+
- Bind the upstream to `127.0.0.1` / a private network the agent cannot reach.
|
|
27
|
+
- Use network policy / firewall so the **only** path to the upstream is through the proxy.
|
|
28
|
+
- Treat any deployment where the agent can resolve+reach the upstream URL as **ungoverned**.
|
|
29
|
+
|
|
30
|
+
The server emits an stderr warning when HTTP-upstream mode is used.
|
|
31
|
+
|
|
32
|
+
### Method coverage
|
|
33
|
+
Only `method === "tools/call"` is policy-evaluated. Other JSON-RPC methods are forwarded (with passthrough receipts as of P2; see `THREAT_BOUNDARY.md` §3.2). If your upstream exposes side effects via non-`tools/call` methods, account for that explicitly.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 2. The gateway key — generate, persist, pin, protect
|
|
38
|
+
|
|
39
|
+
The **gateway key** is the Ed25519 key that signs every receipt and checkpoint. Pinning its public key is what turns a bundle from "internally consistent" into "provably issued by *this* gateway."
|
|
40
|
+
|
|
41
|
+
### Generate a 32-byte seed (64-hex)
|
|
42
|
+
```bash
|
|
43
|
+
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Persist it (so provenance survives restarts and is pinnable)
|
|
47
|
+
Either:
|
|
48
|
+
```bash
|
|
49
|
+
export AGA_GATEWAY_KEY=<64-hex-seed> # environment variable
|
|
50
|
+
# or
|
|
51
|
+
export AGA_GATEWAY_KEY_FILE=/run/secrets/aga-gateway-key # file containing the hex seed
|
|
52
|
+
```
|
|
53
|
+
If neither is set, the server uses an **ephemeral** key that rotates on every restart (it warns on stderr). Ephemeral is fine for local experiments but means **provenance cannot be pinned across restarts** — avoid it in anything you'll later audit.
|
|
54
|
+
|
|
55
|
+
### Obtain the public key to pin
|
|
56
|
+
Call the `get_server_info` tool → **`gateway_public_key`**. That 64-hex value is what verifiers pin.
|
|
57
|
+
|
|
58
|
+
### Pin it when verifying
|
|
59
|
+
```bash
|
|
60
|
+
# reference verifier (zero deps)
|
|
61
|
+
node aga-receipt-spec/verify/verify-sep.mjs evidence-bundle.json --pubkey <gateway_public_key>
|
|
62
|
+
# or the published CLI (2.0.0 — publish pending)
|
|
63
|
+
aga-verify evidence-bundle.json --pubkey <gateway_public_key>
|
|
64
|
+
```
|
|
65
|
+
Or via the tool: `verify_bundle_offline(bundle, pinned_public_key=<gateway_public_key>)`. **Without a pin you get an integrity-only result** (`issuerVerified=false`, summary says "NOT provenance"). See §3.7 of the boundary doc.
|
|
66
|
+
|
|
67
|
+
### Protect it
|
|
68
|
+
The gateway key is a signing secret — **anyone who holds it can mint a fully VERIFIED, provenance-bound bundle saying anything.** Therefore:
|
|
69
|
+
- Store it in a secret manager, or a file with restricted permissions (e.g. `chmod 600`, owned by the service user); never world-readable, never committed, never in shell history.
|
|
70
|
+
- Rotate by minting a new seed and **re-publishing the new public key** to your verifiers (old bundles stay verifiable against the old key).
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 3. Recommended hardened configuration
|
|
75
|
+
|
|
76
|
+
```jsonc
|
|
77
|
+
// Claude Desktop / MCP client config — proxy in front of a stdio upstream, persisted key
|
|
78
|
+
{
|
|
79
|
+
"mcpServers": {
|
|
80
|
+
"aga": {
|
|
81
|
+
"command": "npx",
|
|
82
|
+
"args": ["-y", "@attested-intelligence/aga-mcp-server"],
|
|
83
|
+
"env": { "AGA_GATEWAY_KEY_FILE": "/run/secrets/aga-gateway-key" }
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
Checklist:
|
|
89
|
+
- [ ] stdio upstream (no HTTP upstream, or HTTP only behind network isolation).
|
|
90
|
+
- [ ] Persisted gateway key from a secret manager / restricted file.
|
|
91
|
+
- [ ] The agent's **only** route to tools is through the proxy (network isolation).
|
|
92
|
+
- [ ] Verifiers **pin** `gateway_public_key`; an unpinned PASS is treated as integrity-only, not provenance.
|
|
93
|
+
- [ ] Export evidence bundles regularly — default storage is in-memory and the live chain is lost on restart; the **exported, signed bundle is the durable record** (`THREAT_BOUNDARY.md` §3.5).
|
|
94
|
+
- [ ] Choose the `restrictive` profile (allowlist, default-deny) for high-stakes upstreams.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## 4. Anti-patterns (do not do these)
|
|
99
|
+
|
|
100
|
+
- ❌ **HTTP upstream without network isolation** — the agent reaches the upstream directly and governance is bypassed (§3.1).
|
|
101
|
+
- ❌ **Ephemeral gateway key in production** — provenance can't be pinned across restarts; auditors can't bind bundles to a stable issuer.
|
|
102
|
+
- ❌ **Treating an unpinned "VERIFIED" as proof of who issued it** — unpinned is integrity-only (`issuerVerified=false`). Always pin to claim provenance (§3.7).
|
|
103
|
+
- ❌ **World-readable / committed / shell-history gateway key** — it's a signing secret; leaking it lets anyone forge provenance-bound bundles.
|
|
104
|
+
- ❌ **Relying on the public demo gateway as the canonical artifact** — it's a separate deployment that may track its own version; always verify offline against a pinned key.
|
|
105
|
+
- ❌ **Adding a new mutating tool without governing it** — any new agent-action tool must go through the PEP (not `UNGOVERNED_TOOLS`) so it emits a signed receipt (`THREAT_BOUNDARY.md` §2 maintenance invariant).
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## 5. What this does and does not prove
|
|
110
|
+
|
|
111
|
+
Per `THREAT_BOUNDARY.md`: a verified bundle proves the **integrity of the receipts present** — authentic, ordered, Merkle-included, checkpoint-bound, and (when pinned) issued by the pinned gateway. It does **not** prove non-omission, prevent jailbreaks, or protect a leaked key. Deployment hardening (this guide) is what makes the in-claim guarantee hold in practice.
|
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Attested Intelligence Holdings LLC
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Attested Intelligence Holdings LLC
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -5,21 +5,25 @@ Cryptographic runtime governance for AI agents and autonomous systems.
|
|
|
5
5
|
[](https://www.npmjs.com/package/@attested-intelligence/aga-mcp-server)
|
|
6
6
|
[](https://pypi.org/project/aga-governance/)
|
|
7
7
|
[](LICENSE)
|
|
8
|
-
[](https://github.com/attestedintelligence/aga-mcp-server)
|
|
9
|
+
|
|
10
|
+
> **Status — 3.0.0-rc.** This release candidate emits the **canonical SEP evidence bundle** from both the server tools and the `aga-proxy`, verifiable offline by `@attested-intelligence/aga-verify` and the reference verifier `aga-receipt-spec/verify/verify-sep.mjs`. The **currently-published npm release (2.2.2) still emits a legacy continuity-chain bundle** that does *not* verify under the SEP verifier — upgrade to 3.0 once published. Claim scope and residual attack surface are documented honestly in `THREAT_BOUNDARY.md`.
|
|
9
11
|
|
|
10
12
|
```bash
|
|
11
|
-
#
|
|
12
|
-
|
|
13
|
-
python -m aga demo
|
|
14
|
-
python -m aga verify demo-bundle.json
|
|
13
|
+
# This package IS the AGA MCP server (TypeScript, runs over stdio). Use it from any MCP client:
|
|
14
|
+
npx -y @attested-intelligence/aga-mcp-server
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
+
A Python companion SDK (`aga-governance`) is documented in the Python SDK section below.
|
|
18
|
+
|
|
17
19
|
## What This Does
|
|
18
20
|
|
|
19
21
|
Every tool call an AI agent makes passes through the AGA gateway. Each call is evaluated against policy, and the decision (PERMITTED or DENIED) is recorded as a signed, hash-linked governance receipt. Receipts are collected into evidence bundles that any third party can verify offline using standard cryptography.
|
|
20
22
|
|
|
21
23
|
**Record. Prove. Verify.**
|
|
22
24
|
|
|
25
|
+
**Scope:** a verified bundle proves the *integrity of the receipts present* — each is authentic, correctly ordered, Merkle-included, and (when a key is pinned) provenance-bound. It does **not** prove non-omission (that every action the agent took was logged); completeness is bounded by the tamper-evidence of the interception point, which is outside the bundle.
|
|
26
|
+
|
|
23
27
|
## Use with Claude Desktop
|
|
24
28
|
|
|
25
29
|
Add to your Claude Desktop MCP config (`claude_desktop_config.json`):
|
|
@@ -37,31 +41,32 @@ Add to your Claude Desktop MCP config (`claude_desktop_config.json`):
|
|
|
37
41
|
|
|
38
42
|
Claude can then seal artifacts, measure integrity, generate evidence bundles, and verify compliance through natural language.
|
|
39
43
|
|
|
40
|
-
## MCP Tools (
|
|
44
|
+
## MCP Tools (15)
|
|
41
45
|
|
|
42
46
|
| Category | Tools |
|
|
43
47
|
|----------|-------|
|
|
44
48
|
| **Identity** | `get_server_info`, `get_portal_state` |
|
|
45
49
|
| **Lifecycle** | `init_chain`, `attest_subject`, `revoke_artifact` |
|
|
46
50
|
| **Enforcement** | `measure_integrity`, `measure_behavior`, `verify_chain` |
|
|
47
|
-
| **Evidence** | `
|
|
51
|
+
| **Evidence** | `generate_evidence_bundle`, `verify_bundle_offline` |
|
|
48
52
|
| **Privacy** | `request_claim`, `list_claims` |
|
|
49
53
|
| **Delegation** | `delegate_to_subagent` |
|
|
50
54
|
| **Audit** | `get_receipts`, `get_chain_events` |
|
|
51
55
|
|
|
52
|
-
|
|
56
|
+
> **`measure_behavior` is detective-only by default** — it observes tool-usage patterns and records a *signed, provable* drift finding, but does not block. Enforcement (drift → quarantine) is opt-in via `enforce=true` and off by default. Hard governance decisions (PERMITTED/DENIED) are made by the portal/PEP, not the behavioral monitor.
|
|
57
|
+
|
|
58
|
+
## Quick Start — verify a bundle offline
|
|
53
59
|
|
|
54
|
-
|
|
60
|
+
A bundle this package emits (via the `generate_evidence_bundle` tool, or `aga-proxy export`) is a **canonical SEP bundle**. Verify it offline, with no network and no dependency on us:
|
|
55
61
|
|
|
56
62
|
```bash
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
python -m aga verify evidence-bundle.json
|
|
63
|
+
# Reference verifier (zero deps, Node 18+). Pin the gateway key (from get_server_info) to prove provenance.
|
|
64
|
+
node aga-receipt-spec/verify/verify-sep.mjs evidence-bundle.json --pubkey <gateway-public-key>
|
|
60
65
|
```
|
|
61
66
|
|
|
62
|
-
|
|
67
|
+
The published `@attested-intelligence/aga-verify` CLI mirrors this reference (2.0.0 — publish pending; the npm registry currently has the older 1.0.0). Without `--pubkey` you get an **integrity-only** result (`issuerVerified=false`); pin the key to also prove *who* issued it — see `THREAT_BOUNDARY.md` §3.7. A hosted browser verifier is linked under [Links](#links).
|
|
63
68
|
|
|
64
|
-
|
|
69
|
+
The reference §6 algorithm is implemented in **three languages** — JavaScript (`aga-receipt-spec/verify/verify-sep.mjs`), Go (`verify.go`, stdlib `crypto/ed25519`), and Python (`verify.py`, pure-stdlib RFC-8032 Ed25519) — and a cross-stack harness (`npm run conformance:cross-stack`) proves all three, plus the in-server engine and `aga-verify`, render **identical verdicts** on the canonical vectors (valid, adversarial, and every small-order forgery).
|
|
65
70
|
|
|
66
71
|
## How It Works
|
|
67
72
|
|
|
@@ -77,8 +82,9 @@ AI Agent AGA Gateway Verifier
|
|
|
77
82
|
| [Export Bundle] |
|
|
78
83
|
| |--------- evidence.json ----->|
|
|
79
84
|
| | [Verify Signatures]
|
|
80
|
-
| | [Verify Chain]
|
|
85
|
+
| | [Verify Chain + Order]
|
|
81
86
|
| | [Verify Merkle Tree]
|
|
87
|
+
| | [Verify Signed Checkpoint]
|
|
82
88
|
| | [PASS / FAIL]
|
|
83
89
|
```
|
|
84
90
|
|
|
@@ -87,30 +93,31 @@ AI Agent AGA Gateway Verifier
|
|
|
87
93
|
Run AGA as a transparent proxy between any MCP client and any MCP server. Every tool call gets evaluated against policy and produces a signed receipt.
|
|
88
94
|
|
|
89
95
|
```bash
|
|
90
|
-
# Start the proxy
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
npx
|
|
96
|
+
# Start the proxy (the `aga-proxy` bin) in front of an upstream MCP server.
|
|
97
|
+
# stdio upstream = the hardened default (the upstream is a child process, not network-reachable).
|
|
98
|
+
npx -p @attested-intelligence/aga-mcp-server aga-proxy start \
|
|
99
|
+
--upstream "npx -y @modelcontextprotocol/server-filesystem /tmp/test" --profile standard
|
|
100
|
+
|
|
101
|
+
# Export the canonical SEP evidence bundle, then verify it offline
|
|
102
|
+
npx -p @attested-intelligence/aga-mcp-server aga-proxy export --output evidence.json
|
|
103
|
+
npx -p @attested-intelligence/aga-mcp-server aga-proxy verify evidence.json
|
|
98
104
|
```
|
|
99
105
|
|
|
100
|
-
The proxy intercepts `tools/call` requests, evaluates them against a sealed policy
|
|
106
|
+
The proxy intercepts `tools/call` requests, evaluates them against a sealed policy, and generates a signed SEP receipt for **every** decision. Permitted calls are forwarded to the downstream server; denied calls return an MCP error and never reach it. Every decision is hash-linked and checkpoint-bound into a tamper-evident bundle. (Methods other than `tools/call` aren't policy-evaluated, but non-benign ones are recorded as signed *passthrough* receipts for auditability, and an optional denylist can reject them; see `THREAT_BOUNDARY.md` §3.2.)
|
|
101
107
|
|
|
102
108
|
Three built-in policy profiles:
|
|
103
109
|
- **permissive** - log everything, block nothing (default)
|
|
104
110
|
- **standard** - rate limits + blocks destructive operations
|
|
105
111
|
- **restrictive** - explicit tool allowlist, all unknown tools denied
|
|
106
112
|
|
|
107
|
-
## Verification (
|
|
113
|
+
## Verification _(canonical SEP — 3.0; normative §6 algorithm in `aga-receipt-spec/verify/verify-sep.mjs`)_
|
|
108
114
|
|
|
109
|
-
1. **
|
|
110
|
-
2. **Receipt Signatures** - Ed25519 over
|
|
111
|
-
3. **Chain
|
|
112
|
-
4. **Merkle Proofs** -
|
|
113
|
-
5. **
|
|
115
|
+
1. **Structural floor** - Bundle declares Ed25519-SHA256-JCS, public key well-formed (all small-order encodings + non-canonical `y ≥ p` rejected), `receipts.length > 0`, proof count = receipt count
|
|
116
|
+
2. **Receipt Signatures** - Ed25519 over JCS-profile canonical JSON, sorted-key (signature field excluded)
|
|
117
|
+
3. **Chain + ordering** - Each receipt's `previous_receipt_hash` = leaf of the preceding receipt; non-decreasing timestamps
|
|
118
|
+
4. **Merkle Proofs** - Recompute every leaf from receipt content, walk siblings/directions to one root, leaf indices form the complete `0..N-1` bijection
|
|
119
|
+
5. **Signed checkpoint** - Verify the gateway-signed checkpoint binding `merkle_root`, `leaf_count`, and chain head (this makes the no-prefix construction truncation-safe)
|
|
120
|
+
6. **Provenance** _(when a key is pinned)_ - `public_key == expected key`; otherwise integrity-only is reported
|
|
114
121
|
|
|
115
122
|
## Cryptographic Primitives
|
|
116
123
|
|
|
@@ -118,12 +125,12 @@ Three built-in policy profiles:
|
|
|
118
125
|
|-----------|---------|
|
|
119
126
|
| Ed25519 | Receipt signatures |
|
|
120
127
|
| SHA-256 | Hash chaining, Merkle trees, leaf computation |
|
|
121
|
-
|
|
|
128
|
+
| JCS-profile (sorted-key canonical JSON) | Deterministic signing (canon is byte-compatible with the reference verifier) |
|
|
122
129
|
| Merkle Trees | Binding all receipts to a single verifiable root |
|
|
123
130
|
|
|
124
131
|
## Live Gateway
|
|
125
132
|
|
|
126
|
-
|
|
133
|
+
A demo gateway is deployed on Cloudflare Workers (a **separate deployment** that may track its own version; treat it as a convenience mirror, and always verify what it returns offline against a pinned key — not as the canonical artifact):
|
|
127
134
|
|
|
128
135
|
```bash
|
|
129
136
|
# Check status
|
|
@@ -156,30 +163,35 @@ with AgentSession(gateway_id="my-gateway") as session:
|
|
|
156
163
|
|
|
157
164
|
## Test Suite
|
|
158
165
|
|
|
159
|
-
|
|
166
|
+
Automated tests across TypeScript and Python, plus a conformance corpus:
|
|
160
167
|
|
|
161
|
-
- **TypeScript MCP
|
|
162
|
-
- **
|
|
163
|
-
- **
|
|
168
|
+
- **TypeScript MCP server:** 248 tests (vitest) — including provable-denial and behavioral-monitor regressions
|
|
169
|
+
- **SEP conformance corpus:** `npm run test:conformance` (valid → VERIFIED, negatives → FAILED)
|
|
170
|
+
- **Python companion SDK:** pytest suite (`aga-python`)
|
|
164
171
|
|
|
165
172
|
```bash
|
|
166
|
-
npm test # TypeScript tests
|
|
167
|
-
|
|
173
|
+
npm test # TypeScript tests (vitest)
|
|
174
|
+
npm run test:conformance # SEP conformance corpus
|
|
175
|
+
cd aga-python && python -m pytest # Python companion tests
|
|
168
176
|
```
|
|
169
177
|
|
|
178
|
+
## Benchmarks
|
|
179
|
+
|
|
180
|
+
Performance baseline (signature primitives, storage overhead, the end-to-end measurement cycle, and post-quantum cadence feasibility) is documented in [BENCHMARKS.md](BENCHMARKS.md), matching Section 4.7 of the paper. Receipt-format determinism is reproducible here via the cross-language vectors (`npm test`).
|
|
181
|
+
|
|
170
182
|
## Project Structure
|
|
171
183
|
|
|
172
184
|
```
|
|
173
|
-
src/
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
middleware/ #
|
|
179
|
-
aga-python/ # Python SDK
|
|
180
|
-
independent-verifier/ #
|
|
181
|
-
scenarios/ #
|
|
182
|
-
tests/ # TypeScript test suite (
|
|
185
|
+
src/
|
|
186
|
+
sep/ # Canonical SEP evidence engine — single source of truth (canon, merkle, receipt, checkpoint, bundle, verify)
|
|
187
|
+
core/ # Governance primitives (portal, artifact, attestation, disclosure, delegation, behavioral) + internal continuity-chain profile
|
|
188
|
+
crypto/ # Internal continuity-chain crypto: Ed25519 (node:crypto), SHA-256/blake2b, salt
|
|
189
|
+
proxy/ # MCP governance proxy (transparent interception + policy enforcement; emits SEP bundles)
|
|
190
|
+
middleware/ # Governance PEP wrapper (records a signed PERMITTED/DENIED receipt per governed call)
|
|
191
|
+
aga-python/ # Python companion SDK (PyPI: aga-governance)
|
|
192
|
+
independent-verifier/ # @attested-intelligence/aga-verify — standalone SEP verifier, zero AGA imports
|
|
193
|
+
scenarios/ # Demo scenarios (SCADA, autonomous vehicle, AI agent) — emit SEP bundles
|
|
194
|
+
tests/ # TypeScript test suite (248 tests)
|
|
183
195
|
```
|
|
184
196
|
|
|
185
197
|
## Links
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Reporting a Vulnerability
|
|
4
|
+
|
|
5
|
+
If you discover a security vulnerability in AGA, please report it responsibly.
|
|
6
|
+
|
|
7
|
+
**Email:** [admin@attestedintelligence.com](mailto:admin@attestedintelligence.com)
|
|
8
|
+
|
|
9
|
+
**Subject line:** `[SECURITY] AGA Vulnerability Report`
|
|
10
|
+
|
|
11
|
+
### What to Include
|
|
12
|
+
|
|
13
|
+
- Description of the vulnerability
|
|
14
|
+
- Steps to reproduce
|
|
15
|
+
- Potential impact assessment
|
|
16
|
+
- Suggested fix (if you have one)
|
|
17
|
+
|
|
18
|
+
### Response Timeline
|
|
19
|
+
|
|
20
|
+
- **Acknowledgment:** Within 48 hours of receipt
|
|
21
|
+
- **Initial assessment:** Within 5 business days
|
|
22
|
+
- **Resolution target:** Dependent on severity, typically within 30 days for critical issues
|
|
23
|
+
|
|
24
|
+
### Scope
|
|
25
|
+
|
|
26
|
+
This policy covers:
|
|
27
|
+
|
|
28
|
+
- The AGA reference implementation (`src/`, `independent-verifier/`)
|
|
29
|
+
- The MCP server (`@attested-intelligence/aga-mcp-server`)
|
|
30
|
+
- Cryptographic operations (signing, verification, hash computation, chain integrity)
|
|
31
|
+
- Evidence Bundle generation and verification
|
|
32
|
+
|
|
33
|
+
### Out of Scope
|
|
34
|
+
|
|
35
|
+
- The attestedintelligence.com website (report separately to the same email)
|
|
36
|
+
- Third-party dependencies (report to the upstream maintainer, but let us know)
|
|
37
|
+
- Social engineering or phishing attacks
|
|
38
|
+
|
|
39
|
+
### Cryptographic Considerations
|
|
40
|
+
|
|
41
|
+
AGA relies on Ed25519 signatures, SHA-256 hashing, BLAKE2b-256 fingerprinting, and Merkle tree anchoring. If you identify a weakness in how these primitives are applied (not the primitives themselves), that is a valid report.
|
|
42
|
+
|
|
43
|
+
Key areas of concern:
|
|
44
|
+
|
|
45
|
+
- Sealed hash computation correctness
|
|
46
|
+
- Receipt chain integrity (hash linking)
|
|
47
|
+
- Merkle checkpoint verification
|
|
48
|
+
- Key separation enforcement between Portal and agent
|
|
49
|
+
- Evidence Bundle completeness and tamper detection
|
|
50
|
+
|
|
51
|
+
### Disclosure
|
|
52
|
+
|
|
53
|
+
We follow coordinated disclosure. Please do not publicly disclose vulnerabilities until we have released a fix or 90 days have elapsed, whichever comes first.
|
|
54
|
+
|
|
55
|
+
We do not currently operate a bug bounty program.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
Attested Intelligence Holdings LLC
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# AGA MCP Server — Threat Boundary & Bypass Surface (honest audit)
|
|
2
|
+
|
|
3
|
+
**Scope:** `@attested-intelligence/aga-mcp-server` 3.0.0-rc. Written for Sprint 3 CP3.
|
|
4
|
+
**Stance:** defensibility through honesty. This documents what the package **does** guarantee, what it **does not**, and the **residual attack surface** that remains by design or is deferred. Per the project discipline: better a precisely-stated boundary than an overclaim.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 1. The core claim (what is proven + tested)
|
|
9
|
+
|
|
10
|
+
> Every **governed** decision (PERMITTED *and* DENIED) produces a signed, hash-chained, Merkle-included, **checkpoint-bound** SEP receipt that any third party can verify offline (`aga-verify` / `verify-sep.mjs`), with provenance when the gateway key is pinned.
|
|
11
|
+
|
|
12
|
+
A denial **cannot be silently erased by the agent**:
|
|
13
|
+
|
|
14
|
+
| Attack | Defense | Test |
|
|
15
|
+
|---|---|---|
|
|
16
|
+
| Tamper a receipt | Ed25519 signature + leaf-recompute fail | `acceptance.test.ts 9.3`, `_validation/sep-gate.mjs` |
|
|
17
|
+
| Drop the DENIED receipt (truncation) | signed checkpoint binds `leaf_count` + head | `_validation/sep-gate.mjs` (SC4) |
|
|
18
|
+
| Reorder to bury it | `previous_receipt_hash` chain + non-decreasing timestamp | `_validation/sep-gate.mjs` (SC5) |
|
|
19
|
+
| Re-attest to wipe history | SEP ledger is **not** reset on `attest_subject` | `tests/integration/provable-denial.test.ts` |
|
|
20
|
+
| Forge under a different key | receipts checked vs **pinned** key; **all** small-order encodings (10 canonical + non-canonical `y≥p`) rejected | `_validation/sep-gate.mjs` (SC6), `tests/sep/reaudit-fixes.test.ts` |
|
|
21
|
+
| Crash the recorder to erase a decision (deeply-nested arg "depth bomb") | `canonicalize` is **depth-bounded**; the governance wrapper + proxy **fail closed** — an uncanonicalizable call is DENIED *and recorded*, never silently dropped or forwarded | `tests/proxy/dos-failclosed.test.ts`, `tests/sep/reaudit-fixes.test.ts` |
|
|
22
|
+
|
|
23
|
+
Claim scope is **integrity-of-present-receipts, NOT non-omission**: a PASS proves every *present* receipt is authentic and complete-as-a-set under the checkpoint; it does **not** prove the gateway logged every action it took. Completeness is bounded by the tamper-evidence of the interception point, which is outside the bundle.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 2. Governed vs ungoverned tool surface
|
|
28
|
+
|
|
29
|
+
**Governed (PEP-gated + SEP-recorded; PERMITTED/DENIED on every call):**
|
|
30
|
+
`measure_integrity`, `revoke_artifact`, `request_claim`, `delegate_to_subagent` — the agent-action tools.
|
|
31
|
+
|
|
32
|
+
**Ungoverned (by design):**
|
|
33
|
+
| Tool | Why ungoverned (safe) |
|
|
34
|
+
|---|---|
|
|
35
|
+
| `get_server_info`, `get_portal_state`, `get_receipts`, `get_chain_events`, `list_claims`, `verify_chain` | read-only; no side effects on the governed subject |
|
|
36
|
+
| `init_chain`, `attest_subject` | **bootstrap** — they *establish* the governance relationship (chicken-and-egg: cannot be gated by a policy that doesn't exist yet). `attest_subject` sets policy, it does not perform an agent action, and re-attestation **cannot erase** the prior SEP ledger (§1). |
|
|
37
|
+
| `generate_evidence_bundle`, `verify_bundle_offline` | **evidence operations** — must work *especially after* TERMINATION/quarantine (you need to export and verify the record once governance is revoked). Not agent actions; not SEP-recorded. (The legacy `create_checkpoint` continuity tool was removed in P4.) |
|
|
38
|
+
| `measure_behavior` | **detective-only** monitor (§CP2); records a provable drift finding, does not block unless `enforce=true`. |
|
|
39
|
+
|
|
40
|
+
**Maintenance invariant (must hold for the core claim):** any *new* tool that performs an agent **action** with side effects MUST be added to the governed set (i.e., NOT in `UNGOVERNED_TOOLS`), so it produces a PERMITTED/DENIED receipt. Read/bootstrap/evidence tools stay ungoverned. A CI check that flags new non-ungoverned-listed tools is recommended (future).
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 3. Residual attack surface (honest, deferred, or deployment-dependent)
|
|
45
|
+
|
|
46
|
+
1. **Proxy — mandatory mediation is a deployment property.** `GovernanceProxy` governs the path *through it*; if the agent can reach the upstream MCP server **directly** (network), it bypasses governance entirely. `upstreamUrl` (HTTP) is directly reachable. → **Deployment requirement:** the agent must be network-isolated so the proxy is its *only* route to tools. Documented, not code-enforceable here. *(Empirically demonstrated in CP3 A7: `_validation/redteam/a7-proxy-bypass.mjs` — a direct POST to the upstream fired a side effect with no receipt.)* **See `DEPLOYMENT.md` §1: stdio-upstream is the hardened default — the upstream is a non-network-reachable child process, closing this bypass by construction; HTTP-upstream mode now warns on stderr.**
|
|
47
|
+
2. **Proxy — only `method === "tools/call"` is policy-evaluated; partially mitigated in 3.0-rc.** Other JSON-RPC methods are still forwarded (not policy-evaluated), but they are now recorded as **signed passthrough receipts** in the evidence bundle for auditability — so a side-effecting non-`tools/call` method is no longer *invisible* (the CP3 A7 `admin/deleteAllData` would now appear as a `(passthrough)` receipt with `method` set and `reason: forwarded, not policy-evaluated`). Benign protocol methods (`initialize`, `ping`, `tools/list`, `*/list`, `notifications/*`, …) are excluded by default; an optional `denyMethods` denylist rejects known side-effecting methods (a **DENIED** passthrough receipt, not forwarded). **What this closes:** invisibility — every forwarded non-benign method is now in the tamper-evident, checkpoint-bound bundle. **What it does NOT close:** the method is not policy-evaluated and still *executes* unless explicitly denylisted (this is *visibility, not governance*), and a direct-to-upstream call (§3.1) still bypasses the proxy entirely. Full per-method policy evaluation remains future work.
|
|
48
|
+
3. **Proxy — denial is observable.** A DENIED call returns a distinctive `-32600` error, which an adversary can use as a policy-probing oracle. Low severity; structured denial metadata could be tightened later.
|
|
49
|
+
4. **Key persistence — mitigated in 3.0-rc.** The gateway signing key can be **persisted** via `AGA_GATEWAY_KEY` (64-hex seed) or `AGA_GATEWAY_KEY_FILE` (`DEPLOYMENT.md` §2), so `gateway_public_key` is stable and **pinnable across restarts**. The default remains an ephemeral key (warned on stderr). HSM/KMS backing remains future work. A verifier MUST still pin the key it expects.
|
|
50
|
+
5. **Storage durability (Sprint 5).** Default storage is in-memory → the live chain is lost on **process restart**. The cryptographic record survives via the **exported signed bundle**; durable cross-restart retention needs the SQLite/persistent backend (Sprint 5). The raw quarantine forensic buffer is in-memory by design (only the `arguments_hash` commitment is signed — privacy-preserving and sufficient to *prove* a capture).
|
|
51
|
+
6. **Out of scope entirely (not what AGA does).** AGA does not prevent: model jailbreaks, model-weight theft, credential compromise, or infrastructure compromise. It provides *accountability and provenance* for governed decisions, not prevention of those classes. If an attacker holds the gateway signing key, they can author receipts — protect the key (Sprint 4).
|
|
52
|
+
7. **Verifier-UX / unpinned consumers (NEW — CP3 A5).** A consumer that verifies a bundle **without pinning** the gateway key gets an integrity-only `VERIFIED` with `issuerVerified=false` — *even on a forged, attacker-signed, denial-free bundle*. This is correct (integrity-of-present-receipts ≠ provenance, and the result object/CLI say so explicitly), but a UI that shows a bare "VERIFIED" without prominently propagating `issuerVerified=false` could mislead a non-expert. → Downstream consumers (esp. the website demo) MUST pin the gateway key and never present an unpinned PASS as proof of *who* issued the bundle. **Mitigated in 3.0-rc:** the verify result now carries a prominent `summary` — `VERIFIED (provenance verified …)` vs `VERIFIED (integrity only — NOT provenance …)` — surfaced by `verify_bundle_offline` and the reference/`aga-verify` CLIs; key-pinning ergonomics are in `DEPLOYMENT.md` §2. Consumers must still pin.
|
|
53
|
+
8. **Cross-stack verifier conformance (CLOSED — 2026-06-07).** Earlier in the 3.0 hardening only `src/sep/verify.ts` carried the full strict floor; the reference `verify-sep.mjs`, the published `aga-verify`, Go, and Python lagged. **That asymmetry is now closed.** All six verifiers — engine (`src/sep`), reference (`verify-sep.mjs`), `aga-verify`, Go (`verify.go`), and Python (audited library + pure-stdlib) — apply the identical strict floor and return **byte-identical verdicts**. The shared floor: strict field allowlist; `envelope_consistency` (binds the unsigned `gateway_id`/`merkle_root`/`generated_at` to the signed/recomputed values); checkpoint-algorithm binding; lexicographic-string canonicalization with RFC-8785 integral-number normalization; complete small-order/non-canonical-key rejection; **one library-free canonical-timestamp rule** (exact `.sssZ` UTC form via an ASCII regex + integer-arithmetic calendar + lexicographic ordering — no native date parser); merkle-direction-token strictness (`left`/`right` only, length-matched); unpaired-UTF-16-surrogate rejection; depth-bounded never-throw; and whole-document parse (trailing content rejected). Verified by `npm run conformance:cross-stack` — six verifiers agree on every case in the committed corpus (55 cases incl. raw-byte/file-parse), confirmed across multiple rounds of independent blind differential re-audit. See `fixtures/cross-stack/README.md`. **Residual (by design, not a divergence):** the bundle envelope still carries four *unsigned* metadata fields with no signed counterpart — `bundle_id`, `schema_version`, `policy_reference`, `offline_capable`. They are informational and are **not** security-identity fields (the identity fields `gateway_id`/`merkle_root`/`generated_at` ARE bound); a relying party must still trust only signed/verified values and pin the gateway key (§3.7). Of the four, **`policy_reference` is the only identity-grade one** — but the governing policy IS captured and cryptographically verified inside **every signed receipt's own `policy_reference` field** (one of the 15 signed fields), so the unsigned *envelope* `policy_reference` is only a convenience mirror, not the source of truth. Binding the envelope copy is a recommended near-term (3.1) format revision; a coordinated verifier-output flag that marks these four envelope fields as unsigned/not-verified is a recommended enhancement, deliberately deferred here to avoid adding an untested cross-language output surface immediately after the cross-stack-consistency campaign (the verdict surface already attests only the steps it runs, and never claims these fields). One further residual is **unreachable by construction:** SEP signed fields are strings plus the single integer `leaf_count` (the emit guard `assertSignedReceiptFieldsAreStrings` forbids any other number in a signed field), so a verifier's canonicalization of a *non-integer / exponential* number placed in a signed field — which no conformant gateway can emit — is intentionally left unspecified and MAY differ across language stdlibs; it cannot affect any bundle a conformant gateway produces. Reachable string content is fully cross-stack-consistent (an exhaustive 0..0x10FFFF code-point sweep confirms the only ever-divergent characters, `U+2028`/`U+2029`, are normalized identically by every verifier).
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 4. CP3 adversarial verification results (2026-06-06)
|
|
58
|
+
|
|
59
|
+
A focused adversarial workflow ran **7 independent red-team attacks** on the core claim. Each was attempted *concretely* against the real in-process MCP server / proxy and the **pinned** reference verifier (`verify-sep.mjs`) and published-sound `aga-verify@2.0.0`. A1–A5 were fully adjudicated + agreed in the original workflow. **A6 and A7 — whose original adjudication hit a session usage cap — were re-adjudicated first-hand on 2026-06-07 from the source:** **A6 HELD** — `src/middleware/governance.ts` shows `UNGOVERNED_TOOLS` contains only read/bootstrap/evidence/monitor tools (no mutating agent-action), a tool is GOVERNED iff absent from that set, and every GOVERNED call that is blocked emits a signed DENIED receipt via the `deny()` path (including the fail-closed branch for uncanonicalizable arguments); **A7 RESIDUAL** — the only upstream-reach bypasses are exactly the documented §3.1 (direct upstream HTTP, a deployment/network-isolation property) and §3.2 (non-`tools/call` methods, now recorded as signed passthrough receipts); no new bypass was found. Scripts: `_validation/redteam/`.
|
|
60
|
+
|
|
61
|
+
| # | Attack | Result | Why |
|
|
62
|
+
|---|---|---|---|
|
|
63
|
+
| A1 | Tamper a DENIED receipt (19 mutations) | **HELD** | every mutation FAILED; signature + leaf-recompute + signed checkpoint each reject |
|
|
64
|
+
| A2 | Truncate (drop the DENIED receipt) | **HELD** | signed checkpoint binds `leaf_count`/head → truncated set fails `signed_checkpoint` |
|
|
65
|
+
| A3 | Reorder to bury the denial | **HELD** | `previous_receipt_hash` chain + checkpoint fail |
|
|
66
|
+
| A4 | Re-attest to erase | **HELD** | SEP ledger is not reset on `attest_subject`; the denial is still present in the export |
|
|
67
|
+
| A5 | Key-forge (attacker re-signs a denial-free bundle) | **HELD** | pinned to the real key → FAIL `gateway_key_match` on **both** verifiers; unpinned → integrity-only PASS with `issuerVerified=false` (by design; see §3.7) |
|
|
68
|
+
| A6 | PEP bypass (ungoverned mutating action) | **HELD** | all 16 tools censused; no ungoverned mutating agent-action; even blocked governed calls emit a DENIED receipt; `measure_behavior` enforcement is coupled to a signed receipt |
|
|
69
|
+
| A7 | Proxy bypass | **RESIDUAL** | every governed `tools/call` gets a receipt (PERMITTED+DENIED; DENIED never reaches upstream); the two bypasses are the already-documented §3.1 (direct upstream reach) and §3.2 (non-`tools/call` methods) |
|
|
70
|
+
|
|
71
|
+
**Verdict: 0 guarantee-broken — 6 HELD, 1 RESIDUAL (out-of-claim, already documented).** The core claim — *denials cannot be silently erased by the agent through tampering, truncation, reordering, or re-attestation, and forgery is caught when the gateway key is pinned* — **holds under the tested adversarial pressure**, on both the reference verifier and the published-sound `aga-verify@2.0.0`.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 5. Net boundary statement (for public copy)
|
|
76
|
+
|
|
77
|
+
> Every governed decision produces a signed, chained, checkpoint-bound receipt; denials cannot be silently erased by the agent through tampering, truncation, reordering, or re-attestation, and are independently verifiable offline with provenance. The behavioral monitor is detective-only by default. Mandatory mediation (network isolation), cross-session key persistence, and cross-restart durability are deployment/roadmap properties, documented above. AGA proves *what was governed*; it does not claim to prevent jailbreaks, key theft, or non-`tools/call` side channels.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"behavioral.d.ts","sourceRoot":"","sources":["../../src/core/behavioral.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"behavioral.d.ts","sourceRoot":"","sources":["../../src/core/behavioral.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,2CAA2C;IAC3C,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,mEAAmE;IACnE,mBAAmB,EAAE,MAAM,EAAE,EAAE,CAAC;IAChC,yCAAyC;IACzC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,UAAU,EAAE,mBAAmB,EAAE,CAAC;IAClC,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACrE;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAEvD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,WAAW,CAAwB;IAC3C,OAAO,CAAC,QAAQ,CAAmC;IAEnD,WAAW,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI;IAI/C,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI;IAQ3D,OAAO,IAAI,qBAAqB;IA0DhC,KAAK,IAAI,IAAI;CAGd"}
|
package/dist/core/behavioral.js
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Behavioral Drift Detection.
|
|
2
|
+
* Behavioral Drift Detection — DETECTIVE-ONLY.
|
|
3
|
+
*
|
|
3
4
|
* NIST-2025-0035: "Governance mechanisms must measure behavioral outputs
|
|
4
5
|
* and decision patterns in addition to static artifacts."
|
|
5
6
|
*
|
|
6
|
-
* Tracks tool invocation patterns and compares against a behavioral
|
|
7
|
-
*
|
|
7
|
+
* Tracks tool invocation patterns and compares against a behavioral baseline
|
|
8
|
+
* sealed in the policy artifact.
|
|
9
|
+
*
|
|
10
|
+
* SCOPE (honest): this monitor OBSERVES and REPORTS — by itself it does NOT block,
|
|
11
|
+
* deny, or prevent any tool call. It produces statistical drift findings. Enforcement
|
|
12
|
+
* (drift -> portal quarantine) is OPT-IN and lives in the server's `measure_behavior`
|
|
13
|
+
* handler (`enforce: true`), OFF by default. When drift is detected, the detection event
|
|
14
|
+
* is recorded as a signed SEP receipt so the finding itself is provable; whether it was
|
|
15
|
+
* acted upon is stated explicitly in that receipt's `reason`/`decision`.
|
|
8
16
|
*/
|
|
9
17
|
import { sha256Str } from '../crypto/hash.js';
|
|
10
18
|
export class BehavioralMonitor {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"behavioral.js","sourceRoot":"","sources":["../../src/core/behavioral.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"behavioral.js","sourceRoot":"","sources":["../../src/core/behavioral.ts"],"names":[],"mappings":"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"}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -6,8 +6,6 @@ export * from './receipt.js';
|
|
|
6
6
|
export * from './chain.js';
|
|
7
7
|
export * from './portal.js';
|
|
8
8
|
export * from './quarantine.js';
|
|
9
|
-
export * from './checkpoint.js';
|
|
10
|
-
export * from './bundle.js';
|
|
11
9
|
export * from './disclosure.js';
|
|
12
10
|
export * from './behavioral.js';
|
|
13
11
|
export * from './delegation.js';
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC"}
|
package/dist/core/index.js
CHANGED
|
@@ -6,8 +6,8 @@ export * from './receipt.js';
|
|
|
6
6
|
export * from './chain.js';
|
|
7
7
|
export * from './portal.js';
|
|
8
8
|
export * from './quarantine.js';
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
// Legacy continuity EVIDENCE path removed (P4): './checkpoint.js' and './bundle.js' (the unsound
|
|
10
|
+
// verifier + non-conformant Merkle) are physically deleted. Canonical path = src/sep.
|
|
11
11
|
export * from './disclosure.js';
|
|
12
12
|
export * from './behavioral.js';
|
|
13
13
|
export * from './delegation.js';
|
package/dist/core/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,iGAAiG;AACjG,sFAAsF;AACtF,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC"}
|