theorum 0.1.14 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +178 -89
- package/esm/mod.d.ts +21 -11
- package/esm/mod.js +15 -8
- package/esm/src/cli/commands/bench.js +6 -3
- package/esm/src/cli/commands/fuzz-canary.d.ts +13 -0
- package/esm/src/cli/commands/fuzz-canary.js +195 -0
- package/esm/src/cli/commands/fuzz-guardrails.d.ts +3 -5
- package/esm/src/cli/commands/fuzz-guardrails.js +4 -581
- package/esm/src/cli/commands/profile.js +25 -14
- package/esm/src/cli/commands/run.d.ts +3 -0
- package/esm/src/cli/commands/run.js +22 -30
- package/esm/src/cli/commands/test.d.ts +10 -1
- package/esm/src/cli/commands/test.js +31 -31
- package/esm/src/cli/event-log.d.ts +19 -0
- package/esm/src/cli/event-log.js +147 -0
- package/esm/src/cli/index.js +45 -11
- package/esm/src/cli/matrix/synthesizer.d.ts +7 -9
- package/esm/src/cli/matrix/synthesizer.js +32 -106
- package/esm/src/guardrails/canary-gate.d.ts +20 -0
- package/esm/src/guardrails/canary-gate.js +31 -0
- package/esm/src/guardrails/canary.d.ts +26 -0
- package/esm/src/guardrails/canary.js +139 -0
- package/esm/src/guardrails/corpus/canary-egress-attacks.d.ts +16 -0
- package/esm/src/guardrails/corpus/canary-egress-attacks.js +151 -0
- package/esm/src/guardrails/corpus/fuzz-inbound.d.ts +11 -0
- package/esm/src/guardrails/corpus/fuzz-inbound.js +216 -0
- package/esm/src/guardrails/corpus/inbound-payloads.d.ts +10 -0
- package/esm/src/guardrails/corpus/inbound-payloads.js +124 -0
- package/esm/src/guardrails/corpus/live-attacks.d.ts +20 -0
- package/esm/src/guardrails/corpus/live-attacks.js +232 -0
- package/esm/src/guardrails/corpus/mod.d.ts +13 -0
- package/esm/src/guardrails/corpus/mod.js +11 -0
- package/esm/src/guardrails/corpus/secrets.d.ts +16 -0
- package/esm/src/guardrails/corpus/secrets.js +16 -0
- package/esm/src/guardrails/corpus/strings.d.ts +27 -0
- package/esm/src/guardrails/corpus/strings.js +33 -0
- package/esm/src/guardrails/corpus/types.d.ts +37 -0
- package/esm/src/guardrails/corpus/types.js +6 -0
- package/esm/src/guardrails/egress.d.ts +9 -0
- package/esm/src/guardrails/egress.js +36 -0
- package/esm/src/guardrails/error.js +6 -4
- package/esm/src/guardrails/injection.js +28 -5
- package/esm/src/guardrails/live-outbound-gate.d.ts +39 -0
- package/esm/src/guardrails/live-outbound-gate.js +180 -0
- package/esm/src/guardrails/mod.d.ts +13 -4
- package/esm/src/guardrails/mod.js +10 -4
- package/esm/src/guardrails/quota.js +1 -1
- package/esm/src/guardrails/sanitize.d.ts +11 -15
- package/esm/src/guardrails/sanitize.js +40 -49
- package/esm/src/guardrails/sensitive.js +2 -1
- package/esm/src/guardrails/testing.d.ts +10 -0
- package/esm/src/guardrails/testing.js +9 -0
- package/esm/src/host/client-turn.d.ts +19 -0
- package/esm/src/host/client-turn.js +32 -0
- package/esm/src/host/mod.d.ts +5 -3
- package/esm/src/host/mod.js +4 -3
- package/esm/src/interface/blocks.d.ts +20 -0
- package/esm/src/interface/blocks.js +180 -0
- package/esm/src/interface/from-profile.d.ts +14 -0
- package/esm/src/interface/from-profile.js +104 -0
- package/esm/src/interface/inputs.d.ts +8 -0
- package/esm/src/interface/inputs.js +127 -0
- package/esm/src/interface/mod.d.ts +10 -0
- package/esm/src/interface/mod.js +9 -0
- package/esm/src/interface/types.d.ts +153 -0
- package/esm/src/interface/types.js +13 -0
- package/esm/src/kernel/engine/delta.d.ts +24 -2
- package/esm/src/kernel/engine/delta.js +519 -29
- package/esm/src/kernel/engine/live-inbound.d.ts +9 -0
- package/esm/src/kernel/engine/live-inbound.js +17 -0
- package/esm/src/kernel/engine/repair.js +1 -1
- package/esm/src/kernel/engine/runner/gates.d.ts +1 -1
- package/esm/src/kernel/engine/runner/gates.js +7 -7
- package/esm/src/kernel/engine/runner/mod.js +13 -13
- package/esm/src/kernel/engine/runner/state.d.ts +7 -0
- package/esm/src/kernel/engine/runner/steps.d.ts +1 -1
- package/esm/src/kernel/engine/runner/steps.js +171 -37
- package/esm/src/kernel/engine/runner/stream.d.ts +1 -2
- package/esm/src/kernel/engine/runner/stream.js +66 -29
- package/esm/src/kernel/engine/session/mod.d.ts +23 -0
- package/esm/src/kernel/engine/session/mod.js +205 -0
- package/esm/src/kernel/mod.d.ts +9 -10
- package/esm/src/kernel/mod.js +6 -8
- package/esm/src/kernel/registry/attachments.d.ts +4 -2
- package/esm/src/kernel/registry/attachments.js +6 -3
- package/esm/src/kernel/registry/catalog.d.ts +3 -16
- package/esm/src/kernel/registry/catalog.js +5 -81
- package/esm/src/kernel/registry/ingress.d.ts +9 -4
- package/esm/src/kernel/registry/ingress.js +73 -63
- package/esm/src/kernel/registry/profiles.d.ts +35 -12
- package/esm/src/kernel/registry/profiles.js +159 -66
- package/esm/src/kernel/registry/provider-request.js +11 -7
- package/esm/src/kernel/registry/resolve.d.ts +5 -6
- package/esm/src/kernel/registry/resolve.js +100 -70
- package/esm/src/kernel/registry/vault.d.ts +12 -7
- package/esm/src/kernel/registry/vault.js +30 -8
- package/esm/src/kernel/schema.d.ts +145 -0
- package/esm/src/kernel/schema.js +462 -0
- package/esm/src/kernel/stop.d.ts +15 -10
- package/esm/src/kernel/stop.js +5 -5
- package/esm/src/kernel/tools/execute.d.ts +45 -0
- package/esm/src/kernel/tools/execute.js +363 -0
- package/esm/src/kernel/tools/harness.d.ts +8 -0
- package/esm/src/kernel/tools/harness.js +44 -0
- package/esm/src/kernel/tools/invoke.d.ts +10 -0
- package/esm/src/kernel/tools/invoke.js +83 -0
- package/esm/src/kernel/tools/mod.d.ts +11 -0
- package/esm/src/kernel/tools/mod.js +10 -0
- package/esm/src/kernel/tools/project.d.ts +12 -0
- package/esm/src/kernel/tools/project.js +34 -0
- package/esm/src/kernel/tools/registry.d.ts +23 -0
- package/esm/src/kernel/tools/registry.js +71 -0
- package/esm/src/kernel/tools/resolve.d.ts +29 -0
- package/esm/src/kernel/tools/resolve.js +262 -0
- package/esm/src/kernel/tools/schema.d.ts +13 -0
- package/esm/src/kernel/tools/schema.js +159 -0
- package/esm/src/kernel/tools/types.d.ts +216 -0
- package/esm/src/kernel/tools/types.js +9 -0
- package/esm/src/kernel/types.d.ts +338 -193
- package/esm/src/observability/trace-attach.d.ts +6 -4
- package/esm/src/observability/trace-attach.js +39 -25
- package/esm/src/observability/trace-record.d.ts +11 -9
- package/esm/src/observability/trace-record.js +36 -23
- package/esm/src/observability/trace-usage.d.ts +10 -3
- package/esm/src/observability/trace-usage.js +70 -17
- package/esm/src/observability/trace.d.ts +9 -1
- package/esm/src/observability/trace.js +11 -3
- package/esm/src/presets/google/speech-voices.d.ts +11 -0
- package/esm/src/presets/google/speech-voices.js +41 -0
- package/esm/src/presets/google.d.ts +36 -24
- package/esm/src/presets/google.js +50 -63
- package/esm/src/presets/mod.d.ts +2 -2
- package/esm/src/presets/mod.js +1 -1
- package/esm/src/providers/create-provider.d.ts +14 -14
- package/esm/src/providers/create-provider.js +55 -23
- package/esm/src/providers/google/interactions/framing.d.ts +15 -0
- package/esm/src/providers/google/interactions/framing.js +208 -0
- package/esm/src/providers/google/interactions/mod.d.ts +7 -0
- package/esm/src/providers/google/interactions/mod.js +7 -0
- package/esm/src/providers/google/interactions/stream.d.ts +83 -0
- package/esm/src/providers/google/interactions/stream.js +588 -0
- package/esm/src/providers/google/keys.d.ts +26 -0
- package/esm/src/providers/{keys.js → google/keys.js} +19 -31
- package/esm/src/providers/google/live/framing.d.ts +46 -0
- package/esm/src/providers/google/live/framing.js +515 -0
- package/esm/src/providers/google/live/openapi-schema.d.ts +6 -0
- package/esm/src/providers/google/live/openapi-schema.js +45 -0
- package/esm/src/providers/google/live/session.d.ts +25 -0
- package/esm/src/providers/google/live/session.js +134 -0
- package/esm/src/providers/google/live/stream.d.ts +36 -0
- package/esm/src/providers/google/live/stream.js +201 -0
- package/esm/src/providers/google/urls.d.ts +6 -0
- package/esm/src/providers/google/urls.js +6 -0
- package/esm/src/providers/local/local.d.ts +30 -0
- package/esm/src/providers/{local.js → local/local.js} +66 -126
- package/esm/src/providers/local/mod.d.ts +9 -0
- package/esm/src/providers/local/mod.js +9 -0
- package/esm/src/providers/mod.d.ts +6 -3
- package/esm/src/providers/mod.js +3 -1
- package/esm/src/providers/openrouter/chat.d.ts +87 -0
- package/esm/src/providers/{openrouter.js → openrouter/chat.js} +70 -229
- package/esm/src/providers/openrouter/image.d.ts +34 -0
- package/esm/src/providers/openrouter/image.js +286 -0
- package/esm/src/providers/openrouter/openai/chat-payload.d.ts +24 -0
- package/esm/src/providers/openrouter/openai/chat-payload.js +60 -0
- package/esm/src/providers/openrouter/openai/compat.d.ts +47 -0
- package/esm/src/providers/openrouter/openai/compat.js +194 -0
- package/esm/src/providers/openrouter/openai/image-payload.d.ts +18 -0
- package/esm/src/providers/openrouter/openai/image-payload.js +84 -0
- package/esm/src/providers/openrouter/openai/sdk-messages.d.ts +22 -0
- package/esm/src/providers/openrouter/openai/sdk-messages.js +95 -0
- package/esm/src/providers/openrouter/resolve-api-key.d.ts +9 -0
- package/esm/src/providers/openrouter/resolve-api-key.js +24 -0
- package/esm/src/providers/openrouter/speech.d.ts +23 -0
- package/esm/src/providers/{speech.js → openrouter/speech.js} +32 -55
- package/esm/src/providers/probe.d.ts +1 -0
- package/esm/src/providers/probe.js +22 -0
- package/esm/src/providers/shared/pcm.d.ts +12 -0
- package/esm/src/providers/{pcm.js → shared/pcm.js} +16 -3
- package/esm/src/providers/shared/sse.d.ts +18 -0
- package/esm/src/providers/shared/sse.js +87 -0
- package/esm/src/providers/shared/tool-args.d.ts +17 -0
- package/esm/src/providers/shared/tool-args.js +45 -0
- package/esm/src/providers/shared/upstream-tap.d.ts +5 -0
- package/esm/src/providers/{google-tap.js → shared/upstream-tap.js} +4 -7
- package/esm/src/providers/shared/upstream-tape.d.ts +6 -0
- package/esm/src/providers/{gemini-tape.js → shared/upstream-tape.js} +12 -22
- package/esm/src/providers/types.d.ts +27 -0
- package/esm/src/providers/types.js +1 -0
- package/package.json +11 -7
- package/docs/cli.md +0 -97
- package/docs/guardrails.md +0 -178
- package/docs/host.md +0 -97
- package/docs/kernel.md +0 -404
- package/docs/observability.md +0 -105
- package/docs/openrouter.md +0 -125
- package/docs/presets-google.md +0 -91
- package/docs/presets.md +0 -88
- package/docs/providers.md +0 -201
- package/docs/streaming.md +0 -96
- package/esm/src/kernel/engine/boundary.d.ts +0 -10
- package/esm/src/kernel/engine/boundary.js +0 -55
- package/esm/src/kernel/engine/runner/tools.d.ts +0 -13
- package/esm/src/kernel/engine/runner/tools.js +0 -198
- package/esm/src/kernel/registry/tools.d.ts +0 -12
- package/esm/src/kernel/registry/tools.js +0 -36
- package/esm/src/providers/expose-for-tests.d.ts +0 -1
- package/esm/src/providers/expose-for-tests.js +0 -25
- package/esm/src/providers/gemini-tape.d.ts +0 -2
- package/esm/src/providers/google-tap.d.ts +0 -3
- package/esm/src/providers/interactions.d.ts +0 -5
- package/esm/src/providers/interactions.js +0 -169
- package/esm/src/providers/keys.d.ts +0 -19
- package/esm/src/providers/local.d.ts +0 -29
- package/esm/src/providers/openrouter-mod.d.ts +0 -13
- package/esm/src/providers/openrouter-mod.js +0 -12
- package/esm/src/providers/openrouter-payload.d.ts +0 -39
- package/esm/src/providers/openrouter-payload.js +0 -195
- package/esm/src/providers/openrouter.d.ts +0 -15
- package/esm/src/providers/pcm.d.ts +0 -7
- package/esm/src/providers/provider.d.ts +0 -15
- package/esm/src/providers/provider.js +0 -176
- package/esm/src/providers/speech.d.ts +0 -23
- package/esm/src/providers/sse.d.ts +0 -7
- package/esm/src/providers/sse.js +0 -55
- package/esm/src/streaming/mod.d.ts +0 -9
- package/esm/src/streaming/mod.js +0 -8
- /package/esm/src/{streaming → host}/readStreamingJsonStringField.d.ts +0 -0
- /package/esm/src/{streaming → host}/readStreamingJsonStringField.js +0 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adversarial canary egress fuzzer.
|
|
3
|
+
*
|
|
4
|
+
* Pipes synthetic model leak attempts through the real runTurn stream gate
|
|
5
|
+
* and Live batch gate, then reports bypasses — output that still contains
|
|
6
|
+
* the raw per-turn canary token where the gate should have blocked.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
import { bindCanary, mintCanary, scanTextForCanaryLeak } from '../../guardrails/canary.js';
|
|
11
|
+
import { createCanaryGateSession, filterCanaryGatedEvents } from '../../guardrails/canary-gate.js';
|
|
12
|
+
import { buildCanaryEgressAttacks, FIXED_CANARY, } from '../../guardrails/corpus/canary-egress-attacks.js';
|
|
13
|
+
import { yieldProviderEvents } from '../../kernel/engine/runner/stream.js';
|
|
14
|
+
import { clearProfiles, registerProfile } from '../../kernel/registry/profiles.js';
|
|
15
|
+
import { resolveTurn } from '../../kernel/registry/resolve.js';
|
|
16
|
+
const FUZZ_PROFILE_ID = '__fuzz_canary__';
|
|
17
|
+
function registerFuzzCanaryProfile() {
|
|
18
|
+
registerProfile({
|
|
19
|
+
type: 'text',
|
|
20
|
+
id: FUZZ_PROFILE_ID,
|
|
21
|
+
identity: { handle: 'fuzz-canary', system: 'Canary fuzz profile.' },
|
|
22
|
+
model: {
|
|
23
|
+
protocol: 'openAi',
|
|
24
|
+
provider: 'openrouter',
|
|
25
|
+
allow: ['fuzz-model'],
|
|
26
|
+
config: {
|
|
27
|
+
'fuzz-model': {
|
|
28
|
+
apiId: 'fuzz-model',
|
|
29
|
+
thinking: { on: 'none', off: 'none' },
|
|
30
|
+
thinkingLevels: ['none'],
|
|
31
|
+
summaries: { on: 'none', off: 'none' },
|
|
32
|
+
maxOutputTokens: 4096,
|
|
33
|
+
temperature: 0,
|
|
34
|
+
builtInTools: [],
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
thinking: 'none',
|
|
38
|
+
},
|
|
39
|
+
tools: { allow: [] },
|
|
40
|
+
inputs: { text: true },
|
|
41
|
+
guardrails: { canary: true },
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function resolveFuzzGeneration(canary) {
|
|
45
|
+
const { generation } = resolveTurn({
|
|
46
|
+
profile: FUZZ_PROFILE_ID,
|
|
47
|
+
input: { text: 'fuzz' },
|
|
48
|
+
});
|
|
49
|
+
return { ...generation, canary };
|
|
50
|
+
}
|
|
51
|
+
async function collectEvents(gen) {
|
|
52
|
+
const out = [];
|
|
53
|
+
for await (const event of gen) {
|
|
54
|
+
out.push(event);
|
|
55
|
+
}
|
|
56
|
+
return out;
|
|
57
|
+
}
|
|
58
|
+
function clientVisibleWire(events) {
|
|
59
|
+
return JSON.stringify(events.filter((event) => event.type !== 'error'));
|
|
60
|
+
}
|
|
61
|
+
function literalCanaryReachedClient(events, canary) {
|
|
62
|
+
return clientVisibleWire(events).includes(canary);
|
|
63
|
+
}
|
|
64
|
+
function gateBlocked(events) {
|
|
65
|
+
return events.some((event) => event.type === 'error');
|
|
66
|
+
}
|
|
67
|
+
async function runStreamChannel(attack, generation, canary) {
|
|
68
|
+
async function* mockProvider() {
|
|
69
|
+
await Promise.resolve();
|
|
70
|
+
for (const event of attack.events) {
|
|
71
|
+
yield event;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const events = await collectEvents(yieldProviderEvents({
|
|
75
|
+
generation,
|
|
76
|
+
system: bindCanary('fuzz system', canary),
|
|
77
|
+
provider: { complete: mockProvider },
|
|
78
|
+
upstream: [],
|
|
79
|
+
}));
|
|
80
|
+
const blocked = gateBlocked(events);
|
|
81
|
+
const bypassed = attack.shouldBlock && literalCanaryReachedClient(events, canary);
|
|
82
|
+
const falseAlarm = !attack.shouldBlock && blocked;
|
|
83
|
+
return {
|
|
84
|
+
attack,
|
|
85
|
+
channel: 'runTurn.stream',
|
|
86
|
+
blocked,
|
|
87
|
+
bypassed,
|
|
88
|
+
falseAlarm,
|
|
89
|
+
clientWire: clientVisibleWire(events),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function runLiveBatchChannel(attack, canary) {
|
|
93
|
+
const session = createCanaryGateSession(canary);
|
|
94
|
+
const filtered = filterCanaryGatedEvents(session, attack.events);
|
|
95
|
+
if (filtered.leaked) {
|
|
96
|
+
return {
|
|
97
|
+
attack,
|
|
98
|
+
channel: 'live.batch',
|
|
99
|
+
blocked: true,
|
|
100
|
+
bypassed: false,
|
|
101
|
+
falseAlarm: !attack.shouldBlock,
|
|
102
|
+
clientWire: '',
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
const emitted = [...filtered.events];
|
|
106
|
+
const tail = session.gate.flush();
|
|
107
|
+
if (tail.leak) {
|
|
108
|
+
return {
|
|
109
|
+
attack,
|
|
110
|
+
channel: 'live.batch',
|
|
111
|
+
blocked: true,
|
|
112
|
+
bypassed: false,
|
|
113
|
+
falseAlarm: !attack.shouldBlock,
|
|
114
|
+
clientWire: clientVisibleWire(emitted),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
if (tail.emit) {
|
|
118
|
+
emitted.push({ type: session.lastStreamType ?? 'text', text: tail.emit });
|
|
119
|
+
}
|
|
120
|
+
const bypassed = attack.shouldBlock && literalCanaryReachedClient(emitted, canary);
|
|
121
|
+
const blocked = attack.shouldBlock && !bypassed;
|
|
122
|
+
const falseAlarm = !attack.shouldBlock && filtered.leaked;
|
|
123
|
+
return {
|
|
124
|
+
attack,
|
|
125
|
+
channel: 'live.batch',
|
|
126
|
+
blocked,
|
|
127
|
+
bypassed,
|
|
128
|
+
falseAlarm,
|
|
129
|
+
clientWire: clientVisibleWire(emitted),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function truncate(s, max) {
|
|
133
|
+
if (s.length <= max)
|
|
134
|
+
return s;
|
|
135
|
+
return `${s.slice(0, max - 3)}...`;
|
|
136
|
+
}
|
|
137
|
+
function printResults(results) {
|
|
138
|
+
const bypassed = results.filter((r) => r.bypassed);
|
|
139
|
+
const falseAlarms = results.filter((r) => r.falseAlarm);
|
|
140
|
+
const caught = results.filter((r) => r.attack.shouldBlock && r.blocked && !r.bypassed);
|
|
141
|
+
console.log(`\n${'═'.repeat(72)}`);
|
|
142
|
+
console.log(` TOTAL: ${results.length} | CAUGHT: ${caught.length} | BYPASSED: ${bypassed.length} | FALSE ALARM: ${falseAlarms.length}`);
|
|
143
|
+
console.log(`${'═'.repeat(72)}`);
|
|
144
|
+
if (bypassed.length > 0) {
|
|
145
|
+
console.log('\n\x1b[31mBYPASSED (canary reached client-visible output):\x1b[0m\n');
|
|
146
|
+
for (const r of bypassed) {
|
|
147
|
+
console.log(` ✗ ${r.attack.category}/${r.attack.name} [${r.channel}]`);
|
|
148
|
+
console.log(` \x1b[2m${truncate(r.clientWire, 90)}\x1b[0m`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (falseAlarms.length > 0) {
|
|
152
|
+
console.log('\n\x1b[33mFALSE ALARMS (benign payload blocked):\x1b[0m\n');
|
|
153
|
+
for (const r of falseAlarms) {
|
|
154
|
+
console.log(` ⚠ ${r.attack.category}/${r.attack.name} [${r.channel}]`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (bypassed.length === 0 && falseAlarms.length === 0) {
|
|
158
|
+
console.log('\n\x1b[32mAll leak attempts blocked; benign controls passed.\x1b[0m\n');
|
|
159
|
+
}
|
|
160
|
+
return bypassed.length === 0 && falseAlarms.length === 0;
|
|
161
|
+
}
|
|
162
|
+
/** Run adversarial canary fuzz; returns true when no bypasses or false alarms. */
|
|
163
|
+
export async function fuzzCanaryCommand(options) {
|
|
164
|
+
console.log('\n🔐 Theorum Canary Egress Adversarial Fuzzer\n');
|
|
165
|
+
clearProfiles();
|
|
166
|
+
registerFuzzCanaryProfile();
|
|
167
|
+
const canary = options?.canary ?? FIXED_CANARY;
|
|
168
|
+
if (!/^theo-[0-9a-f]{32}$/.test(canary)) {
|
|
169
|
+
console.error(`Invalid canary shape (expected theo- + 32 hex): ${canary}`);
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
// Sanity: mint path uses same shape
|
|
173
|
+
const minted = mintCanary();
|
|
174
|
+
if (!/^theo-[0-9a-f]{32}$/.test(minted)) {
|
|
175
|
+
console.error(`mintCanary produced unexpected shape: ${minted}`);
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
const generation = resolveFuzzGeneration(canary);
|
|
179
|
+
const attacks = buildCanaryEgressAttacks(canary);
|
|
180
|
+
console.log(`Canary: ${canary.slice(0, 12)}… (${attacks.length} attacks × 2 channels)`);
|
|
181
|
+
const results = [];
|
|
182
|
+
for (const attack of attacks) {
|
|
183
|
+
results.push(await runStreamChannel(attack, generation, canary));
|
|
184
|
+
results.push(runLiveBatchChannel(attack, canary));
|
|
185
|
+
}
|
|
186
|
+
// Spot-check scan helper matches expectations
|
|
187
|
+
if (!scanTextForCanaryLeak(canary, canary)) {
|
|
188
|
+
console.error('scanTextForCanaryLeak failed to detect literal canary');
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
const ok = printResults(results);
|
|
192
|
+
clearProfiles();
|
|
193
|
+
console.log('');
|
|
194
|
+
return ok;
|
|
195
|
+
}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Adversarial guardrail fuzzer.
|
|
3
|
-
*
|
|
4
|
-
* Throws injection payloads at every sanitization ingress and reports
|
|
5
|
-
* what gets through unchanged — meaning the guardrails missed it.
|
|
2
|
+
* Adversarial inbound guardrail fuzzer (CLI entry).
|
|
6
3
|
*
|
|
7
4
|
* @module
|
|
8
5
|
*/
|
|
9
|
-
|
|
6
|
+
/** Run inbound fuzz; returns true when no expected catches are missed. */
|
|
7
|
+
export declare function fuzzGuardrailsCommand(): boolean;
|