blindseal 0.5.0 → 0.5.1

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.
Files changed (34) hide show
  1. package/dashboard/assets/blindseal_verifier_bg-BYF7rQG1.wasm +0 -0
  2. package/dashboard/assets/geist-400-gapTbOY8.woff2 +0 -0
  3. package/dashboard/assets/geist-500-uokXdC-Q.woff2 +0 -0
  4. package/dashboard/assets/geist-600-DFOURf8L.woff2 +0 -0
  5. package/dashboard/assets/geist-mono-400-DTRLJnHl.woff2 +0 -0
  6. package/dashboard/assets/geist-mono-600-V-KvD_pi.woff2 +0 -0
  7. package/dashboard/assets/index-ErSVkiAF.css +1 -0
  8. package/dashboard/assets/index-cOSTL8eT.js +1 -0
  9. package/dashboard/assets/index-p0eB3k2y.js +70 -0
  10. package/dashboard/index.html +76 -0
  11. package/dist/attest-VWYZAOLY.js +346 -0
  12. package/dist/{audit-C756XFXR.js → audit-G4DDMAXH.js} +1 -1
  13. package/dist/chunk-6EU4GH4P.js +513 -0
  14. package/dist/chunk-B44GZXDX.js +136 -0
  15. package/dist/chunk-CIUQ6WHJ.js +88 -0
  16. package/dist/{chunk-BTIXDNTV.js → chunk-DJL2E6RF.js} +69 -6
  17. package/dist/{chunk-PQ457W6T.js → chunk-VSOUJM6X.js} +1 -0
  18. package/dist/{chunk-JJY62YXJ.js → chunk-ZZTWGFH2.js} +0 -20
  19. package/dist/dashboard-J6BA7OBL.js +105 -0
  20. package/dist/decide.js +1 -1
  21. package/dist/index.js +122 -1307
  22. package/dist/{init.js → init-ZP3SLHM3.js} +122 -36
  23. package/dist/run-YQBNEPSD.js +17 -0
  24. package/dist/{submit-2UALCRX2.js → submit-D6MQTAXT.js} +1 -1
  25. package/dist/verify-RISAGKXC.js +98 -0
  26. package/fixtures/attestation-sample.json +25 -0
  27. package/fixtures/attestation-tampered.json +29 -0
  28. package/fixtures/attestations.json +174 -0
  29. package/fixtures/audit.json +1810 -0
  30. package/fixtures/decisions.json +9899 -0
  31. package/fixtures/policy.json +216 -0
  32. package/package.json +8 -8
  33. package/dist/attest-QLIE2OSQ.js +0 -195
  34. package/dist/verify-HO4IU7XV.js +0 -45
