taintguard 0.1.3

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 ADDED
@@ -0,0 +1,35 @@
1
+ **⚠️ Experimental – Not for production**
2
+
3
+ This package is a *reference implementation / idea starter* for span-based taint tracking and guardrails around LLM prompts. It is **not** a drop-in security control and comes **without guarantees**. Use it for exploration, prototypes, or as a basis for your own hardened implementation.
4
+ For any production use, perform your own threat modeling, add comprehensive tests, and combine with defense-in-depth controls (rate limiting, moderation, output validation, allowlists, human review, etc.).
5
+
6
+ # taintguard
7
+
8
+ Span-based taint tracking for LLM prompts (TypeScript-first).
9
+ Keep untrusted text from hijacking system instructions or tools. Fence low-trust data, enforce policies before the call, guard the stream token-by-token, and gate tool use by provenance.
10
+
11
+ ## Why taintguard?
12
+
13
+ Prompt injection thrives on mixing instructions with data. Regex-only filters are brittle. taintguard labels every text span with a trust level (root/trusted/low/unknown).
14
+
15
+ ## Features
16
+
17
+ 🧩 Span provenance: per-span trust + origin (system|user|rag|tool)
18
+ 🧱 Prompt fencing: XML-like <DATA trust="low">…</DATA> by default
19
+ 🔎 Preflight detection: jailbreak/role-hijack/“developer mode”/tool-trigger patterns
20
+ 💧 Leakage controls: deny lists for API keys, passwords, tokens
21
+ 📡 Streaming guards: token-wise mask/drop to avoid echoing risky text
22
+ 🔐 Tool gating: allow/deny lists; elevation required for sensitive tools
23
+ 🌍 Language packs: English & German rules out of the box
24
+ 🧪 Property tests: adversarial fuzzing (zero-width, homoglyphs, spacing) with fast-check
25
+
26
+ ## Quick Start
27
+
28
+ ```bash
29
+ pnpm i
30
+ pnpm build
31
+ pnpm test
32
+ ```
33
+
34
+ Branch Code Coverage: 79.48%
35
+ License: MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,313 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Context: () => Context,
24
+ auditedTool: () => auditedTool,
25
+ combinedRules: () => combinedRules,
26
+ compilePrompt: () => compilePrompt,
27
+ context: () => context,
28
+ deInjectionPhrases: () => deInjectionPhrases,
29
+ deLeakage: () => deLeakage,
30
+ deRules: () => deRules,
31
+ defineRules: () => defineRules,
32
+ emitAudit: () => emitAudit,
33
+ enInjectionPhrases: () => enInjectionPhrases,
34
+ enLeakage: () => enLeakage,
35
+ enRules: () => enRules,
36
+ guardedOpenAIChat: () => guardedOpenAIChat,
37
+ normalize: () => normalize,
38
+ preflight: () => preflight,
39
+ spanViolations: () => spanViolations,
40
+ streamGuard: () => streamGuard
41
+ });
42
+ module.exports = __toCommonJS(index_exports);
43
+
44
+ // src/core/context.ts
45
+ var Context = class {
46
+ messages = [];
47
+ add(role, text, trust, origin, meta) {
48
+ const span = { text, trust, origin, meta };
49
+ this.messages.push({ role, spans: [span] });
50
+ return this;
51
+ }
52
+ addSystem(text, opts) {
53
+ return this.add("system", text, opts?.trust ?? "root", "system");
54
+ }
55
+ addUser(text, opts) {
56
+ return this.add("user", text, opts?.trust ?? "low", "user");
57
+ }
58
+ addRag(text, opts) {
59
+ return this.add("user", text, opts?.trust ?? "trusted", "rag", opts?.meta);
60
+ }
61
+ list() {
62
+ return this.messages;
63
+ }
64
+ };
65
+ var context = () => new Context();
66
+
67
+ // src/core/homoglyph.ts
68
+ var MAP = {
69
+ "\u0430": "a",
70
+ // Cyrillic a -> Latin a
71
+ "\uFF45": "e",
72
+ // fullwidth e -> e
73
+ "\u0456": "i",
74
+ // Cyrillic i -> i
75
+ "\u043E": "o",
76
+ "\u0440": "p",
77
+ "\u0455": "s",
78
+ "\u0443": "y",
79
+ "\u0475": "v",
80
+ "\uFF1A": ":",
81
+ "\uFF0F": "/",
82
+ "\uFF0D": "-",
83
+ "\uFF3F": "_"
84
+ };
85
+ var foldHomoglyphs = (s) => s.replace(
86
+ /[аеіорѕуѵ:/-_]/g,
87
+ (ch) => MAP[ch] ?? ch
88
+ );
89
+
90
+ // src/core/normalizer.ts
91
+ var normalize = (s) => foldHomoglyphs(
92
+ s.normalize("NFKC").replace(/[​-‍]/g, "")
93
+ // zero-width
94
+ ).toLowerCase();
95
+
96
+ // src/core/detector.ts
97
+ function spanViolations(span, rules) {
98
+ const n = normalize(span.text);
99
+ const applicable = rules.filter((r) => r.when.from === span.trust);
100
+ const denies = applicable.flatMap((r) => r.deny.map((d) => typeof d === "string" ? new RegExp(d, "i") : d));
101
+ return denies.filter((re) => re.test(n)).map((re) => re.toString());
102
+ }
103
+
104
+ // src/core/rules.ts
105
+ var defineRules = (r) => r;
106
+
107
+ // src/core/renderer.ts
108
+ var fenceSpan = (s) => {
109
+ if (s.trust === "low") return `<DATA trust="low" origin="${s.origin}">${s.text}</DATA>`;
110
+ if (s.trust === "trusted") return `<DATA trust="trusted" origin="${s.origin}">${s.text}</DATA>`;
111
+ return s.text;
112
+ };
113
+ function compilePrompt(messages, opts) {
114
+ const parts = [];
115
+ for (const m of messages) {
116
+ for (const s of m.spans) {
117
+ parts.push(opts?.fenceLowTrust ? fenceSpan(s) : s.text);
118
+ }
119
+ }
120
+ const prompt = parts.join("\n\n");
121
+ const provenance = messages.flatMap((m) => m.spans.map((s) => ({ trust: s.trust, origin: s.origin })));
122
+ return { prompt, provenance };
123
+ }
124
+
125
+ // src/core/guard.ts
126
+ function preflight(messages, rules) {
127
+ const inj = rules.injections ?? [];
128
+ const v = [];
129
+ for (const m of messages) for (const s of m.spans) {
130
+ const hits = spanViolations(s, inj);
131
+ if (hits.length) v.push({ code: "INJECTION", message: `Denied patterns: ${hits.join(", ")}`, span: s });
132
+ }
133
+ return v;
134
+ }
135
+ function streamGuard(onTokenRules) {
136
+ const patterns = onTokenRules.denyLeakage ?? [];
137
+ return (tok) => {
138
+ if (patterns.some((r) => r.test(tok))) return "mask";
139
+ if (/ignore previous|you are now|override|entwicklermodus|du bist jetzt/i.test(tok)) return "drop";
140
+ return "pass";
141
+ };
142
+ }
143
+
144
+ // src/core/audit.ts
145
+ function isDebugEnabled() {
146
+ try {
147
+ const anyGlobal = globalThis;
148
+ const dbg = anyGlobal?.process?.env?.DEBUG ?? anyGlobal?.DEBUG ?? "";
149
+ return typeof dbg === "string" && dbg.includes("taintguard");
150
+ } catch {
151
+ return false;
152
+ }
153
+ }
154
+ function emitAudit(e) {
155
+ if (isDebugEnabled() && typeof console !== "undefined" && typeof console.debug === "function") {
156
+ console.debug("[audit]", e.type, e.data);
157
+ }
158
+ }
159
+
160
+ // src/tools/auditedTool.ts
161
+ function auditedTool(name, requiredTrust, impl) {
162
+ return async (args, ctx) => {
163
+ if (ctx.minTrust === "low") throw new Error(`TOOL_FORBIDDEN:${name}`);
164
+ if (requiredTrust === "trusted" && ctx.minTrust !== "trusted" && ctx.minTrust !== "root")
165
+ throw new Error(`TOOL_ELEVATION_REQUIRED:${name}`);
166
+ return impl(args);
167
+ };
168
+ }
169
+
170
+ // src/adapters/openai.ts
171
+ async function guardedOpenAIChat(fetchImpl, endpoint, apiKey, messages, rules) {
172
+ const violations = preflight(messages, rules);
173
+ if (violations.length) throw new Error(`GuardViolation:${JSON.stringify(violations)}`);
174
+ const { prompt } = compilePrompt(messages, { fenceLowTrust: true });
175
+ const res = await fetchImpl(endpoint, {
176
+ method: "POST",
177
+ headers: { "Content-Type": "application/json", "Authorization": `Bearer ${apiKey}` },
178
+ body: JSON.stringify({ model: "gpt-5", messages: [{ role: "user", content: prompt }] })
179
+ });
180
+ return res;
181
+ }
182
+
183
+ // src/packs/en.ts
184
+ var enInjectionPhrases = [
185
+ /ignore previous/i,
186
+ /previous instructions/i,
187
+ /ignore (all|the)? previous (instructions|messages)/i,
188
+ /disregard (all )?(rules|instructions)/i,
189
+ /you are now/i,
190
+ /act as/i,
191
+ /override (the )?(system|policy)/i,
192
+ /reset (the )?system prompt/i,
193
+ /developer mode/i,
194
+ /disable (safety|guardrails|filters)/i,
195
+ /call function/i,
196
+ /use tool/i,
197
+ /run tool/i,
198
+ /function call/i,
199
+ /use function/i,
200
+ /output raw text/i,
201
+ /answer (only|strictly) in/i,
202
+ /return unfiltered/i,
203
+ /do anything now/i,
204
+ /dan (mode)?/i,
205
+ /jailbreak/i,
206
+ /hypothetical/i,
207
+ /write a story about/i,
208
+ /simulate/i,
209
+ /repeat (the )?system prompt/i,
210
+ /reveal (your )?(prompt|instructions)/i,
211
+ /without ethics/i,
212
+ /in character as/i,
213
+ /\[?SYSTEM\b.+\]?/i,
214
+ /as a (text|fictional) model/i,
215
+ /print the instructions/i
216
+ ];
217
+ var enLeakage = [
218
+ /api[_ -]?key/i,
219
+ /secret/i,
220
+ /password/i,
221
+ /bearer\s+[a-z0-9\-_\.]+/i,
222
+ /private token/i,
223
+ /client[_ -]?secret/i
224
+ ];
225
+ var enRules = defineRules({
226
+ injections: [
227
+ { when: { from: "low" }, deny: enInjectionPhrases },
228
+ { when: { from: "unknown" }, deny: enInjectionPhrases }
229
+ ],
230
+ outputs: { denyLeakage: enLeakage }
231
+ });
232
+
233
+ // src/packs/de.ts
234
+ var deInjectionPhrases = [
235
+ /ignoriere vorherige/i,
236
+ /ignoriere (alle|die)? (vorherigen|bisherigen) (anweisungen|nachrichten)/i,
237
+ /missachte (alle )?(regeln|anweisungen)/i,
238
+ /du bist jetzt/i,
239
+ /tue so als ob|ag(iere)? als/i,
240
+ /überschreibe (den )?(system|policy)-prompt/i,
241
+ /setze den system[- ]?prompt zurück/i,
242
+ /entwicklermodus|developer[- ]?mode/i,
243
+ /sicherheit (deaktivieren|abschalten)/i,
244
+ /funktion (ausführen|verwenden|aufrufen|callen)/i,
245
+ /rohen? text ausgeben|ohne json antworten/i,
246
+ /ungefiltert zurückgeben/i,
247
+ /handle als ob|gib vor zu sein/i,
248
+ /ändere deine (persönlichkeit|rolle)/i,
249
+ /verhalte dich wie/i,
250
+ /geh über (deine )?(grenzen|einschränkungen) hinaus/i,
251
+ /zeige mir den (original|geheim)-prompt/i,
252
+ /zeige (den )?(inhalt|text|daten) ungefiltert/i,
253
+ /gib (alles|eine )?(alternative|verbotene) antwort/i,
254
+ /(antworte|sag) das (folgende|genau|jetzt|untenstehende)/i,
255
+ /deaktiviere (deine )?(zensur|filter|ethik)/i,
256
+ /was ist der (erste|anfangs) teil (deiner)? anweisung/i,
257
+ /gib den (ursprünglichen|systemischen) befehl aus/i,
258
+ /füge (den )?(folgenden )?text ein/i,
259
+ /verletzt du deine (regeln|richtlinien)/i,
260
+ /mach (eine|etwas) (gefährliche|illegale|verbotene) ausgabe/i,
261
+ /verstecke diese (anweisung|nachricht)/i,
262
+ /tarn(e)? dich als/i,
263
+ /(schalt|deaktivier) den sicherheitsmodus ab/i,
264
+ /systembeschränkungen (umgehen|ignoriere)/i
265
+ ];
266
+ var deLeakage = [
267
+ /api[_ -]?schl(ü|u)ssel/i,
268
+ /passwort/i,
269
+ /geheime?s? token/i,
270
+ /bearer\s+[a-z0-9\-_\.]+/i,
271
+ /client[_ -]?secret/i
272
+ ];
273
+ var deRules = defineRules({
274
+ injections: [
275
+ { when: { from: "low" }, deny: deInjectionPhrases },
276
+ { when: { from: "unknown" }, deny: deInjectionPhrases }
277
+ ],
278
+ outputs: { denyLeakage: deLeakage }
279
+ });
280
+
281
+ // src/packs/index.ts
282
+ var combinedRules = (lang = "both") => {
283
+ switch (lang) {
284
+ case "de":
285
+ return { lang, packs: ["de"] };
286
+ case "en":
287
+ return { lang, packs: ["en"] };
288
+ default:
289
+ return { lang, packs: ["de", "en"] };
290
+ }
291
+ };
292
+ // Annotate the CommonJS export names for ESM import in node:
293
+ 0 && (module.exports = {
294
+ Context,
295
+ auditedTool,
296
+ combinedRules,
297
+ compilePrompt,
298
+ context,
299
+ deInjectionPhrases,
300
+ deLeakage,
301
+ deRules,
302
+ defineRules,
303
+ emitAudit,
304
+ enInjectionPhrases,
305
+ enLeakage,
306
+ enRules,
307
+ guardedOpenAIChat,
308
+ normalize,
309
+ preflight,
310
+ spanViolations,
311
+ streamGuard
312
+ });
313
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/core/context.ts","../src/core/homoglyph.ts","../src/core/normalizer.ts","../src/core/detector.ts","../src/core/rules.ts","../src/core/renderer.ts","../src/core/guard.ts","../src/core/audit.ts","../src/tools/auditedTool.ts","../src/adapters/openai.ts","../src/packs/en.ts","../src/packs/de.ts","../src/packs/index.ts"],"sourcesContent":["export * from \"./core/types.js\";\nexport * from \"./core/context.js\";\nexport * from \"./core/normalizer.js\";\nexport * from \"./core/detector.js\";\nexport * from \"./core/rules.js\";\nexport * from \"./core/renderer.js\";\nexport * from \"./core/guard.js\";\nexport * from \"./core/audit.js\";\nexport * from \"./tools/auditedTool.js\";\nexport * from \"./adapters/openai.js\";\nexport * from \"./packs/index.js\";\n","import { Message, Span, Trust } from \"./types.js\";\n\nexport class Context {\n private messages: Message[] = [];\n add(role: Message[\"role\"], text: string, trust: Trust, origin: Span[\"origin\"], meta?: Span[\"meta\"]) {\n const span: Span = { text, trust, origin, meta };\n this.messages.push({ role, spans: [span] });\n return this;\n }\n addSystem(text: string, opts?: { trust?: Trust }) { return this.add(\"system\", text, opts?.trust ?? \"root\", \"system\"); }\n addUser(text: string, opts?: { trust?: Trust }) { return this.add(\"user\", text, opts?.trust ?? \"low\", \"user\"); }\n addRag(text: string, opts?: { trust?: Trust, meta?: any }) { return this.add(\"user\", text, opts?.trust ?? \"trusted\", \"rag\", opts?.meta); }\n list() { return this.messages; }\n}\nexport const context = () => new Context();\n","const MAP: Record<string, string> = {\n \"а\": \"a\", // Cyrillic a -> Latin a\n \"e\": \"e\", // fullwidth e -> e\n \"і\": \"i\", // Cyrillic i -> i\n \"о\": \"o\",\n \"р\": \"p\",\n \"ѕ\": \"s\",\n \"у\": \"y\",\n \"ѵ\": \"v\",\n \":\": \":\", \n \"/\": \"/\", \n \"-\": \"-\", \n \"_\": \"_\"\n};\nexport const foldHomoglyphs = (s: string) => s.replace(\n /[аеіорѕуѵ:/-_]/g,\n (ch) => MAP[ch] ?? ch\n);\n","import { foldHomoglyphs } from \"./homoglyph.js\";\n\nexport const normalize = (s: string) =>\n foldHomoglyphs(\n s.normalize(\"NFKC\")\n .replace(/[​-‍]/g, \"\") // zero-width\n ).toLowerCase();\n","import { Span, InjectionRule } from \"./types.js\";\nimport { normalize } from \"./normalizer.js\";\n\nexport function spanViolations(span: Span, rules: InjectionRule[]): string[] {\n const n = normalize(span.text);\n const applicable = rules.filter(r => r.when.from === span.trust);\n const denies = applicable.flatMap(r => r.deny.map(d => (typeof d === \"string\" ? new RegExp(d, \"i\") : d)));\n return denies.filter(re => re.test(n)).map(re => re.toString());\n}\n","import { Rules } from \"./types.js\";\nexport const defineRules = (r: Rules) => r;\n","import { Message, Span } from \"./types.js\";\n\nconst fenceSpan = (s: Span) => {\n if (s.trust === \"low\") return `<DATA trust=\"low\" origin=\"${s.origin}\">${s.text}</DATA>`;\n if (s.trust === \"trusted\") return `<DATA trust=\"trusted\" origin=\"${s.origin}\">${s.text}</DATA>`;\n return s.text;\n};\n\nexport function compilePrompt(messages: Message[], opts?: { fenceLowTrust?: boolean; hashSystem?: boolean }) {\n const parts: string[] = [];\n for (const m of messages) {\n for (const s of m.spans) {\n parts.push(opts?.fenceLowTrust ? fenceSpan(s) : s.text);\n }\n }\n const prompt = parts.join(\"\\n\\n\");\n const provenance = messages.flatMap(m => m.spans.map(s => ({ trust: s.trust, origin: s.origin })));\n return { prompt, provenance };\n}\n","import { Message, Rules, Violation } from \"./types.js\";\nimport { spanViolations } from \"./detector.js\";\n\nexport function preflight(messages: Message[], rules: Rules): Violation[] {\n const inj = rules.injections ?? [];\n const v: Violation[] = [];\n for (const m of messages) for (const s of m.spans) {\n const hits = spanViolations(s, inj);\n if (hits.length) v.push({ code: \"INJECTION\", message: `Denied patterns: ${hits.join(\", \")}`, span: s });\n }\n return v;\n}\n\nexport type StreamAction = \"pass\" | \"mask\" | \"drop\" | \"abort\";\nexport type OnToken = (tok: string) => StreamAction;\n\nexport function streamGuard(onTokenRules: { denyLeakage?: RegExp[] }) {\n const patterns = onTokenRules.denyLeakage ?? [];\n return (tok: string): StreamAction => {\n if (patterns.some(r => r.test(tok))) return \"mask\";\n if (/ignore previous|you are now|override|entwicklermodus|du bist jetzt/i.test(tok)) return \"drop\";\n return \"pass\";\n };\n}\n","export type AuditEvent = {\n type: \"violation\" | \"tool\" | \"prompt\";\n data: any;\n};\n\nfunction isDebugEnabled(): boolean {\n try {\n const anyGlobal: any = (globalThis as any);\n const dbg = anyGlobal?.process?.env?.DEBUG ?? anyGlobal?.DEBUG ?? \"\";\n return typeof dbg === \"string\" && dbg.includes(\"taintguard\");\n } catch {\n return false;\n }\n}\n\nexport function emitAudit(e: AuditEvent) {\n if (isDebugEnabled() && typeof console !== \"undefined\" && typeof console.debug === \"function\") {\n console.debug(\"[audit]\", e.type, e.data);\n }\n}\n","import { Trust } from \"../core/types.js\";\n\nexport function auditedTool<TArgs extends object>(\n name: string,\n requiredTrust: Exclude<Trust, \"low\">,\n impl: (args: TArgs) => Promise<any>\n) {\n return async (args: TArgs, ctx: { minTrust: Trust; why?: string; evidence?: string[] }) => {\n if (ctx.minTrust === \"low\") throw new Error(`TOOL_FORBIDDEN:${name}`);\n if (requiredTrust === \"trusted\" && ctx.minTrust !== \"trusted\" && ctx.minTrust !== \"root\")\n throw new Error(`TOOL_ELEVATION_REQUIRED:${name}`);\n return impl(args);\n };\n}\n","import { preflight } from \"../core/guard.js\";\nimport { compilePrompt } from \"../core/renderer.js\";\nimport { Rules, Message } from \"../core/types.js\";\n\nexport async function guardedOpenAIChat(fetchImpl: typeof fetch, endpoint: string, apiKey: string, messages: Message[], rules: Rules) {\n const violations = preflight(messages, rules);\n if (violations.length) throw new Error(`GuardViolation:${JSON.stringify(violations)}`);\n const { prompt } = compilePrompt(messages, { fenceLowTrust: true });\n\n const res = await fetchImpl(endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", \"Authorization\": `Bearer ${apiKey}` },\n body: JSON.stringify({ model: \"gpt-5\", messages: [{ role: \"user\", content: prompt }] })\n });\n return res;\n}\n","import { defineRules } from \"../core/rules.js\";\nimport { Rules } from \"../core/types.js\";\n\nexport const enInjectionPhrases: (RegExp | string)[] = [\n /ignore previous/i,\n /previous instructions/i,\n /ignore (all|the)? previous (instructions|messages)/i,\n /disregard (all )?(rules|instructions)/i,\n /you are now/i,\n /act as/i,\n /override (the )?(system|policy)/i,\n /reset (the )?system prompt/i,\n /developer mode/i,\n /disable (safety|guardrails|filters)/i,\n /call function/i, /use tool/i, /run tool/i, /function call/i, /use function/i,\n /output raw text/i, /answer (only|strictly) in/i,\n /return unfiltered/i,\n /do anything now/i,\n /dan (mode)?/i,\n /jailbreak/i,\n /hypothetical/i,\n /write a story about/i,\n /simulate/i,\n /repeat (the )?system prompt/i,\n /reveal (your )?(prompt|instructions)/i,\n /without ethics/i,\n /in character as/i,\n /\\[?SYSTEM\\b.+\\]?/i,\n /as a (text|fictional) model/i,\n /print the instructions/i\n];\n\nexport const enLeakage: RegExp[] = [\n /api[_ -]?key/i, /secret/i, /password/i, /bearer\\s+[a-z0-9\\-_\\.]+/i,\n /private token/i, /client[_ -]?secret/i,\n];\n\nexport const enRules: Rules = defineRules({\n injections: [\n { when: { from: \"low\" }, deny: enInjectionPhrases },\n { when: { from: \"unknown\" }, deny: enInjectionPhrases },\n ],\n outputs: { denyLeakage: enLeakage }\n});\n","import { defineRules } from \"../core/rules.js\";\nimport { Rules } from \"../core/types.js\";\n\nexport const deInjectionPhrases: (RegExp | string)[] = [\n /ignoriere vorherige/i,\n /ignoriere (alle|die)? (vorherigen|bisherigen) (anweisungen|nachrichten)/i,\n /missachte (alle )?(regeln|anweisungen)/i,\n /du bist jetzt/i,\n /tue so als ob|ag(iere)? als/i,\n /überschreibe (den )?(system|policy)-prompt/i,\n /setze den system[- ]?prompt zurück/i,\n /entwicklermodus|developer[- ]?mode/i,\n /sicherheit (deaktivieren|abschalten)/i,\n /funktion (ausführen|verwenden|aufrufen|callen)/i,\n /rohen? text ausgeben|ohne json antworten/i,\n /ungefiltert zurückgeben/i,\n /handle als ob|gib vor zu sein/i,\n /ändere deine (persönlichkeit|rolle)/i,\n /verhalte dich wie/i,\n /geh über (deine )?(grenzen|einschränkungen) hinaus/i,\n /zeige mir den (original|geheim)-prompt/i,\n /zeige (den )?(inhalt|text|daten) ungefiltert/i,\n /gib (alles|eine )?(alternative|verbotene) antwort/i,\n /(antworte|sag) das (folgende|genau|jetzt|untenstehende)/i,\n /deaktiviere (deine )?(zensur|filter|ethik)/i,\n /was ist der (erste|anfangs) teil (deiner)? anweisung/i,\n /gib den (ursprünglichen|systemischen) befehl aus/i,\n /füge (den )?(folgenden )?text ein/i,\n /verletzt du deine (regeln|richtlinien)/i,\n /mach (eine|etwas) (gefährliche|illegale|verbotene) ausgabe/i,\n /verstecke diese (anweisung|nachricht)/i,\n /tarn(e)? dich als/i,\n /(schalt|deaktivier) den sicherheitsmodus ab/i,\n /systembeschränkungen (umgehen|ignoriere)/i,\n];\n\nexport const deLeakage: RegExp[] = [\n /api[_ -]?schl(ü|u)ssel/i, /passwort/i, /geheime?s? token/i,\n /bearer\\s+[a-z0-9\\-_\\.]+/i, /client[_ -]?secret/i,\n];\n\nexport const deRules: Rules = defineRules({\n injections: [\n { when: { from: \"low\" }, deny: deInjectionPhrases },\n { when: { from: \"unknown\" }, deny: deInjectionPhrases },\n ],\n outputs: { denyLeakage: deLeakage }\n});\n","export * from \"./en.js\";\nexport * from \"./de.js\";\n\nexport const combinedRules = (lang: \"de\" | \"en\" | \"both\" = \"both\") => {\n switch (lang) {\n case \"de\": return { lang, packs: [\"de\"] as const };\n case \"en\": return { lang, packs: [\"en\"] as const };\n default: return { lang, packs: [\"de\",\"en\"] as const };\n }\n};\n"],"mappings":"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","names":[]}
@@ -0,0 +1,112 @@
1
+ type Trust = "root" | "trusted" | "low" | "unknown";
2
+ type Origin = "system" | "user" | "rag" | "tool";
3
+ type Span = {
4
+ text: string;
5
+ trust: Trust;
6
+ origin: Origin;
7
+ meta?: Record<string, any>;
8
+ };
9
+ type Message = {
10
+ role: "system" | "user" | "assistant";
11
+ spans: Span[];
12
+ };
13
+ type InjectionRule = {
14
+ when: {
15
+ from: Trust;
16
+ };
17
+ deny: (RegExp | string)[];
18
+ };
19
+ type ToolsRule = {
20
+ allow?: string[];
21
+ deny?: string[];
22
+ };
23
+ type OutputRule = {
24
+ mustBeJson?: boolean;
25
+ denyLeakage?: RegExp[];
26
+ };
27
+ type Rules = {
28
+ injections?: InjectionRule[];
29
+ tools?: ToolsRule;
30
+ outputs?: OutputRule;
31
+ };
32
+ type Violation = {
33
+ code: string;
34
+ message: string;
35
+ span?: Span;
36
+ };
37
+
38
+ declare class Context {
39
+ private messages;
40
+ add(role: Message["role"], text: string, trust: Trust, origin: Span["origin"], meta?: Span["meta"]): this;
41
+ addSystem(text: string, opts?: {
42
+ trust?: Trust;
43
+ }): this;
44
+ addUser(text: string, opts?: {
45
+ trust?: Trust;
46
+ }): this;
47
+ addRag(text: string, opts?: {
48
+ trust?: Trust;
49
+ meta?: any;
50
+ }): this;
51
+ list(): Message[];
52
+ }
53
+ declare const context: () => Context;
54
+
55
+ declare const normalize: (s: string) => string;
56
+
57
+ declare function spanViolations(span: Span, rules: InjectionRule[]): string[];
58
+
59
+ declare const defineRules: (r: Rules) => Rules;
60
+
61
+ declare function compilePrompt(messages: Message[], opts?: {
62
+ fenceLowTrust?: boolean;
63
+ hashSystem?: boolean;
64
+ }): {
65
+ prompt: string;
66
+ provenance: {
67
+ trust: Trust;
68
+ origin: Origin;
69
+ }[];
70
+ };
71
+
72
+ declare function preflight(messages: Message[], rules: Rules): Violation[];
73
+ type StreamAction = "pass" | "mask" | "drop" | "abort";
74
+ type OnToken = (tok: string) => StreamAction;
75
+ declare function streamGuard(onTokenRules: {
76
+ denyLeakage?: RegExp[];
77
+ }): (tok: string) => StreamAction;
78
+
79
+ type AuditEvent = {
80
+ type: "violation" | "tool" | "prompt";
81
+ data: any;
82
+ };
83
+ declare function emitAudit(e: AuditEvent): void;
84
+
85
+ declare function auditedTool<TArgs extends object>(name: string, requiredTrust: Exclude<Trust, "low">, impl: (args: TArgs) => Promise<any>): (args: TArgs, ctx: {
86
+ minTrust: Trust;
87
+ why?: string;
88
+ evidence?: string[];
89
+ }) => Promise<any>;
90
+
91
+ declare function guardedOpenAIChat(fetchImpl: typeof fetch, endpoint: string, apiKey: string, messages: Message[], rules: Rules): Promise<Response>;
92
+
93
+ declare const enInjectionPhrases: (RegExp | string)[];
94
+ declare const enLeakage: RegExp[];
95
+ declare const enRules: Rules;
96
+
97
+ declare const deInjectionPhrases: (RegExp | string)[];
98
+ declare const deLeakage: RegExp[];
99
+ declare const deRules: Rules;
100
+
101
+ declare const combinedRules: (lang?: "de" | "en" | "both") => {
102
+ lang: "de";
103
+ packs: readonly ["de"];
104
+ } | {
105
+ lang: "en";
106
+ packs: readonly ["en"];
107
+ } | {
108
+ lang: "both";
109
+ packs: readonly ["de", "en"];
110
+ };
111
+
112
+ export { type AuditEvent, Context, type InjectionRule, type Message, type OnToken, type Origin, type OutputRule, type Rules, type Span, type StreamAction, type ToolsRule, type Trust, type Violation, auditedTool, combinedRules, compilePrompt, context, deInjectionPhrases, deLeakage, deRules, defineRules, emitAudit, enInjectionPhrases, enLeakage, enRules, guardedOpenAIChat, normalize, preflight, spanViolations, streamGuard };
@@ -0,0 +1,112 @@
1
+ type Trust = "root" | "trusted" | "low" | "unknown";
2
+ type Origin = "system" | "user" | "rag" | "tool";
3
+ type Span = {
4
+ text: string;
5
+ trust: Trust;
6
+ origin: Origin;
7
+ meta?: Record<string, any>;
8
+ };
9
+ type Message = {
10
+ role: "system" | "user" | "assistant";
11
+ spans: Span[];
12
+ };
13
+ type InjectionRule = {
14
+ when: {
15
+ from: Trust;
16
+ };
17
+ deny: (RegExp | string)[];
18
+ };
19
+ type ToolsRule = {
20
+ allow?: string[];
21
+ deny?: string[];
22
+ };
23
+ type OutputRule = {
24
+ mustBeJson?: boolean;
25
+ denyLeakage?: RegExp[];
26
+ };
27
+ type Rules = {
28
+ injections?: InjectionRule[];
29
+ tools?: ToolsRule;
30
+ outputs?: OutputRule;
31
+ };
32
+ type Violation = {
33
+ code: string;
34
+ message: string;
35
+ span?: Span;
36
+ };
37
+
38
+ declare class Context {
39
+ private messages;
40
+ add(role: Message["role"], text: string, trust: Trust, origin: Span["origin"], meta?: Span["meta"]): this;
41
+ addSystem(text: string, opts?: {
42
+ trust?: Trust;
43
+ }): this;
44
+ addUser(text: string, opts?: {
45
+ trust?: Trust;
46
+ }): this;
47
+ addRag(text: string, opts?: {
48
+ trust?: Trust;
49
+ meta?: any;
50
+ }): this;
51
+ list(): Message[];
52
+ }
53
+ declare const context: () => Context;
54
+
55
+ declare const normalize: (s: string) => string;
56
+
57
+ declare function spanViolations(span: Span, rules: InjectionRule[]): string[];
58
+
59
+ declare const defineRules: (r: Rules) => Rules;
60
+
61
+ declare function compilePrompt(messages: Message[], opts?: {
62
+ fenceLowTrust?: boolean;
63
+ hashSystem?: boolean;
64
+ }): {
65
+ prompt: string;
66
+ provenance: {
67
+ trust: Trust;
68
+ origin: Origin;
69
+ }[];
70
+ };
71
+
72
+ declare function preflight(messages: Message[], rules: Rules): Violation[];
73
+ type StreamAction = "pass" | "mask" | "drop" | "abort";
74
+ type OnToken = (tok: string) => StreamAction;
75
+ declare function streamGuard(onTokenRules: {
76
+ denyLeakage?: RegExp[];
77
+ }): (tok: string) => StreamAction;
78
+
79
+ type AuditEvent = {
80
+ type: "violation" | "tool" | "prompt";
81
+ data: any;
82
+ };
83
+ declare function emitAudit(e: AuditEvent): void;
84
+
85
+ declare function auditedTool<TArgs extends object>(name: string, requiredTrust: Exclude<Trust, "low">, impl: (args: TArgs) => Promise<any>): (args: TArgs, ctx: {
86
+ minTrust: Trust;
87
+ why?: string;
88
+ evidence?: string[];
89
+ }) => Promise<any>;
90
+
91
+ declare function guardedOpenAIChat(fetchImpl: typeof fetch, endpoint: string, apiKey: string, messages: Message[], rules: Rules): Promise<Response>;
92
+
93
+ declare const enInjectionPhrases: (RegExp | string)[];
94
+ declare const enLeakage: RegExp[];
95
+ declare const enRules: Rules;
96
+
97
+ declare const deInjectionPhrases: (RegExp | string)[];
98
+ declare const deLeakage: RegExp[];
99
+ declare const deRules: Rules;
100
+
101
+ declare const combinedRules: (lang?: "de" | "en" | "both") => {
102
+ lang: "de";
103
+ packs: readonly ["de"];
104
+ } | {
105
+ lang: "en";
106
+ packs: readonly ["en"];
107
+ } | {
108
+ lang: "both";
109
+ packs: readonly ["de", "en"];
110
+ };
111
+
112
+ export { type AuditEvent, Context, type InjectionRule, type Message, type OnToken, type Origin, type OutputRule, type Rules, type Span, type StreamAction, type ToolsRule, type Trust, type Violation, auditedTool, combinedRules, compilePrompt, context, deInjectionPhrases, deLeakage, deRules, defineRules, emitAudit, enInjectionPhrases, enLeakage, enRules, guardedOpenAIChat, normalize, preflight, spanViolations, streamGuard };
package/dist/index.js ADDED
@@ -0,0 +1,269 @@
1
+ // src/core/context.ts
2
+ var Context = class {
3
+ messages = [];
4
+ add(role, text, trust, origin, meta) {
5
+ const span = { text, trust, origin, meta };
6
+ this.messages.push({ role, spans: [span] });
7
+ return this;
8
+ }
9
+ addSystem(text, opts) {
10
+ return this.add("system", text, opts?.trust ?? "root", "system");
11
+ }
12
+ addUser(text, opts) {
13
+ return this.add("user", text, opts?.trust ?? "low", "user");
14
+ }
15
+ addRag(text, opts) {
16
+ return this.add("user", text, opts?.trust ?? "trusted", "rag", opts?.meta);
17
+ }
18
+ list() {
19
+ return this.messages;
20
+ }
21
+ };
22
+ var context = () => new Context();
23
+
24
+ // src/core/homoglyph.ts
25
+ var MAP = {
26
+ "\u0430": "a",
27
+ // Cyrillic a -> Latin a
28
+ "\uFF45": "e",
29
+ // fullwidth e -> e
30
+ "\u0456": "i",
31
+ // Cyrillic i -> i
32
+ "\u043E": "o",
33
+ "\u0440": "p",
34
+ "\u0455": "s",
35
+ "\u0443": "y",
36
+ "\u0475": "v",
37
+ "\uFF1A": ":",
38
+ "\uFF0F": "/",
39
+ "\uFF0D": "-",
40
+ "\uFF3F": "_"
41
+ };
42
+ var foldHomoglyphs = (s) => s.replace(
43
+ /[аеіорѕуѵ:/-_]/g,
44
+ (ch) => MAP[ch] ?? ch
45
+ );
46
+
47
+ // src/core/normalizer.ts
48
+ var normalize = (s) => foldHomoglyphs(
49
+ s.normalize("NFKC").replace(/[​-‍]/g, "")
50
+ // zero-width
51
+ ).toLowerCase();
52
+
53
+ // src/core/detector.ts
54
+ function spanViolations(span, rules) {
55
+ const n = normalize(span.text);
56
+ const applicable = rules.filter((r) => r.when.from === span.trust);
57
+ const denies = applicable.flatMap((r) => r.deny.map((d) => typeof d === "string" ? new RegExp(d, "i") : d));
58
+ return denies.filter((re) => re.test(n)).map((re) => re.toString());
59
+ }
60
+
61
+ // src/core/rules.ts
62
+ var defineRules = (r) => r;
63
+
64
+ // src/core/renderer.ts
65
+ var fenceSpan = (s) => {
66
+ if (s.trust === "low") return `<DATA trust="low" origin="${s.origin}">${s.text}</DATA>`;
67
+ if (s.trust === "trusted") return `<DATA trust="trusted" origin="${s.origin}">${s.text}</DATA>`;
68
+ return s.text;
69
+ };
70
+ function compilePrompt(messages, opts) {
71
+ const parts = [];
72
+ for (const m of messages) {
73
+ for (const s of m.spans) {
74
+ parts.push(opts?.fenceLowTrust ? fenceSpan(s) : s.text);
75
+ }
76
+ }
77
+ const prompt = parts.join("\n\n");
78
+ const provenance = messages.flatMap((m) => m.spans.map((s) => ({ trust: s.trust, origin: s.origin })));
79
+ return { prompt, provenance };
80
+ }
81
+
82
+ // src/core/guard.ts
83
+ function preflight(messages, rules) {
84
+ const inj = rules.injections ?? [];
85
+ const v = [];
86
+ for (const m of messages) for (const s of m.spans) {
87
+ const hits = spanViolations(s, inj);
88
+ if (hits.length) v.push({ code: "INJECTION", message: `Denied patterns: ${hits.join(", ")}`, span: s });
89
+ }
90
+ return v;
91
+ }
92
+ function streamGuard(onTokenRules) {
93
+ const patterns = onTokenRules.denyLeakage ?? [];
94
+ return (tok) => {
95
+ if (patterns.some((r) => r.test(tok))) return "mask";
96
+ if (/ignore previous|you are now|override|entwicklermodus|du bist jetzt/i.test(tok)) return "drop";
97
+ return "pass";
98
+ };
99
+ }
100
+
101
+ // src/core/audit.ts
102
+ function isDebugEnabled() {
103
+ try {
104
+ const anyGlobal = globalThis;
105
+ const dbg = anyGlobal?.process?.env?.DEBUG ?? anyGlobal?.DEBUG ?? "";
106
+ return typeof dbg === "string" && dbg.includes("taintguard");
107
+ } catch {
108
+ return false;
109
+ }
110
+ }
111
+ function emitAudit(e) {
112
+ if (isDebugEnabled() && typeof console !== "undefined" && typeof console.debug === "function") {
113
+ console.debug("[audit]", e.type, e.data);
114
+ }
115
+ }
116
+
117
+ // src/tools/auditedTool.ts
118
+ function auditedTool(name, requiredTrust, impl) {
119
+ return async (args, ctx) => {
120
+ if (ctx.minTrust === "low") throw new Error(`TOOL_FORBIDDEN:${name}`);
121
+ if (requiredTrust === "trusted" && ctx.minTrust !== "trusted" && ctx.minTrust !== "root")
122
+ throw new Error(`TOOL_ELEVATION_REQUIRED:${name}`);
123
+ return impl(args);
124
+ };
125
+ }
126
+
127
+ // src/adapters/openai.ts
128
+ async function guardedOpenAIChat(fetchImpl, endpoint, apiKey, messages, rules) {
129
+ const violations = preflight(messages, rules);
130
+ if (violations.length) throw new Error(`GuardViolation:${JSON.stringify(violations)}`);
131
+ const { prompt } = compilePrompt(messages, { fenceLowTrust: true });
132
+ const res = await fetchImpl(endpoint, {
133
+ method: "POST",
134
+ headers: { "Content-Type": "application/json", "Authorization": `Bearer ${apiKey}` },
135
+ body: JSON.stringify({ model: "gpt-5", messages: [{ role: "user", content: prompt }] })
136
+ });
137
+ return res;
138
+ }
139
+
140
+ // src/packs/en.ts
141
+ var enInjectionPhrases = [
142
+ /ignore previous/i,
143
+ /previous instructions/i,
144
+ /ignore (all|the)? previous (instructions|messages)/i,
145
+ /disregard (all )?(rules|instructions)/i,
146
+ /you are now/i,
147
+ /act as/i,
148
+ /override (the )?(system|policy)/i,
149
+ /reset (the )?system prompt/i,
150
+ /developer mode/i,
151
+ /disable (safety|guardrails|filters)/i,
152
+ /call function/i,
153
+ /use tool/i,
154
+ /run tool/i,
155
+ /function call/i,
156
+ /use function/i,
157
+ /output raw text/i,
158
+ /answer (only|strictly) in/i,
159
+ /return unfiltered/i,
160
+ /do anything now/i,
161
+ /dan (mode)?/i,
162
+ /jailbreak/i,
163
+ /hypothetical/i,
164
+ /write a story about/i,
165
+ /simulate/i,
166
+ /repeat (the )?system prompt/i,
167
+ /reveal (your )?(prompt|instructions)/i,
168
+ /without ethics/i,
169
+ /in character as/i,
170
+ /\[?SYSTEM\b.+\]?/i,
171
+ /as a (text|fictional) model/i,
172
+ /print the instructions/i
173
+ ];
174
+ var enLeakage = [
175
+ /api[_ -]?key/i,
176
+ /secret/i,
177
+ /password/i,
178
+ /bearer\s+[a-z0-9\-_\.]+/i,
179
+ /private token/i,
180
+ /client[_ -]?secret/i
181
+ ];
182
+ var enRules = defineRules({
183
+ injections: [
184
+ { when: { from: "low" }, deny: enInjectionPhrases },
185
+ { when: { from: "unknown" }, deny: enInjectionPhrases }
186
+ ],
187
+ outputs: { denyLeakage: enLeakage }
188
+ });
189
+
190
+ // src/packs/de.ts
191
+ var deInjectionPhrases = [
192
+ /ignoriere vorherige/i,
193
+ /ignoriere (alle|die)? (vorherigen|bisherigen) (anweisungen|nachrichten)/i,
194
+ /missachte (alle )?(regeln|anweisungen)/i,
195
+ /du bist jetzt/i,
196
+ /tue so als ob|ag(iere)? als/i,
197
+ /überschreibe (den )?(system|policy)-prompt/i,
198
+ /setze den system[- ]?prompt zurück/i,
199
+ /entwicklermodus|developer[- ]?mode/i,
200
+ /sicherheit (deaktivieren|abschalten)/i,
201
+ /funktion (ausführen|verwenden|aufrufen|callen)/i,
202
+ /rohen? text ausgeben|ohne json antworten/i,
203
+ /ungefiltert zurückgeben/i,
204
+ /handle als ob|gib vor zu sein/i,
205
+ /ändere deine (persönlichkeit|rolle)/i,
206
+ /verhalte dich wie/i,
207
+ /geh über (deine )?(grenzen|einschränkungen) hinaus/i,
208
+ /zeige mir den (original|geheim)-prompt/i,
209
+ /zeige (den )?(inhalt|text|daten) ungefiltert/i,
210
+ /gib (alles|eine )?(alternative|verbotene) antwort/i,
211
+ /(antworte|sag) das (folgende|genau|jetzt|untenstehende)/i,
212
+ /deaktiviere (deine )?(zensur|filter|ethik)/i,
213
+ /was ist der (erste|anfangs) teil (deiner)? anweisung/i,
214
+ /gib den (ursprünglichen|systemischen) befehl aus/i,
215
+ /füge (den )?(folgenden )?text ein/i,
216
+ /verletzt du deine (regeln|richtlinien)/i,
217
+ /mach (eine|etwas) (gefährliche|illegale|verbotene) ausgabe/i,
218
+ /verstecke diese (anweisung|nachricht)/i,
219
+ /tarn(e)? dich als/i,
220
+ /(schalt|deaktivier) den sicherheitsmodus ab/i,
221
+ /systembeschränkungen (umgehen|ignoriere)/i
222
+ ];
223
+ var deLeakage = [
224
+ /api[_ -]?schl(ü|u)ssel/i,
225
+ /passwort/i,
226
+ /geheime?s? token/i,
227
+ /bearer\s+[a-z0-9\-_\.]+/i,
228
+ /client[_ -]?secret/i
229
+ ];
230
+ var deRules = defineRules({
231
+ injections: [
232
+ { when: { from: "low" }, deny: deInjectionPhrases },
233
+ { when: { from: "unknown" }, deny: deInjectionPhrases }
234
+ ],
235
+ outputs: { denyLeakage: deLeakage }
236
+ });
237
+
238
+ // src/packs/index.ts
239
+ var combinedRules = (lang = "both") => {
240
+ switch (lang) {
241
+ case "de":
242
+ return { lang, packs: ["de"] };
243
+ case "en":
244
+ return { lang, packs: ["en"] };
245
+ default:
246
+ return { lang, packs: ["de", "en"] };
247
+ }
248
+ };
249
+ export {
250
+ Context,
251
+ auditedTool,
252
+ combinedRules,
253
+ compilePrompt,
254
+ context,
255
+ deInjectionPhrases,
256
+ deLeakage,
257
+ deRules,
258
+ defineRules,
259
+ emitAudit,
260
+ enInjectionPhrases,
261
+ enLeakage,
262
+ enRules,
263
+ guardedOpenAIChat,
264
+ normalize,
265
+ preflight,
266
+ spanViolations,
267
+ streamGuard
268
+ };
269
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/context.ts","../src/core/homoglyph.ts","../src/core/normalizer.ts","../src/core/detector.ts","../src/core/rules.ts","../src/core/renderer.ts","../src/core/guard.ts","../src/core/audit.ts","../src/tools/auditedTool.ts","../src/adapters/openai.ts","../src/packs/en.ts","../src/packs/de.ts","../src/packs/index.ts"],"sourcesContent":["import { Message, Span, Trust } from \"./types.js\";\n\nexport class Context {\n private messages: Message[] = [];\n add(role: Message[\"role\"], text: string, trust: Trust, origin: Span[\"origin\"], meta?: Span[\"meta\"]) {\n const span: Span = { text, trust, origin, meta };\n this.messages.push({ role, spans: [span] });\n return this;\n }\n addSystem(text: string, opts?: { trust?: Trust }) { return this.add(\"system\", text, opts?.trust ?? \"root\", \"system\"); }\n addUser(text: string, opts?: { trust?: Trust }) { return this.add(\"user\", text, opts?.trust ?? \"low\", \"user\"); }\n addRag(text: string, opts?: { trust?: Trust, meta?: any }) { return this.add(\"user\", text, opts?.trust ?? \"trusted\", \"rag\", opts?.meta); }\n list() { return this.messages; }\n}\nexport const context = () => new Context();\n","const MAP: Record<string, string> = {\n \"а\": \"a\", // Cyrillic a -> Latin a\n \"e\": \"e\", // fullwidth e -> e\n \"і\": \"i\", // Cyrillic i -> i\n \"о\": \"o\",\n \"р\": \"p\",\n \"ѕ\": \"s\",\n \"у\": \"y\",\n \"ѵ\": \"v\",\n \":\": \":\", \n \"/\": \"/\", \n \"-\": \"-\", \n \"_\": \"_\"\n};\nexport const foldHomoglyphs = (s: string) => s.replace(\n /[аеіорѕуѵ:/-_]/g,\n (ch) => MAP[ch] ?? ch\n);\n","import { foldHomoglyphs } from \"./homoglyph.js\";\n\nexport const normalize = (s: string) =>\n foldHomoglyphs(\n s.normalize(\"NFKC\")\n .replace(/[​-‍]/g, \"\") // zero-width\n ).toLowerCase();\n","import { Span, InjectionRule } from \"./types.js\";\nimport { normalize } from \"./normalizer.js\";\n\nexport function spanViolations(span: Span, rules: InjectionRule[]): string[] {\n const n = normalize(span.text);\n const applicable = rules.filter(r => r.when.from === span.trust);\n const denies = applicable.flatMap(r => r.deny.map(d => (typeof d === \"string\" ? new RegExp(d, \"i\") : d)));\n return denies.filter(re => re.test(n)).map(re => re.toString());\n}\n","import { Rules } from \"./types.js\";\nexport const defineRules = (r: Rules) => r;\n","import { Message, Span } from \"./types.js\";\n\nconst fenceSpan = (s: Span) => {\n if (s.trust === \"low\") return `<DATA trust=\"low\" origin=\"${s.origin}\">${s.text}</DATA>`;\n if (s.trust === \"trusted\") return `<DATA trust=\"trusted\" origin=\"${s.origin}\">${s.text}</DATA>`;\n return s.text;\n};\n\nexport function compilePrompt(messages: Message[], opts?: { fenceLowTrust?: boolean; hashSystem?: boolean }) {\n const parts: string[] = [];\n for (const m of messages) {\n for (const s of m.spans) {\n parts.push(opts?.fenceLowTrust ? fenceSpan(s) : s.text);\n }\n }\n const prompt = parts.join(\"\\n\\n\");\n const provenance = messages.flatMap(m => m.spans.map(s => ({ trust: s.trust, origin: s.origin })));\n return { prompt, provenance };\n}\n","import { Message, Rules, Violation } from \"./types.js\";\nimport { spanViolations } from \"./detector.js\";\n\nexport function preflight(messages: Message[], rules: Rules): Violation[] {\n const inj = rules.injections ?? [];\n const v: Violation[] = [];\n for (const m of messages) for (const s of m.spans) {\n const hits = spanViolations(s, inj);\n if (hits.length) v.push({ code: \"INJECTION\", message: `Denied patterns: ${hits.join(\", \")}`, span: s });\n }\n return v;\n}\n\nexport type StreamAction = \"pass\" | \"mask\" | \"drop\" | \"abort\";\nexport type OnToken = (tok: string) => StreamAction;\n\nexport function streamGuard(onTokenRules: { denyLeakage?: RegExp[] }) {\n const patterns = onTokenRules.denyLeakage ?? [];\n return (tok: string): StreamAction => {\n if (patterns.some(r => r.test(tok))) return \"mask\";\n if (/ignore previous|you are now|override|entwicklermodus|du bist jetzt/i.test(tok)) return \"drop\";\n return \"pass\";\n };\n}\n","export type AuditEvent = {\n type: \"violation\" | \"tool\" | \"prompt\";\n data: any;\n};\n\nfunction isDebugEnabled(): boolean {\n try {\n const anyGlobal: any = (globalThis as any);\n const dbg = anyGlobal?.process?.env?.DEBUG ?? anyGlobal?.DEBUG ?? \"\";\n return typeof dbg === \"string\" && dbg.includes(\"taintguard\");\n } catch {\n return false;\n }\n}\n\nexport function emitAudit(e: AuditEvent) {\n if (isDebugEnabled() && typeof console !== \"undefined\" && typeof console.debug === \"function\") {\n console.debug(\"[audit]\", e.type, e.data);\n }\n}\n","import { Trust } from \"../core/types.js\";\n\nexport function auditedTool<TArgs extends object>(\n name: string,\n requiredTrust: Exclude<Trust, \"low\">,\n impl: (args: TArgs) => Promise<any>\n) {\n return async (args: TArgs, ctx: { minTrust: Trust; why?: string; evidence?: string[] }) => {\n if (ctx.minTrust === \"low\") throw new Error(`TOOL_FORBIDDEN:${name}`);\n if (requiredTrust === \"trusted\" && ctx.minTrust !== \"trusted\" && ctx.minTrust !== \"root\")\n throw new Error(`TOOL_ELEVATION_REQUIRED:${name}`);\n return impl(args);\n };\n}\n","import { preflight } from \"../core/guard.js\";\nimport { compilePrompt } from \"../core/renderer.js\";\nimport { Rules, Message } from \"../core/types.js\";\n\nexport async function guardedOpenAIChat(fetchImpl: typeof fetch, endpoint: string, apiKey: string, messages: Message[], rules: Rules) {\n const violations = preflight(messages, rules);\n if (violations.length) throw new Error(`GuardViolation:${JSON.stringify(violations)}`);\n const { prompt } = compilePrompt(messages, { fenceLowTrust: true });\n\n const res = await fetchImpl(endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", \"Authorization\": `Bearer ${apiKey}` },\n body: JSON.stringify({ model: \"gpt-5\", messages: [{ role: \"user\", content: prompt }] })\n });\n return res;\n}\n","import { defineRules } from \"../core/rules.js\";\nimport { Rules } from \"../core/types.js\";\n\nexport const enInjectionPhrases: (RegExp | string)[] = [\n /ignore previous/i,\n /previous instructions/i,\n /ignore (all|the)? previous (instructions|messages)/i,\n /disregard (all )?(rules|instructions)/i,\n /you are now/i,\n /act as/i,\n /override (the )?(system|policy)/i,\n /reset (the )?system prompt/i,\n /developer mode/i,\n /disable (safety|guardrails|filters)/i,\n /call function/i, /use tool/i, /run tool/i, /function call/i, /use function/i,\n /output raw text/i, /answer (only|strictly) in/i,\n /return unfiltered/i,\n /do anything now/i,\n /dan (mode)?/i,\n /jailbreak/i,\n /hypothetical/i,\n /write a story about/i,\n /simulate/i,\n /repeat (the )?system prompt/i,\n /reveal (your )?(prompt|instructions)/i,\n /without ethics/i,\n /in character as/i,\n /\\[?SYSTEM\\b.+\\]?/i,\n /as a (text|fictional) model/i,\n /print the instructions/i\n];\n\nexport const enLeakage: RegExp[] = [\n /api[_ -]?key/i, /secret/i, /password/i, /bearer\\s+[a-z0-9\\-_\\.]+/i,\n /private token/i, /client[_ -]?secret/i,\n];\n\nexport const enRules: Rules = defineRules({\n injections: [\n { when: { from: \"low\" }, deny: enInjectionPhrases },\n { when: { from: \"unknown\" }, deny: enInjectionPhrases },\n ],\n outputs: { denyLeakage: enLeakage }\n});\n","import { defineRules } from \"../core/rules.js\";\nimport { Rules } from \"../core/types.js\";\n\nexport const deInjectionPhrases: (RegExp | string)[] = [\n /ignoriere vorherige/i,\n /ignoriere (alle|die)? (vorherigen|bisherigen) (anweisungen|nachrichten)/i,\n /missachte (alle )?(regeln|anweisungen)/i,\n /du bist jetzt/i,\n /tue so als ob|ag(iere)? als/i,\n /überschreibe (den )?(system|policy)-prompt/i,\n /setze den system[- ]?prompt zurück/i,\n /entwicklermodus|developer[- ]?mode/i,\n /sicherheit (deaktivieren|abschalten)/i,\n /funktion (ausführen|verwenden|aufrufen|callen)/i,\n /rohen? text ausgeben|ohne json antworten/i,\n /ungefiltert zurückgeben/i,\n /handle als ob|gib vor zu sein/i,\n /ändere deine (persönlichkeit|rolle)/i,\n /verhalte dich wie/i,\n /geh über (deine )?(grenzen|einschränkungen) hinaus/i,\n /zeige mir den (original|geheim)-prompt/i,\n /zeige (den )?(inhalt|text|daten) ungefiltert/i,\n /gib (alles|eine )?(alternative|verbotene) antwort/i,\n /(antworte|sag) das (folgende|genau|jetzt|untenstehende)/i,\n /deaktiviere (deine )?(zensur|filter|ethik)/i,\n /was ist der (erste|anfangs) teil (deiner)? anweisung/i,\n /gib den (ursprünglichen|systemischen) befehl aus/i,\n /füge (den )?(folgenden )?text ein/i,\n /verletzt du deine (regeln|richtlinien)/i,\n /mach (eine|etwas) (gefährliche|illegale|verbotene) ausgabe/i,\n /verstecke diese (anweisung|nachricht)/i,\n /tarn(e)? dich als/i,\n /(schalt|deaktivier) den sicherheitsmodus ab/i,\n /systembeschränkungen (umgehen|ignoriere)/i,\n];\n\nexport const deLeakage: RegExp[] = [\n /api[_ -]?schl(ü|u)ssel/i, /passwort/i, /geheime?s? token/i,\n /bearer\\s+[a-z0-9\\-_\\.]+/i, /client[_ -]?secret/i,\n];\n\nexport const deRules: Rules = defineRules({\n injections: [\n { when: { from: \"low\" }, deny: deInjectionPhrases },\n { when: { from: \"unknown\" }, deny: deInjectionPhrases },\n ],\n outputs: { denyLeakage: deLeakage }\n});\n","export * from \"./en.js\";\nexport * from \"./de.js\";\n\nexport const combinedRules = (lang: \"de\" | \"en\" | \"both\" = \"both\") => {\n switch (lang) {\n case \"de\": return { lang, packs: [\"de\"] as const };\n case \"en\": return { lang, packs: [\"en\"] as const };\n default: return { lang, packs: [\"de\",\"en\"] as const };\n }\n};\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "taintguard",
3
+ "version": "0.1.3",
4
+ "description": "Span-based taint tracking for LLM prompts (TypeScript-first).",
5
+ "license": "MIT",
6
+ "author": "Maciej Rezler",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/rezlerski/taintguard.git"
10
+ },
11
+ "homepage": "https://github.com/rezlerski/taintguard",
12
+ "bugs": {
13
+ "url": "https://github.com/rezlerski/taintguard/issues"
14
+ },
15
+ "type": "module",
16
+ "sideEffects": false,
17
+ "engines": {
18
+ "node": ">=18"
19
+ },
20
+ "main": "dist/index.cjs",
21
+ "module": "dist/index.js",
22
+ "types": "dist/index.d.ts",
23
+ "exports": {
24
+ ".": {
25
+ "types": "./dist/index.d.ts",
26
+ "import": "./dist/index.js",
27
+ "require": "./dist/index.cjs",
28
+ "default": "./dist/index.js"
29
+ }
30
+ },
31
+ "files": [
32
+ "dist",
33
+ "README.md",
34
+ "LICENSE"
35
+ ],
36
+ "scripts": {
37
+ "clean": "rimraf dist || rm -rf dist",
38
+ "build": "tsup src/index.ts --format esm,cjs --dts --sourcemap --clean --target es2022",
39
+ "test": "vitest run",
40
+ "prepublishOnly": "npm run clean && npm run build && npm run test"
41
+ },
42
+ "keywords": [
43
+ "llm",
44
+ "ai-security",
45
+ "prompt-injection",
46
+ "typescript",
47
+ "taint-tracking"
48
+ ],
49
+ "devDependencies": {
50
+ "@types/node": "^22.7.5",
51
+ "@vitest/coverage-v8": "2.1.9",
52
+ "fast-check": "^3.18.0",
53
+ "rimraf": "^6.0.1",
54
+ "tsup": "^8.0.1",
55
+ "typescript": "^5.6.3",
56
+ "vitest": "^2.0.5"
57
+ },
58
+ "publishConfig": {
59
+ "access": "public"
60
+ }
61
+ }