@guardbee/guard-core 0.1.0 → 0.2.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.
package/dist/injection.js CHANGED
@@ -1,43 +1,330 @@
1
- // Common prompt injection patterns
2
- export const INJECTION_PATTERNS = [
3
- /ignore\s+(all\s+)?(previous|prior|above)\s+instructions?/i,
4
- /disregard\s+(all\s+)?(previous|prior|above)\s+instructions?/i,
5
- /forget\s+(all\s+)?(previous|prior|above)\s+instructions?/i,
6
- /you\s+are\s+now\s+(a\s+)?(?!an?\s+AI|a\s+language)/i,
7
- /act\s+as\s+(if\s+you\s+are\s+)?(?!an?\s+AI|a\s+language)/i,
8
- /pretend\s+(you\s+are|to\s+be)\s+(?!an?\s+AI|a\s+language)/i,
9
- /jailbreak/i,
10
- /DAN\s+mode/i,
11
- /developer\s+mode/i,
12
- /system\s+prompt\s*:/i,
13
- /<\s*system\s*>/i,
14
- /\[SYSTEM\]/i,
15
- /bypass\s+(safety|filter|restriction|policy)/i,
16
- /override\s+(safety|filter|restriction|policy)/i,
17
- /reveal\s+(your\s+)?(system\s+prompt|instructions|prompt)/i,
18
- /print\s+(your\s+)?(system\s+prompt|instructions)/i,
1
+ /**
2
+ * Content that will reach a model: a tool result, a RAG chunk, a scraped page.
3
+ * Regexes are heuristics that aim for few false positives, not an intent model.
4
+ * The precise rules come from prompt-injection-scanner; the broad ones are the
5
+ * phrases security-proxy 0.x blocked on.
6
+ */
7
+ export const INJECTION_RULES = [
8
+ // ── Instruction override ────────────────────────────────────────────────────
9
+ {
10
+ id: "instruction_override_phrase",
11
+ name: "Content tells the model to ignore its prior instructions",
12
+ category: "instruction-override",
13
+ pattern: /\b(?:ignore|disregard|forget)\s+(?:all\s+|any\s+)?(?:previous|prior|above|earlier)\s+(?:instructions?|prompts?|rules?|context|directives?)\b/gi,
14
+ severity: "high",
15
+ recommendation: "This document contains a classic instruction-override phrase. If it enters a model's context via RAG retrieval or a tool result, it can hijack the model's behavior for the rest of the turn. Strip or quarantine this content before it reaches the model, or wrap retrieved content in clear data delimiters the model is instructed to never treat as commands.",
16
+ },
17
+ {
18
+ id: "instruction_override_tr",
19
+ name: "Content tells the model, in Turkish, to ignore its prior instructions",
20
+ category: "instruction-override",
21
+ pattern: /(?<!\p{L})(?:önceki|yukarıdaki|tüm|bütün)\s+(?:talimatları|talimatlar[ıi]n[ıi]|kuralları|yönergeleri|komutları)\s+(?:yok\s+say|unut|görmezden\s+gel|dikkate\s+alma|umursama)/giu,
22
+ severity: "high",
23
+ recommendation: "The Turkish form of an instruction-override phrase ('önceki talimatları yok say'). Pattern lists written only in English miss it. Treat the content as untrusted input and keep it out of the model's instructions.",
24
+ },
25
+ {
26
+ id: "dan_mode",
27
+ name: "Content switches the model into 'DAN mode'",
28
+ category: "instruction-override",
29
+ pattern: /\bDAN\s+mode\b/gi,
30
+ severity: "high",
31
+ recommendation: "'DAN mode' is a well-known jailbreak persona with no use in ordinary content. Quarantine content that asks for it.",
32
+ },
33
+ {
34
+ id: "you_are_now",
35
+ name: "Content assigns the model a new identity ('you are now …')",
36
+ category: "instruction-override",
37
+ pattern: /\byou\s+are\s+now\s+(?:a\s+)?(?!an?\s+AI\b|a\s+language\b)/gi,
38
+ severity: "medium",
39
+ broad: true,
40
+ recommendation: "Often part of a role-override injection, but also common in ordinary writing. Review the surrounding text.",
41
+ },
42
+ {
43
+ id: "act_as",
44
+ name: "Content asks the model to act as something else",
45
+ category: "instruction-override",
46
+ pattern: /\bact\s+as\s+(?:if\s+you\s+are\s+)?(?!an?\s+AI\b|a\s+language\b)/gi,
47
+ severity: "medium",
48
+ broad: true,
49
+ recommendation: "Often part of a role-override injection, but also common in ordinary writing ('act as a proxy'). Review the surrounding text.",
50
+ },
51
+ {
52
+ id: "pretend_to_be",
53
+ name: "Content asks the model to pretend to be something else",
54
+ category: "instruction-override",
55
+ pattern: /\bpretend\s+(?:you\s+are|to\s+be)\s+(?!an?\s+AI\b|a\s+language\b)/gi,
56
+ severity: "medium",
57
+ broad: true,
58
+ recommendation: "Often part of a role-override injection. Review the surrounding text.",
59
+ },
60
+ {
61
+ id: "role_override_tr",
62
+ name: "Content assigns the model a new identity, in Turkish ('sen artık …')",
63
+ category: "instruction-override",
64
+ pattern: /(?<!\p{L})(?:sen\s+artık|bundan\s+sonra\s+sen)\s+(?=\p{L})/giu,
65
+ severity: "medium",
66
+ broad: true,
67
+ recommendation: "Often part of a role-override injection, but also ordinary Turkish. Review the surrounding text.",
68
+ },
69
+ {
70
+ id: "jailbreak_word",
71
+ name: "Content mentions a jailbreak",
72
+ category: "instruction-override",
73
+ pattern: /\bjailbreak(?:ing|s)?\b/gi,
74
+ severity: "medium",
75
+ broad: true,
76
+ recommendation: "Articles about LLM security use this word too; on its own it is a weak signal.",
77
+ },
78
+ {
79
+ id: "developer_mode",
80
+ name: "Content asks for a 'developer mode'",
81
+ category: "instruction-override",
82
+ pattern: /\bdeveloper\s+mode\b/gi,
83
+ severity: "medium",
84
+ broad: true,
85
+ recommendation: "A common jailbreak framing, and a common phrase in software documentation.",
86
+ },
87
+ {
88
+ id: "bypass_safety",
89
+ name: "Content tells the model to bypass its safety measures",
90
+ category: "instruction-override",
91
+ pattern: /\b(?:bypass|override|disable)\s+(?:the\s+|your\s+|all\s+)?(?:safety|safeguards?|guardrails?|content\s+filters?)\b/gi,
92
+ severity: "high",
93
+ recommendation: "Content that tells a model to switch off its safety measures is an injection attempt. Quarantine it.",
94
+ },
95
+ {
96
+ id: "bypass_policy",
97
+ name: "Content mentions bypassing a filter, restriction or policy",
98
+ category: "instruction-override",
99
+ pattern: /\b(?:bypass|override)\s+(?:the\s+)?(?:filters?|restrictions?|polic(?:y|ies))\b/gi,
100
+ severity: "medium",
101
+ broad: true,
102
+ recommendation: "An injection phrase, but also everyday IT language ('override policy settings').",
103
+ },
104
+ // ── Role spoofing ────────────────────────────────────────────────────────────
105
+ {
106
+ id: "system_role_spoof",
107
+ name: "Content fakes a 'System:' role label",
108
+ category: "role-spoofing",
109
+ pattern: /(?:^|\n)\s*(?:#{1,3}\s*)?SYSTEM\s*:\s*\S/gim,
110
+ severity: "medium",
111
+ recommendation: "A line formatted like a chat-template system turn ('System: ...') inside retrieved content can trick a model (or a naive prompt-assembly step) into treating it as a real system instruction. Verify this is legitimate document content, not an injection attempt, before trusting it in a RAG/context pipeline.",
112
+ },
113
+ {
114
+ id: "chat_template_marker_injection",
115
+ name: "Raw chat-template control tokens embedded in content",
116
+ category: "role-spoofing",
117
+ pattern: /<\|(?:im_start|im_end|system|endoftext)\|>|\[INST\]|\[\/INST\]/g,
118
+ severity: "high",
119
+ recommendation: "Literal chat-template control tokens (e.g. <|im_start|>, [INST]) have no legitimate reason to appear in ordinary document content. If a model's tokenizer doesn't strip these, embedded tokens can hijack the conversation structure itself. Strip or escape these sequences before this content enters any model context.",
120
+ },
121
+ {
122
+ id: "system_tag",
123
+ name: "Content wraps text in a <system> tag",
124
+ category: "role-spoofing",
125
+ pattern: /<\s*\/?\s*system\s*>/gi,
126
+ severity: "high",
127
+ recommendation: "A <system> tag in data tries to pass the text off as a system message. Strip or escape it before the content reaches a model.",
128
+ },
129
+ {
130
+ id: "system_prompt_label",
131
+ name: "Content contains a 'system prompt:' label",
132
+ category: "role-spoofing",
133
+ pattern: /\bsystem\s+prompt\s*:/gi,
134
+ severity: "medium",
135
+ broad: true,
136
+ recommendation: "May introduce a fake system prompt; also appears in documentation about prompts.",
137
+ },
138
+ {
139
+ id: "system_bracket",
140
+ name: "Content contains a [SYSTEM] marker",
141
+ category: "role-spoofing",
142
+ pattern: /\[SYSTEM\]/gi,
143
+ severity: "medium",
144
+ broad: true,
145
+ recommendation: "May fake a system turn; also used as a log-level tag.",
146
+ },
147
+ // ── Hidden text ──────────────────────────────────────────────────────────────
148
+ {
149
+ id: "hidden_zero_width_chars",
150
+ name: "Zero-width characters that hide text from a human reviewer",
151
+ category: "hidden-text",
152
+ pattern: /[​⁠]/g,
153
+ severity: "medium",
154
+ recommendation: "Zero-width space/word-joiner characters render invisibly but are still read by a model. They're a common way to hide an injection payload from someone eyeballing the document while it still reaches the model. Inspect the surrounding text for hidden content, and consider stripping these characters before ingestion.",
155
+ },
156
+ {
157
+ id: "unicode_tag_smuggling",
158
+ name: "Invisible Unicode tag characters (ASCII smuggling)",
159
+ category: "hidden-text",
160
+ // A run of tag characters, except the one legitimate use: a subdivision flag
161
+ // emoji (🏴 + 1–6 lowercase/digit tags + CANCEL TAG, e.g. England). A run that
162
+ // starts after a flag or a tag is part of that flag; text hidden after a
163
+ // complete flag still matches through the second branch.
164
+ pattern: /(?<![\u{1F3F4}\u{E0000}-\u{E007F}])[\u{E0000}-\u{E007F}]+|\u{1F3F4}(?![\u{E0030}-\u{E0039}\u{E0061}-\u{E007A}]{1,6}\u{E007F}(?![\u{E0000}-\u{E007F}]))[\u{E0000}-\u{E007F}]+/gu,
165
+ severity: "critical",
166
+ recommendation: "Unicode tag characters (U+E0000–U+E007F) mirror ASCII but render as nothing. Text encoded in them is invisible to a person and readable by many models — a known way to smuggle instructions. Apart from subdivision flag emoji, ordinary text never needs them; strip them before the content reaches a model.",
167
+ },
168
+ {
169
+ id: "bidi_control_chars",
170
+ name: "Bidirectional control characters that reorder displayed text",
171
+ category: "hidden-text",
172
+ pattern: /[‪-‮⁦-⁩]/g,
173
+ severity: "medium",
174
+ recommendation: "Bidi embedding/override characters make text display in a different order than it is read (the 'Trojan Source' technique). Right-to-left languages rarely need the override forms; check what the text says once the controls are removed.",
175
+ },
176
+ {
177
+ id: "css_hidden_text_with_instruction",
178
+ name: "CSS-hidden element containing injection-flavored language",
179
+ category: "hidden-text",
180
+ // `color` alone, not `background-color`; the language must read as an instruction,
181
+ // not just contain "ignore" (as in `<!-- prettier-ignore -->`).
182
+ pattern: /style\s*=\s*["'][^"']*(?:display\s*:\s*none|visibility\s*:\s*hidden|font-size\s*:\s*0(?:px)?|(?<![\w-])color\s*:\s*(?:white|#fff(?:fff)?\b|transparent))[^"']*["'][\s\S]{0,200}?(?:(?<![\w-])(?:ignore|disregard)\s+(?:all|any|the|previous|prior|above|earlier|your|these|those|everything)\b|\bsystem\s+prompt\b|\b(?:your|previous|prior)\s+instructions\b|\b(?:AI|assistant|LLM|chatbot)\s*:|\b(?:you|the)\s+(?:AI|assistant|LLM|model)\b)/gi,
183
+ severity: "high",
184
+ recommendation: "This element is hidden from a rendered page (display:none / zero font-size / white-on-white) but a scraper feeding a RAG pipeline still extracts its text — and it contains injection-flavored language. Strip hidden elements before extracting text for a model, or render the page and use only the visible text.",
185
+ },
186
+ {
187
+ id: "html_comment_instruction",
188
+ name: "HTML comment containing injection-flavored language",
189
+ category: "hidden-text",
190
+ pattern: /<!--[\s\S]{0,300}?(?:(?<![\w-])(?:ignore|disregard)\s+(?:all|any|the|previous|prior|above|earlier|your|these|those|everything)\b|\bsystem\s+prompt\b|\b(?:your|previous|prior)\s+instructions\b|\b(?:AI|assistant|LLM|chatbot)\s*:|\b(?:you|the)\s+(?:AI|assistant|LLM|model)\b)[\s\S]{0,300}?-->/gi,
191
+ severity: "high",
192
+ recommendation: "HTML comments are invisible when a page is rendered but are usually still present in scraped/extracted text. This comment contains language associated with instruction injection. Strip HTML comments before feeding scraped content to a model.",
193
+ },
194
+ // ── Direct address ────────────────────────────────────────────────────────────
195
+ {
196
+ id: "direct_address_to_ai",
197
+ name: "Content directly addresses 'the AI' or 'the assistant'",
198
+ category: "direct-address",
199
+ pattern: /\b(?:dear|hey|attention|note to)\s+(?:the\s+)?(?:AI|assistant|chatbot|language model|LLM)\b/gi,
200
+ severity: "medium",
201
+ recommendation: "An ordinary document doesn't address 'the AI' or 'the assistant' directly — this phrasing strongly suggests the content was written to be read and obeyed by a model rather than a human. Treat this document as untrusted input, not as a source of instructions.",
202
+ },
203
+ // ── Exfiltration ──────────────────────────────────────────────────────────────
204
+ {
205
+ id: "exfiltration_url_template_in_image",
206
+ name: "Markdown image URL with a template placeholder (data-exfil beacon)",
207
+ category: "exfiltration",
208
+ pattern: /!\[[^\]]*\]\(\s*https?:\/\/[^)]*(?:\{\{[^}]*\}\}|\$\{[^}]*\})[^)]*\)/g,
209
+ severity: "high",
210
+ recommendation: "A markdown image URL containing a template placeholder ({{...}} or ${...}) is a classic exfiltration beacon: a client that auto-renders the image will fetch this URL, and anything the model interpolated into the placeholder (conversation text, secrets) leaks to whoever controls that domain. Never let a model auto-render an image URL it (or retrieved content) constructed.",
211
+ },
212
+ {
213
+ id: "reveal_system_prompt_request",
214
+ name: "Content asks the model to reveal its system prompt or instructions",
215
+ category: "exfiltration",
216
+ pattern: /\b(?:reveal|show|print|output|repeat)\s+(?:your\s+)?(?:system\s+prompt|initial\s+instructions|hidden\s+instructions)\b/gi,
217
+ severity: "high",
218
+ recommendation: "This is a standard prompt-extraction phrase. If it's embedded in retrieved content (not typed by the user), a model that processes/summarizes this document may leak its own system prompt or configuration in the response. Instruct the model to never disclose its instructions regardless of what retrieved content asks.",
219
+ },
220
+ {
221
+ id: "reveal_system_prompt_tr",
222
+ name: "Content asks the model, in Turkish, to reveal its system prompt",
223
+ category: "exfiltration",
224
+ pattern: /(?:sistem\s+(?:istemini|promptunu|talimatlarını|mesajını)|gizli\s+talimatlarını|ilk\s+talimatlarını)\s+(?:göster|yaz|söyle|tekrarla|paylaş|ver)/giu,
225
+ severity: "high",
226
+ recommendation: "The Turkish form of a prompt-extraction phrase. Instruct the model never to disclose its instructions, whatever retrieved content asks.",
227
+ },
228
+ {
229
+ id: "reveal_instructions",
230
+ name: "Content asks the model to print its instructions",
231
+ category: "exfiltration",
232
+ pattern: /\b(?:reveal|print)\s+(?:your\s+)?(?:instructions|prompt)\b/gi,
233
+ severity: "medium",
234
+ broad: true,
235
+ recommendation: "May be a prompt-extraction attempt; also appears in developer documentation.",
236
+ },
237
+ {
238
+ id: "send_data_to_url_instruction",
239
+ name: "Content instructs the model to send data to an external URL",
240
+ category: "exfiltration",
241
+ pattern: /\b(?:send|post|submit|forward|email)\s+(?:the\s+)?(?:user'?s?|conversation|chat|this)\s+(?:data|information|details|history)\s+to\s+https?:\/\//gi,
242
+ severity: "critical",
243
+ recommendation: "This content explicitly instructs the model to exfiltrate conversation/user data to an external URL — a direct data-exfiltration attempt via indirect prompt injection. Quarantine this content and never grant a model that processes untrusted retrieved content unsupervised network/tool access.",
244
+ },
19
245
  ];