@@ -0,0 +1,216 @@
1
+ {
2
+ "root": "0x36a9e9457db6ecfd752a379fc9279ad6a0acfea07928f61e2f3638a685c38397",
3
+ "version": 2,
4
+ "updatedAt": "2026-10-20T09:00:01.026Z",
5
+ "detectorVersion": "0x726faa56c0857bbace50727feedf504a76f37a98c975f565e44bf341fb29851d",
6
+ "leafCount": 23,
7
+ "parameters": {
8
+ "zeroWidthDensityThreshold": 0.1
9
+ },
10
+ "l0Decoders": [
11
+ "base64-decoded-run",
12
+ "hex-decoded-run",
13
+ "url-decoded-run",
14
+ "html-entity-decoded-run"
15
+ ],
16
+ "rules": [
17
+ {
18
+ "id": "unicode-tag-smuggling",
19
+ "layer": "L1",
20
+ "kind": "dfa",
21
+ "name": "unicode-tag-smuggling",
22
+ "severity": "Malicious",
23
+ "verdict": "block",
24
+ "enabled": true
25
+ },
26
+ {
27
+ "id": "bidi-override-smuggling",
28
+ "layer": "L1",
29
+ "kind": "dfa",
30
+ "name": "bidi-override-smuggling",
31
+ "severity": "Malicious",
32
+ "verdict": "block",
33
+ "enabled": true
34
+ },
35
+ {
36
+ "id": "html-entity-encoded-run",
37
+ "layer": "L1",
38
+ "kind": "dfa",
39
+ "name": "html-entity-encoded-run",
40
+ "severity": "Suspicious",
41
+ "verdict": "flag",
42
+ "enabled": true
43
+ },
44
+ {
45
+ "id": "instruction-prefix:ignore-previous",
46
+ "layer": "L1",
47
+ "kind": "dfa",
48
+ "name": "instruction-prefix:ignore-previous",
49
+ "severity": "Malicious",
50
+ "verdict": "block",
51
+ "enabled": true
52
+ },
53
+ {
54
+ "id": "instruction-prefix:disregard-above",
55
+ "layer": "L1",
56
+ "kind": "dfa",
57
+ "name": "instruction-prefix:disregard-above",
58
+ "severity": "Malicious",
59
+ "verdict": "block",
60
+ "enabled": true
61
+ },
62
+ {
63
+ "id": "instruction-prefix:forget-previous",
64
+ "layer": "L1",
65
+ "kind": "dfa",
66
+ "name": "instruction-prefix:forget-previous",
67
+ "severity": "Malicious",
68
+ "verdict": "block",
69
+ "enabled": true
70
+ },
71
+ {
72
+ "id": "instruction-prefix:system-prefix",
73
+ "layer": "L1",
74
+ "kind": "dfa",
75
+ "name": "instruction-prefix:system-prefix",
76
+ "severity": "Malicious",
77
+ "verdict": "block",
78
+ "enabled": true
79
+ },
80
+ {
81
+ "id": "instruction-prefix:you-are-now",
82
+ "layer": "L1",
83
+ "kind": "dfa",
84
+ "name": "instruction-prefix:you-are-now",
85
+ "severity": "Malicious",
86
+ "verdict": "block",
87
+ "enabled": true
88
+ },
89
+ {
90
+ "id": "instruction-prefix:new-instructions",
91
+ "layer": "L1",
92
+ "kind": "dfa",
93
+ "name": "instruction-prefix:new-instructions",
94
+ "severity": "Malicious",
95
+ "verdict": "block",
96
+ "enabled": true
97
+ },
98
+ {
99
+ "id": "instruction-prefix:override-above",
100
+ "layer": "L1",
101
+ "kind": "dfa",
102
+ "name": "instruction-prefix:override-above",
103
+ "severity": "Malicious",
104
+ "verdict": "block",
105
+ "enabled": true
106
+ },
107
+ {
108
+ "id": "html-comment-injection",
109
+ "layer": "L1",
110
+ "kind": "dfa",
111
+ "name": "html-comment-injection",
112
+ "severity": "Suspicious",
113
+ "verdict": "flag",
114
+ "enabled": true
115
+ },
116
+ {
117
+ "id": "markdown-link-prompt-anchor",
118
+ "layer": "L1",
119
+ "kind": "dfa",
120
+ "name": "markdown-link-prompt-anchor",
121
+ "severity": "Suspicious",
122
+ "verdict": "flag",
123
+ "enabled": true
124
+ },
125
+ {
126
+ "id": "large-base64-blob",
127
+ "layer": "L1",
128
+ "kind": "dfa",
129
+ "name": "large-base64-blob",
130
+ "severity": "Suspicious",
131
+ "verdict": "flag",
132
+ "enabled": true
133
+ },
134
+ {
135
+ "id": "bracket-ai-directive",
136
+ "layer": "L1",
137
+ "kind": "dfa",
138
+ "name": "bracket-ai-directive",
139
+ "severity": "Suspicious",
140
+ "verdict": "flag",
141
+ "enabled": true
142
+ },
143
+ {
144
+ "id": "refusal-suppression-directive",
145
+ "layer": "L1",
146
+ "kind": "dfa",
147
+ "name": "refusal-suppression-directive",
148
+ "severity": "Suspicious",
149
+ "verdict": "flag",
150
+ "enabled": true
151
+ },
152
+ {
153
+ "id": "memory-store-injection",
154
+ "layer": "L1",
155
+ "kind": "dfa",
156
+ "name": "memory-store-injection",
157
+ "severity": "Malicious",
158
+ "verdict": "block",
159
+ "enabled": true
160
+ },
161
+ {
162
+ "id": "pipeline-authority-claim",
163
+ "layer": "L1",
164
+ "kind": "dfa",
165
+ "name": "pipeline-authority-claim",
166
+ "severity": "Malicious",
167
+ "verdict": "block",
168
+ "enabled": true
169
+ },
170
+ {
171
+ "id": "sleeper-trigger-setup",
172
+ "layer": "L1",
173
+ "kind": "dfa",
174
+ "name": "sleeper-trigger-setup",
175
+ "severity": "Suspicious",
176
+ "verdict": "flag",
177
+ "enabled": true
178
+ },
179
+ {
180
+ "id": "recursive-output-injection",
181
+ "layer": "L1",
182
+ "kind": "dfa",
183
+ "name": "recursive-output-injection",
184
+ "severity": "Suspicious",
185
+ "verdict": "flag",
186
+ "enabled": true
187
+ },
188
+ {
189
+ "id": "dan-dual-label",
190
+ "layer": "L1",
191
+ "kind": "dfa",
192
+ "name": "dan-dual-label",
193
+ "severity": "Malicious",
194
+ "verdict": "block",
195
+ "enabled": true
196
+ },
197
+ {
198
+ "id": "affirmative-prefix-elicitation",
199
+ "layer": "L1",
200
+ "kind": "dfa",
201
+ "name": "affirmative-prefix-elicitation",
202
+ "severity": "Suspicious",
203
+ "verdict": "flag",
204
+ "enabled": true
205
+ },
206
+ {
207
+ "id": "task-reassignment-directive",
208
+ "layer": "L1",
209
+ "kind": "dfa",
210
+ "name": "task-reassignment-directive",
211
+ "severity": "Suspicious",
212
+ "verdict": "flag",
213
+ "enabled": true
214
+ }
215
+ ]
216
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blindseal",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "Blindseal — a local MCP proxy that screens every tool call (four detection layers), redacts before the model-based layers, keeps a hash-chained audit log, and produces zero-knowledge attestations verifiable on Solana.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://blindseal.tech",
@@ -15,11 +15,12 @@
15
15
  "bin": {
16
16
  "blindseal": "dist/index.js",
17
17
  "blindseal-audit": "dist/audit-view.js",
18
- "blindseal-init": "dist/init.js",
19
18
  "blindseal-decide": "dist/decide.js"
20
19
  },
21
20
  "files": [
22
- "dist"
21
+ "dist",
22
+ "dashboard",
23
+ "fixtures"
23
24
  ],
24
25
  "dependencies": {
25
26
  "@anthropic-ai/sdk": "^0.32.0",
@@ -27,7 +28,7 @@
27
28
  "@solana/web3.js": "1.98.0",
28
29
  "@xenova/transformers": "^2.17.2",
29
30
  "better-sqlite3": "^12.10.0",
30
- "blindseal-verifier-wasm": "0.5.0"
31
+ "blindseal-verifier-wasm": "0.5.1"
31
32
  },
32
33
  "devDependencies": {
33
34
  "@types/better-sqlite3": "^7.6.13",
@@ -36,11 +37,11 @@
36
37
  "tsx": "^4.19.0",
37
38
  "typescript": "^5.6.0",
38
39
  "vitest": "^2.1.0",
39
- "@blindseal/redactor": "0.0.1",
40
40
  "@blindseal/corpus": "0.0.1",
41
41
  "@blindseal/audit": "0.0.1",
42
+ "@blindseal/redactor": "0.0.1",
42
43
  "@blindseal/chain-reads": "0.0.0",
43
- "blindseal-sdk": "0.5.0"
44
+ "blindseal-sdk": "0.5.1"
44
45
  },
45
46
  "keywords": [
46
47
  "mcp",
@@ -58,10 +59,9 @@
58
59
  "access": "public"
59
60
  },
60
61
  "scripts": {
61
- "build": "tsup",
62
+ "build": "tsup && node scripts/bundle-assets.mjs",
62
63
  "dev": "tsx src/index.ts",
63
64
  "view-audit": "tsx src/cli/audit-view.ts",
64
- "init": "tsx src/cli/init.ts",
65
65
  "test": "vitest run",
66
66
  "typecheck": "tsc --noEmit",
67
67
  "bench:l3": "tsx bench/layer3-floor.ts"
@@ -1,195 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- makeLayer0Result,
4
- runLayer0,
5
- runLayer1
6
- } from "./chunk-XV57KLEO.js";
7
- import {
8
- openAudit
9
- } from "./chunk-PQ457W6T.js";
10
- import "./chunk-PDX44BCA.js";
11
-
12
- // src/cli/attest.ts
13
- import { createHash, randomBytes } from "crypto";
14
- import { existsSync, readFileSync, writeFileSync } from "fs";
15
- import { spawnSync } from "child_process";
16
- import os from "os";
17
- import path from "path";
18
-
19
- // src/chain/solana.ts
20
- var CHAIN_ID_SOLANA_MAINNET = 1;
21
- var SYSTEM_PROGRAM = "11111111111111111111111111111111";
22
- var TOKEN_PROGRAM = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
23
- var RECIPIENT_KEYS = ["recipient", "to", "destination", "dest", "receiver", "toPubkey", "toAddress"];
24
- var AMOUNT_KEYS = ["amount", "lamports", "value", "tokenAmount", "quantity"];
25
- var MINT_KEYS = ["mint", "token", "tokenMint", "mintAddress"];
26
- var AUTHORITY_KEYS = ["authority", "owner", "from", "source", "payer", "fromPubkey", "signer"];
27
- var PROGRAM_KEYS = ["program", "programId", "programAddress"];
28
- var TRANSFER_TOOL = /(?:^|_|\b)(?:transfer|send|pay|spl[_-]?transfer|transfer[_-]?checked)(?:_|\b|$)/i;
29
- function firstString(obj, keys) {
30
- for (const k of keys) {
31
- const v = obj[k];
32
- if (typeof v === "string" && v.length > 0) return v;
33
- if (typeof v === "number" && Number.isFinite(v)) return String(v);
34
- if (typeof v === "bigint") return v.toString();
35
- }
36
- return void 0;
37
- }
38
- function parseSolanaAction(toolName, args, opts = {}) {
39
- if (!args || typeof args !== "object") return null;
40
- const a = args;
41
- const amount = firstString(a, AMOUNT_KEYS);
42
- const recipient = firstString(a, RECIPIENT_KEYS);
43
- const explicitProgram = firstString(a, PROGRAM_KEYS);
44
- const looksLikeTransfer = TRANSFER_TOOL.test(toolName);
45
- if (!looksLikeTransfer && !explicitProgram) return null;
46
- if (recipient === void 0 && amount === void 0 && explicitProgram === void 0) return null;
47
- const mint = firstString(a, MINT_KEYS);
48
- const sourceAuthority = firstString(a, AUTHORITY_KEYS);
49
- void opts;
50
- const chainId = CHAIN_ID_SOLANA_MAINNET;
51
- const targetProgram = explicitProgram ?? (mint ? TOKEN_PROGRAM : SYSTEM_PROGRAM);
52
- const instruction = typeof a.instruction === "string" && a.instruction || typeof a.method === "string" && a.method || (mint ? "transferChecked" : "transfer");
53
- return {
54
- chain: "solana",
55
- chainId,
56
- targetProgram,
57
- instruction,
58
- recipient: recipient ?? "",
59
- mint: mint ?? "",
60
- amount: amount ?? "",
61
- sourceAuthority: sourceAuthority ?? ""
62
- };
63
- }
64
-
65
- // src/cli/attest.ts
66
- var HELP = `blindseal attest \u2014 screen a tool call, record the decision, prove it
67
-
68
- Usage:
69
- blindseal attest <toolcall.json> --out <attestation.json> --target-program <program id> [flags]
70
-
71
- Flags
72
- --out <file> where to write attestation.json (default ./attestation.json)
73
- --target-program <id> the gated program the action targets (base58)
74
- --instruction <16 hex> instruction discriminator (default: transfer-gate gated_transfer)
75
- --expiry <slot> expirySlot (default 2000000000)
76
- --prover <path> prover binary (default crates/prover/target/release/blindseal-prover)
77
- --audit-dir <dir> audit base dir (default ~/.blindseal)
78
- --help, -h this help
79
-
80
- Only clean verdicts are attested. The decision is appended to the hash-chained audit log first.
81
- `;
82
- var GATED_TRANSFER_DISC = "0x981894646560fc2b";
83
- function parse(argv) {
84
- const o = { out: "attestation.json", instruction: GATED_TRANSFER_DISC, expiry: "2000000000", auditDir: path.join(os.homedir(), ".blindseal") };
85
- for (let i = 0; i < argv.length; i++) {
86
- const a = argv[i];
87
- if (a === "--help" || a === "-h") o.help = true;
88
- else if (a === "--out") o.out = argv[++i];
89
- else if (a === "--target-program") o.targetProgram = argv[++i];
90
- else if (a === "--instruction") o.instruction = argv[++i];
91
- else if (a === "--expiry") o.expiry = argv[++i];
92
- else if (a === "--prover") o.prover = argv[++i];
93
- else if (a === "--audit-dir") o.auditDir = argv[++i];
94
- else if (a.startsWith("--")) throw new Error(`unknown flag: ${a}`);
95
- else o.file = a;
96
- }
97
- return o;
98
- }
99
- function findProver(explicit) {
100
- if (explicit) return explicit;
101
- let dir = process.cwd();
102
- for (let i = 0; i < 7; i++) {
103
- const c = path.join(dir, "crates/prover/target/release/blindseal-prover");
104
- if (existsSync(c)) return c;
105
- const parent = path.dirname(dir);
106
- if (parent === dir) break;
107
- dir = parent;
108
- }
109
- throw new Error("prover binary not found; build crates/prover or pass --prover");
110
- }
111
- async function runAttestCli(argv) {
112
- let o;
113
- try {
114
- o = parse(argv);
115
- } catch (e) {
116
- process.stderr.write(`blindseal attest: ${e.message}
117
- ${HELP}`);
118
- return 2;
119
- }
120
- if (o.help || !o.file) {
121
- process.stdout.write(HELP);
122
- return o.help ? 0 : 2;
123
- }
124
- if (!o.targetProgram) {
125
- process.stderr.write("blindseal attest: --target-program is required\n");
126
- return 2;
127
- }
128
- const raw = readFileSync(o.file, "utf8");
129
- const call = JSON.parse(raw);
130
- const payload = JSON.stringify({ tool: call.toolName, args: call.args });
131
- const payloadHash = "0x" + createHash("sha256").update(payload).digest("hex");
132
- const l0 = runLayer0(payload);
133
- const result = l0.fired ? makeLayer0Result(l0) : runLayer1(payload);
134
- const verdict = result.verdict;
135
- const decisionId = "d_" + randomBytes(8).toString("hex");
136
- const audit = openAudit(o.auditDir);
137
- const entry = audit.chain.append({ decisionId, verdict, payloadHash });
138
- process.stdout.write(`decision ${decisionId}: ${verdict} (audit #${entry.index} ${entry.hash.slice(0, 18)}\u2026)
139
- `);
140
- if (verdict !== "clean") {
141
- process.stderr.write(`blindseal attest: verdict is ${verdict} (${result.detectedPatterns.join(", ")}); no attestation for a non-clean call
142
- `);
143
- return 1;
144
- }
145
- const action = parseSolanaAction(call.toolName, call.args);
146
- if (!action) {
147
- process.stderr.write("blindseal attest: the call is not a recognizable on-chain action\n");
148
- return 1;
149
- }
150
- if (!action.recipient || !action.amount || !action.sourceAuthority) {
151
- process.stderr.write("blindseal attest: action needs recipient, amount and source authority\n");
152
- return 1;
153
- }
154
- const prover = findProver(o.prover);
155
- const tmpPayload = path.join(os.tmpdir(), `blindseal-payload-${decisionId}.json`);
156
- writeFileSync(tmpPayload, payload);
157
- const args = [
158
- "--payload",
159
- tmpPayload,
160
- "--out",
161
- o.out,
162
- "--decision-id",
163
- decisionId,
164
- "--chain-id",
165
- String(action.chainId),
166
- "--target-program",
167
- o.targetProgram,
168
- "--source-authority",
169
- action.sourceAuthority,
170
- "--recipient",
171
- action.recipient,
172
- "--mint",
173
- action.mint,
174
- "--amount",
175
- action.amount,
176
- "--instruction",
177
- o.instruction,
178
- "--expiry",
179
- o.expiry
180
- ];
181
- process.stdout.write(`proving (this takes a while on CPU)\u2026
182
- `);
183
- const r = spawnSync(prover, args, { stdio: "inherit" });
184
- if (r.status !== 0) {
185
- process.stderr.write(`blindseal attest: prover exited ${r.status}
186
- `);
187
- return 1;
188
- }
189
- process.stdout.write(`attestation written: ${o.out} (decision ${decisionId}, payloadHash ${payloadHash})
190
- `);
191
- return 0;
192
- }
193
- export {
194
- runAttestCli
195
- };
@@ -1,45 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- verifyOffchain
4
- } from "./chunk-BTIXDNTV.js";
5
- import {
6
- isCleanWindow,
7
- verifyDisclosure
8
- } from "./chunk-PQ457W6T.js";
9
- import "./chunk-PDX44BCA.js";
10
-
11
- // src/cli/verify.ts
12
- import { readFileSync } from "fs";
13
- var HELP = `blindseal verify \u2014 verify an attestation.json or a disclosure.json offline
14
-
15
- Usage:
16
- blindseal verify <file>
17
- `;
18
- async function runVerifyCli(argv) {
19
- const file = argv[0];
20
- if (!file || file === "--help" || file === "-h") {
21
- process.stdout.write(HELP);
22
- return file ? 0 : 2;
23
- }
24
- const doc = JSON.parse(readFileSync(file, "utf8"));
25
- if (Array.isArray(doc.entries) && typeof doc.signature === "string") {
26
- const d = doc;
27
- const v = verifyDisclosure(d);
28
- process.stdout.write(`disclosure ${file}: ${v.ok ? "VALID" : `INVALID \u2014 ${v.reason}`}
29
- `);
30
- if (v.ok) process.stdout.write(` window #${d.from}\u2013#${d.to}, ${d.entries.length} entries, signer ${d.signerPubkey.slice(0, 16)}\u2026, clean window: ${isCleanWindow(d) ? "yes" : "no"}
31
- `);
32
- return v.ok ? 0 : 1;
33
- }
34
- if (doc.proof && Array.isArray(doc.publicInputs)) {
35
- const r = await verifyOffchain(doc);
36
- process.stdout.write(`attestation ${file}: ${r.ok ? "VALID" : `INVALID \u2014 ${r.reason}`}
37
- `);
38
- return r.ok ? 0 : 1;
39
- }
40
- process.stderr.write("blindseal verify: not an attestation.json or a disclosure.json\n");
41
- return 2;
42
- }
43
- export {
44
- runVerifyCli
45
- };