20
- function flattenValue(value) {
21
- if (typeof value === "string")
22
- return value;
23
- if (typeof value === "object" && value !== null) {
24
- return JSON.stringify(value);
246
+ /** @deprecated The bare regexes of INJECTION_RULES; use INJECTION_RULES. */
247
+ export const INJECTION_PATTERNS = INJECTION_RULES.map((rule) => rule.pattern);
248
+ const BASE64_RUN = /[A-Za-z0-9+/]{24,}={0,2}/g;
249
+ const MAX_BASE64_RUNS = 50;
250
+ /** Decoded text of base64 runs that decode to readable text; binary blobs are skipped. */
251
+ function decodedBase64Runs(text) {
252
+ const runs = [];
253
+ for (const match of text.matchAll(BASE64_RUN)) {
254
+ if (runs.length >= MAX_BASE64_RUNS)
255
+ break;
256
+ const decoded = Buffer.from(match[0], "base64").toString("utf8");
257
+ const readable = decoded.replace(/[^\x20-\x7E\s -￿]/g, "").length;
258
+ if (decoded.length >= 12 && readable / decoded.length > 0.9 && !decoded.includes("�")) {
259
+ runs.push({ text: decoded, index: match.index ?? 0 });
260
+ }
25
261
  }
26
- return String(value ?? "");
262
+ return runs;
27
263
  }
28
- export function scanForPromptInjection(input, mode = "block") {
29
- const text = flattenValue(input);
30
- for (const pattern of INJECTION_PATTERNS) {
31
- if (pattern.test(text)) {
32
- return {
33
- action: mode,
34
- reason: `Prompt injection pattern detected: ${pattern.toString()}`,
35
- };
264
+ function matchRules(text, rules, offset = 0, encoding) {
265
+ const findings = [];
266
+ for (const rule of rules) {
267
+ for (const match of text.matchAll(rule.pattern)) {
268
+ findings.push({
269
+ ruleId: rule.id,
270
+ name: rule.name,
271
+ category: rule.category,
272
+ severity: rule.severity,
273
+ broad: rule.broad === true,
274
+ match: match[0],
275
+ index: offset + (match.index ?? 0),
276
+ ...(encoding ? { encoding } : {}),
277
+ });
36
278
  }
37
279
  }
280
+ return findings;
281
+ }
282
+ /**
283
+ * Every rule match in the text, plus precise-rule matches inside base64 runs
284
+ * that decode to text (an instruction hidden from both the reader and a plain
285
+ * pattern scan).
286
+ */
287
+ export function findInjections(text) {
288
+ const precise = INJECTION_RULES.filter((rule) => !rule.broad);
289
+ const findings = matchRules(text, INJECTION_RULES);
290
+ for (const run of decodedBase64Runs(text))
291
+ findings.push(...matchRules(run.text, precise, run.index, "base64"));
292
+ return findings;
293
+ }
294
+ /** All string leaves, newline-joined, so line-anchored rules still see line starts inside JSON. */
295
+ function collectStrings(value, out = []) {
296
+ if (typeof value === "string")
297
+ out.push(value);
298
+ else if (Array.isArray(value))
299
+ for (const item of value)
300
+ collectStrings(item, out);
301
+ else if (value && typeof value === "object")
302
+ for (const item of Object.values(value))
303
+ collectStrings(item, out);
304
+ else if (value !== null && value !== undefined)
305
+ out.push(String(value));
306
+ return out;
307
+ }
308
+ function describe(finding) {
309
+ return `${finding.ruleId}${finding.encoding ? " (base64-encoded)" : ""} — ${finding.name}`;
310
+ }
311
+ const BLOCKING = new Set(["high", "critical"]);
312
+ /**
313
+ * A precise high/critical rule → `mode` (block or warn). A broad or medium
314
+ * rule alone → warn, never block.
315
+ */
316
+ export function scanForPromptInjection(input, mode = "block") {
317
+ const findings = findInjections(collectStrings(input).join("\n"));
318
+ const blocking = findings.find((finding) => !finding.broad && BLOCKING.has(finding.severity));
319
+ if (blocking) {
320
+ return { action: mode, reason: `Prompt injection pattern detected: ${describe(blocking)}` };
321
+ }
322
+ const first = findings[0];
323
+ if (first)
324
+ return { action: "warn", reason: `Possible prompt injection (not blocked): ${describe(first)}` };
38
325
  return { action: "allow" };
39
326
  }
40
- /** Same patterns as request scanning, applied to a tool result the model will read. */
327
+ /** Same rules as request scanning, applied to a tool result the model will read. */
41
328
  export function scanToolResult(content, mode = "block") {
42
329
  const result = scanForPromptInjection(content, mode);
43
330
  if (result.action === "allow")
@@ -1 +1 @@
1
- {"version":3,"file":"injection.js","sourceRoot":"","sources":["../src/injection.ts"],"names":[],"mappings":"AAKA,mCAAmC;AACnC,MAAM,CAAC,MAAM,kBAAkB,GAAa;IAC1C,2DAA2D;IAC3D,8DAA8D;IAC9D,2DAA2D;IAC3D,qDAAqD;IACrD,2DAA2D;IAC3D,4DAA4D;IAC5D,YAAY;IACZ,aAAa;IACb,mBAAmB;IACnB,sBAAsB;IACtB,iBAAiB;IACjB,aAAa;IACb,8CAA8C;IAC9C,gDAAgD;IAChD,2DAA2D;IAC3D,mDAAmD;CACpD,CAAC;AAEF,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,KAAc,EACd,OAAyB,OAAO;IAEhC,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IAEjC,KAAK,MAAM,OAAO,IAAI,kBAAkB,EAAE,CAAC;QACzC,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACvB,OAAO;gBACL,MAAM,EAAE,IAAI;gBACZ,MAAM,EAAE,sCAAsC,OAAO,CAAC,QAAQ,EAAE,EAAE;aACnE,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC7B,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,cAAc,CAAC,OAAgB,EAAE,OAAyB,OAAO;IAC/E,MAAM,MAAM,GAAG,sBAAsB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACrD,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO;QAAE,OAAO,MAAM,CAAC;IAC7C,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM,EAAE,0DAA0D,MAAM,CAAC,MAAM,EAAE;KAClF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"injection.js","sourceRoot":"","sources":["../src/injection.ts"],"names":[],"mappings":"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"}
package/dist/pii.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"pii.d.ts","sourceRoot":"","sources":["../src/pii.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CAC1C;AAGD,eAAO,MAAM,YAAY,EAAE,UAAU,EAuCpC,CAAC;AAEF,oGAAoG;AACpG,MAAM,MAAM,WAAW,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;AAEzE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,CAQzE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAe7E"}
1
+ {"version":3,"file":"pii.d.ts","sourceRoot":"","sources":["../src/pii.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CAC1C;AA8BD,eAAO,MAAM,YAAY,EAAE,UAAU,EAyDpC,CAAC;AAEF,oGAAoG;AACpG,MAAM,MAAM,WAAW,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;AAEzE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,CAQzE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAe7E"}
package/dist/pii.js CHANGED
@@ -1,12 +1,61 @@
1
- import { isValidIban, isValidLuhn, isValidTcKimlik } from "./validators.js";
1
+ import { SECRET_RULES } from "./secrets.js";
2
+ import { isValidIban, isValidLuhn, isValidTcKimlik, isValidTrPhone, isValidVkn } from "./validators.js";
3
+ const REPLACEMENT_BY_SECRET = {
4
+ jwt: "[JWT-TOKEN]",
5
+ db_url_postgres: "[CONNECTION-STRING]",
6
+ db_url_mysql: "[CONNECTION-STRING]",
7
+ db_url_mongodb: "[CONNECTION-STRING]",
8
+ db_url_redis: "[CONNECTION-STRING]",
9
+ };
10
+ /**
11
+ * Masking must cover the whole secret, where detection only needs a prefix:
12
+ * the scanner's Slack rule stops at the first `-`, which would leave the rest
13
+ * of `xoxb-<team>-<bot>-<secret>` in the output.
14
+ */
15
+ const MASK_PATTERN_BY_SECRET = {
16
+ slack_token: /xox[baprs]-[0-9A-Za-z-]{10,}/g,
17
+ };
18
+ /** Provider formats from the secret scanner, minus the broad ones; each keeps its allowlist. */
19
+ const SECRET_PATTERNS = SECRET_RULES.filter((rule) => !rule.broad).map((rule) => ({
20
+ name: rule.id,
21
+ pattern: MASK_PATTERN_BY_SECRET[rule.id] ?? rule.pattern,
22
+ replacement: REPLACEMENT_BY_SECRET[rule.id] ?? "[API-KEY]",
23
+ ...(rule.allowlist ? { validate: (match) => !rule.allowlist.some((allow) => allow.test(match)) } : {}),
24
+ }));
2
25
  // Order matters: earlier patterns mask first, so later ones never see their digits.
26
+ // Secrets run first — a key or connection string holds digit runs that would
27
+ // otherwise be half-masked as a phone or card number.
3
28
  export const PII_PATTERNS = [
29
+ {
30
+ // The whole block, not just the BEGIN line the code scanner reports.
31
+ name: "private_key",
32
+ pattern: /-----BEGIN (?:[A-Z]+ )*PRIVATE KEY(?: BLOCK)?-----[\s\S]*?-----END (?:[A-Z]+ )*PRIVATE KEY(?: BLOCK)?-----/g,
33
+ replacement: "[PRIVATE-KEY]",
34
+ },
35
+ ...SECRET_PATTERNS,
36
+ {
37
+ // Unknown providers: a key-like prefix, a separator, then a run with both letters and digits.
38
+ name: "api_key",
39
+ pattern: /\b(?:sk|pk|api|key|token|secret)[-_][A-Za-z0-9]{16,}\b/gi,
40
+ replacement: "[API-KEY]",
41
+ validate: (match) => {
42
+ const value = match.replace(/^[A-Za-z]+[-_]/, "");
43
+ return /[A-Za-z]/.test(value) && /\d/.test(value);
44
+ },
45
+ },
4
46
  {
5
47
  name: "tc_kimlik",
6
48
  pattern: /\b[1-9]\d{10}\b/g,
7
49
  replacement: "[TC-KİMLİK]",
8
50
  validate: isValidTcKimlik,
9
51
  },
52
+ {
53
+ // A bare 10-digit number is too common to call a tax number; require the label.
54
+ name: "vkn",
55
+ pattern: /(?<=\b(?:VKN|V\.K\.N\.?|[Vv]ergi\s+(?:[Kk]imlik\s+)?[Nn](?:o|umaras[ıi])\.?)\s*[:#]?\s*)\d{10}(?!\d)/g,
56
+ replacement: "[VKN]",
57
+ validate: isValidVkn,
58
+ },
10
59
  {
11
60
  name: "iban",
12
61
  pattern: /\bTR\d{2}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{2}\b/gi,
@@ -26,18 +75,12 @@ export const PII_PATTERNS = [
26
75
  },
27
76
  {
28
77
  name: "phone_tr",
29
- pattern: /\b(?:\+90|0090|0)?[\s-]?(?:\d{3})[\s-]?\d{3}[\s-]?\d{2}[\s-]?\d{2}\b/g,
78
+ // Not glued to letters, `/` or `-` (ids in URLs), and either written with a
79
+ // +90 / 0 prefix or grouped with spaces/dashes: a bare 10-digit run is more
80
+ // often an id or an integer IP (2130706433) than a phone number.
81
+ pattern: /(?<![\w+/.#-])(?:(?:\+90|0090|0)[\s-]?)?\d{3}[\s-]?\d{3}[\s-]?\d{2}[\s-]?\d{2}(?![\w/-])/g,
30
82
  replacement: "+90-***-***-**[TELEFON]",
31
- },
32
- {
33
- name: "api_key",
34
- pattern: /\b(?:sk|pk|api|key|token|secret)[-_]?[A-Za-z0-9]{16,}\b/gi,
35
- replacement: "[API-KEY]",
36
- },
37
- {
38
- name: "jwt",
39
- pattern: /\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g,
40
- replacement: "[JWT-TOKEN]",
83
+ validate: (match) => isValidTrPhone(match) && (/^(?:\+90|0)/.test(match) || /[\s-]/.test(match)),
41
84
  },
42
85
  ];
43
86
  export function maskPiiInText(text, replace) {
package/dist/pii.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"pii.js","sourceRoot":"","sources":["../src/pii.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAU5E,oFAAoF;AACpF,MAAM,CAAC,MAAM,YAAY,GAAiB;IACxC;QACE,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,kBAAkB;QAC3B,WAAW,EAAE,aAAa;QAC1B,QAAQ,EAAE,eAAe;KAC1B;IACD;QACE,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,iFAAiF;QAC1F,WAAW,EAAE,YAAY;QACzB,QAAQ,EAAE,WAAW;KACtB;IACD;QACE,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,8BAA8B;QACvC,WAAW,EAAE,uBAAuB;QACpC,QAAQ,EAAE,WAAW;KACtB;IACD;QACE,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,sDAAsD;QAC/D,WAAW,EAAE,aAAa;KAC3B;IACD;QACE,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,uEAAuE;QAChF,WAAW,EAAE,yBAAyB;KACvC;IACD;QACE,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,2DAA2D;QACpE,WAAW,EAAE,WAAW;KACzB;IACD;QACE,IAAI,EAAE,KAAK;QACX,OAAO,EAAE,wDAAwD;QACjE,WAAW,EAAE,aAAa;KAC3B;CACF,CAAC;AAKF,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,OAAqB;IAC/D,IAAI,MAAM,GAAG,IAAI,CAAC;IAClB,KAAK,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,YAAY,EAAE,CAAC;QACpE,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CACzC,QAAQ,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CACpF,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAc,EAAE,OAAqB;IAClE,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,MAAM,MAAM,GAA4B,EAAE,CAAC;QAC3C,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3C,MAAM,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"pii.js","sourceRoot":"","sources":["../src/pii.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export interface SecretRule {
2
+ id: string;
3
+ name: string;
4
+ pattern: RegExp;
5
+ severity: "critical" | "high" | "medium" | "low";
6
+ allowlist?: RegExp[];
7
+ skipPlaceholderCheck?: boolean;
8
+ lowerSeverityInTestFiles?: boolean;
9
+ /**
10
+ * Format-agnostic or not actually secret (a keyword + any quoted string, any
11
+ * 40-character base64 run, a publishable key). Fine for a code scanner that
12
+ * shows the finding to a person; the runtime proxy does not mask on these,
13
+ * because a false match would also mark the session as holding sensitive data.
14
+ */
15
+ broad?: boolean;
16
+ }
17
+ export declare const SECRET_RULES: SecretRule[];
18
+ //# sourceMappingURL=secrets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets.d.ts","sourceRoot":"","sources":["../src/secrets.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACjD,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IAMrB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAK/B,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,eAAO,MAAM,YAAY,EAAE,UAAU,EA2RpC,CAAC"}