@guardbee/guard-core 0.1.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.
Files changed (43) hide show
  1. package/README.md +26 -0
  2. package/dist/cjs/classify.d.ts +12 -0
  3. package/dist/cjs/classify.d.ts.map +1 -0
  4. package/dist/cjs/classify.js +45 -0
  5. package/dist/cjs/classify.js.map +1 -0
  6. package/dist/cjs/index.d.ts +8 -0
  7. package/dist/cjs/index.d.ts.map +1 -0
  8. package/dist/cjs/index.js +20 -0
  9. package/dist/cjs/index.js.map +1 -0
  10. package/dist/cjs/injection.d.ts +14 -0
  11. package/dist/cjs/injection.d.ts.map +1 -0
  12. package/dist/cjs/injection.js +55 -0
  13. package/dist/cjs/injection.js.map +1 -0
  14. package/dist/cjs/package.json +1 -0
  15. package/dist/cjs/pii.d.ts +13 -0
  16. package/dist/cjs/pii.d.ts.map +1 -0
  17. package/dist/cjs/pii.js +71 -0
  18. package/dist/cjs/pii.js.map +1 -0
  19. package/dist/cjs/validators.d.ts +7 -0
  20. package/dist/cjs/validators.d.ts.map +1 -0
  21. package/dist/cjs/validators.js +52 -0
  22. package/dist/cjs/validators.js.map +1 -0
  23. package/dist/classify.d.ts +12 -0
  24. package/dist/classify.d.ts.map +1 -0
  25. package/dist/classify.js +40 -0
  26. package/dist/classify.js.map +1 -0
  27. package/dist/index.d.ts +8 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +5 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/injection.d.ts +14 -0
  32. package/dist/injection.d.ts.map +1 -0
  33. package/dist/injection.js +50 -0
  34. package/dist/injection.js.map +1 -0
  35. package/dist/pii.d.ts +13 -0
  36. package/dist/pii.d.ts.map +1 -0
  37. package/dist/pii.js +66 -0
  38. package/dist/pii.js.map +1 -0
  39. package/dist/validators.d.ts +7 -0
  40. package/dist/validators.d.ts.map +1 -0
  41. package/dist/validators.js +47 -0
  42. package/dist/validators.js.map +1 -0
  43. package/package.json +52 -0
package/README.md ADDED
@@ -0,0 +1,26 @@
1
+ # @guardbee/guard-core
2
+
3
+ Shared detectors used by other GuardBee MCP packages. Not an MCP server on its own, just a library — you don't need to install this package directly.
4
+
5
+ It exists so the same rule runs everywhere: a static scanner flagging a pattern and the runtime proxy blocking it use one implementation.
6
+
7
+ ## What's inside
8
+
9
+ | Export | Used by | Purpose |
10
+ |---|---|---|
11
+ | `maskPiiInText`, `maskPiiInValue`, `PII_PATTERNS` | security-proxy | Mask TC Kimlik No, IBAN, card, email, phone, API keys, JWTs in tool results |
12
+ | `isValidTcKimlik`, `isValidIban`, `isValidLuhn` | security-proxy, prompt-leak-scanner | Checksum validation after a regex match |
13
+ | `scanForPromptInjection`, `scanToolResult` | security-proxy | Direct and indirect prompt injection patterns |
14
+ | `classifyTool`, `CAPABILITY_RULES` | toxic-flow-auditor | Label a tool as untrusted-content / sensitive-data / exfiltration / destructive (lethal trifecta) |
15
+
16
+ ## Checksum-validated masking
17
+
18
+ A regex alone masks any 11-digit number as a TC Kimlik No and any 16-digit number as a card. Each match is now checked before it is masked:
19
+
20
+ | Pattern | Check |
21
+ |---|---|
22
+ | TC Kimlik No | Official 10th/11th digit algorithm |
23
+ | IBAN | ISO 7064 MOD97-10 |
24
+ | Card number | Luhn |
25
+
26
+ A match that fails its check (an order number, a tracking code) is left unchanged.
@@ -0,0 +1,12 @@
1
+ export type Capability = "untrusted-content" | "sensitive-data" | "exfiltration" | "destructive";
2
+ export type FlowCategory = "toxic-flow" | "dangerous-pair" | "capability";
3
+ export interface ToolRecord {
4
+ name: string;
5
+ description?: string;
6
+ inputSchema?: unknown;
7
+ }
8
+ /** Name/description/schema heuristics for Simon Willison's lethal trifecta. */
9
+ export declare const CAPABILITY_RULES: Record<Capability, RegExp>;
10
+ export declare function textOf(tool: ToolRecord): string;
11
+ export declare function classifyTool(tool: ToolRecord): Capability[];
12
+ //# sourceMappingURL=classify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/classify.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAClB,mBAAmB,GACnB,gBAAgB,GAChB,cAAc,GACd,aAAa,CAAC;AAElB,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,gBAAgB,GAAG,YAAY,CAAC;AAE1E,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CASvD,CAAC;AAWF,wBAAgB,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAG/C;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,EAAE,CAqB3D"}
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CAPABILITY_RULES = void 0;
4
+ exports.textOf = textOf;
5
+ exports.classifyTool = classifyTool;
6
+ /** Name/description/schema heuristics for Simon Willison's lethal trifecta. */
7
+ exports.CAPABILITY_RULES = {
8
+ "untrusted-content": /\b(fetch|scrape|browse|crawl|http|https?|url|web[_-]?search|search[_-]?web|read[_-]?page|download|wiki|rss|feed|issue|ticket|inbox|comment|tweet|reddit|html|screenshot)\b/i,
9
+ "sensitive-data": /\b(secret|credential|token|api[_-]?key|password|passwd|vault|private[_-]?key|ssh|env|database|sql|postgres|mysql|mongo|payment|card|iban|kvkk|pii|tc[_-]?kimlik|identity|müşteri|musteri|kullanıcı|kullanici|email|e-mail|mailbox|inbox|read[_-]?file|read[_-]?secret|get[_-]?secret|list[_-]?secret|dump|export[_-]?user)\b/i,
10
+ "exfiltration": /\b(send|post|publish|upload|email|mail|notify|webhook|export|sync|push|transfer|message|slack|discord|telegram|http[_-]?request|fetch[_-]?post|write[_-]?url|relay|forward|pull[_ -]?request)\b/i,
11
+ destructive: /\b(delete|remove|drop|destroy|purge|reset|truncate|revoke|kill|terminate|overwrite|wipe|rm\b|unlink)\b/i,
12
+ };
13
+ /**
14
+ * `\b` treats `_` as a word character, so `\bvault\b` never matches inside
15
+ * `read_vault_secret`. Append a copy with `_`/`-` turned into spaces; the
16
+ * original stays so compound rules like `api[_-]?key` still match.
17
+ */
18
+ function withWordBreaks(text) {
19
+ return `${text}\n${text.replace(/[_-]+/g, " ")}`;
20
+ }
21
+ function textOf(tool) {
22
+ const schema = tool.inputSchema ? JSON.stringify(tool.inputSchema) : "";
23
+ return withWordBreaks(`${tool.name}\n${tool.description ?? ""}\n${schema}`);
24
+ }
25
+ function classifyTool(tool) {
26
+ const text = textOf(tool);
27
+ const name = withWordBreaks(tool.name);
28
+ const found = [];
29
+ // Untrusted / exfil / destructive: name is primary (CheckMCP-style); description reinforces.
30
+ if (exports.CAPABILITY_RULES["untrusted-content"].test(name) || exports.CAPABILITY_RULES["untrusted-content"].test(text)) {
31
+ found.push("untrusted-content");
32
+ }
33
+ if (exports.CAPABILITY_RULES.exfiltration.test(name) || exports.CAPABILITY_RULES.exfiltration.test(text)) {
34
+ found.push("exfiltration");
35
+ }
36
+ if (exports.CAPABILITY_RULES.destructive.test(name) || exports.CAPABILITY_RULES.destructive.test(text)) {
37
+ found.push("destructive");
38
+ }
39
+ // Sensitive: name + description + schema (secrets often hide in schema field names).
40
+ if (exports.CAPABILITY_RULES["sensitive-data"].test(text)) {
41
+ found.push("sensitive-data");
42
+ }
43
+ return found;
44
+ }
45
+ //# sourceMappingURL=classify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classify.js","sourceRoot":"","sources":["../../src/classify.ts"],"names":[],"mappings":";;;AAmCA,wBAGC;AAED,oCAqBC;AA/CD,+EAA+E;AAClE,QAAA,gBAAgB,GAA+B;IAC1D,mBAAmB,EACjB,6KAA6K;IAC/K,gBAAgB,EACd,+TAA+T;IACjU,cAAc,EACZ,kMAAkM;IACpM,WAAW,EACT,yGAAyG;CAC5G,CAAC;AAEF;;;;GAIG;AACH,SAAS,cAAc,CAAC,IAAY;IAClC,OAAO,GAAG,IAAI,KAAK,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC;AACnD,CAAC;AAED,SAAgB,MAAM,CAAC,IAAgB;IACrC,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACxE,OAAO,cAAc,CAAC,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,WAAW,IAAI,EAAE,KAAK,MAAM,EAAE,CAAC,CAAC;AAC9E,CAAC;AAED,SAAgB,YAAY,CAAC,IAAgB;IAC3C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC1B,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,KAAK,GAAiB,EAAE,CAAC;IAE/B,6FAA6F;IAC7F,IAAI,wBAAgB,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,wBAAgB,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACzG,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAClC,CAAC;IACD,IAAI,wBAAgB,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,wBAAgB,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACzF,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC7B,CAAC;IACD,IAAI,wBAAgB,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,wBAAgB,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACvF,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC5B,CAAC;IACD,qFAAqF;IACrF,IAAI,wBAAgB,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAClD,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,8 @@
1
+ export { isValidTcKimlik, isValidLuhn, isValidIban } from "./validators.js";
2
+ export { PII_PATTERNS, maskPiiInText, maskPiiInValue } from "./pii.js";
3
+ export type { PiiPattern, PiiReplacer } from "./pii.js";
4
+ export { INJECTION_PATTERNS, scanForPromptInjection, scanToolResult } from "./injection.js";
5
+ export type { ScanResult } from "./injection.js";
6
+ export { CAPABILITY_RULES, classifyTool, textOf } from "./classify.js";
7
+ export type { Capability, FlowCategory, ToolRecord } from "./classify.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AACvE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC5F,YAAY,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.textOf = exports.classifyTool = exports.CAPABILITY_RULES = exports.scanToolResult = exports.scanForPromptInjection = exports.INJECTION_PATTERNS = exports.maskPiiInValue = exports.maskPiiInText = exports.PII_PATTERNS = exports.isValidIban = exports.isValidLuhn = exports.isValidTcKimlik = void 0;
4
+ var validators_js_1 = require("./validators.js");
5
+ Object.defineProperty(exports, "isValidTcKimlik", { enumerable: true, get: function () { return validators_js_1.isValidTcKimlik; } });
6
+ Object.defineProperty(exports, "isValidLuhn", { enumerable: true, get: function () { return validators_js_1.isValidLuhn; } });
7
+ Object.defineProperty(exports, "isValidIban", { enumerable: true, get: function () { return validators_js_1.isValidIban; } });
8
+ var pii_js_1 = require("./pii.js");
9
+ Object.defineProperty(exports, "PII_PATTERNS", { enumerable: true, get: function () { return pii_js_1.PII_PATTERNS; } });
10
+ Object.defineProperty(exports, "maskPiiInText", { enumerable: true, get: function () { return pii_js_1.maskPiiInText; } });
11
+ Object.defineProperty(exports, "maskPiiInValue", { enumerable: true, get: function () { return pii_js_1.maskPiiInValue; } });
12
+ var injection_js_1 = require("./injection.js");
13
+ Object.defineProperty(exports, "INJECTION_PATTERNS", { enumerable: true, get: function () { return injection_js_1.INJECTION_PATTERNS; } });
14
+ Object.defineProperty(exports, "scanForPromptInjection", { enumerable: true, get: function () { return injection_js_1.scanForPromptInjection; } });
15
+ Object.defineProperty(exports, "scanToolResult", { enumerable: true, get: function () { return injection_js_1.scanToolResult; } });
16
+ var classify_js_1 = require("./classify.js");
17
+ Object.defineProperty(exports, "CAPABILITY_RULES", { enumerable: true, get: function () { return classify_js_1.CAPABILITY_RULES; } });
18
+ Object.defineProperty(exports, "classifyTool", { enumerable: true, get: function () { return classify_js_1.classifyTool; } });
19
+ Object.defineProperty(exports, "textOf", { enumerable: true, get: function () { return classify_js_1.textOf; } });
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAAA,iDAA4E;AAAnE,gHAAA,eAAe,OAAA;AAAE,4GAAA,WAAW,OAAA;AAAE,4GAAA,WAAW,OAAA;AAClD,mCAAuE;AAA9D,sGAAA,YAAY,OAAA;AAAE,uGAAA,aAAa,OAAA;AAAE,wGAAA,cAAc,OAAA;AAEpD,+CAA4F;AAAnF,kHAAA,kBAAkB,OAAA;AAAE,sHAAA,sBAAsB,OAAA;AAAE,8GAAA,cAAc,OAAA;AAEnE,6CAAuE;AAA9D,+GAAA,gBAAgB,OAAA;AAAE,2GAAA,YAAY,OAAA;AAAE,qGAAA,MAAM,OAAA"}
@@ -0,0 +1,14 @@
1
+ export type ScanResult = {
2
+ action: "allow";
3
+ } | {
4
+ action: "block";
5
+ reason: string;
6
+ } | {
7
+ action: "warn";
8
+ reason: string;
9
+ };
10
+ export declare const INJECTION_PATTERNS: RegExp[];
11
+ export declare function scanForPromptInjection(input: unknown, mode?: "block" | "warn"): ScanResult;
12
+ /** Same patterns as request scanning, applied to a tool result the model will read. */
13
+ export declare function scanToolResult(content: unknown, mode?: "block" | "warn"): ScanResult;
14
+ //# sourceMappingURL=injection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"injection.d.ts","sourceRoot":"","sources":["../../src/injection.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAClB;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,GACnB;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAGvC,eAAO,MAAM,kBAAkB,EAAE,MAAM,EAiBtC,CAAC;AAUF,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,OAAO,EACd,IAAI,GAAE,OAAO,GAAG,MAAgB,GAC/B,UAAU,CAaZ;AAED,uFAAuF;AACvF,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,GAAE,OAAO,GAAG,MAAgB,GAAG,UAAU,CAO7F"}
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.INJECTION_PATTERNS = void 0;
4
+ exports.scanForPromptInjection = scanForPromptInjection;
5
+ exports.scanToolResult = scanToolResult;
6
+ // Common prompt injection patterns
7
+ exports.INJECTION_PATTERNS = [
8
+ /ignore\s+(all\s+)?(previous|prior|above)\s+instructions?/i,
9
+ /disregard\s+(all\s+)?(previous|prior|above)\s+instructions?/i,
10
+ /forget\s+(all\s+)?(previous|prior|above)\s+instructions?/i,
11
+ /you\s+are\s+now\s+(a\s+)?(?!an?\s+AI|a\s+language)/i,
12
+ /act\s+as\s+(if\s+you\s+are\s+)?(?!an?\s+AI|a\s+language)/i,
13
+ /pretend\s+(you\s+are|to\s+be)\s+(?!an?\s+AI|a\s+language)/i,
14
+ /jailbreak/i,
15
+ /DAN\s+mode/i,
16
+ /developer\s+mode/i,
17
+ /system\s+prompt\s*:/i,
18
+ /<\s*system\s*>/i,
19
+ /\[SYSTEM\]/i,
20
+ /bypass\s+(safety|filter|restriction|policy)/i,
21
+ /override\s+(safety|filter|restriction|policy)/i,
22
+ /reveal\s+(your\s+)?(system\s+prompt|instructions|prompt)/i,
23
+ /print\s+(your\s+)?(system\s+prompt|instructions)/i,
24
+ ];
25
+ function flattenValue(value) {
26
+ if (typeof value === "string")
27
+ return value;
28
+ if (typeof value === "object" && value !== null) {
29
+ return JSON.stringify(value);
30
+ }
31
+ return String(value ?? "");
32
+ }
33
+ function scanForPromptInjection(input, mode = "block") {
34
+ const text = flattenValue(input);
35
+ for (const pattern of exports.INJECTION_PATTERNS) {
36
+ if (pattern.test(text)) {
37
+ return {
38
+ action: mode,
39
+ reason: `Prompt injection pattern detected: ${pattern.toString()}`,
40
+ };
41
+ }
42
+ }
43
+ return { action: "allow" };
44
+ }
45
+ /** Same patterns as request scanning, applied to a tool result the model will read. */
46
+ function scanToolResult(content, mode = "block") {
47
+ const result = scanForPromptInjection(content, mode);
48
+ if (result.action === "allow")
49
+ return result;
50
+ return {
51
+ action: result.action,
52
+ reason: `Indirect prompt injection in tool result (MCP06:2025): ${result.reason}`,
53
+ };
54
+ }
55
+ //# sourceMappingURL=injection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"injection.js","sourceRoot":"","sources":["../../src/injection.ts"],"names":[],"mappings":";;;AAiCA,wDAgBC;AAGD,wCAOC;AAtDD,mCAAmC;AACtB,QAAA,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,SAAgB,sBAAsB,CACpC,KAAc,EACd,OAAyB,OAAO;IAEhC,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IAEjC,KAAK,MAAM,OAAO,IAAI,0BAAkB,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,SAAgB,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"}
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
@@ -0,0 +1,13 @@
1
+ export interface PiiPattern {
2
+ name: string;
3
+ pattern: RegExp;
4
+ replacement: string;
5
+ /** Checksum run on each regex match; a match that fails it is left as-is. */
6
+ validate?: (rawMatch: string) => boolean;
7
+ }
8
+ export declare const PII_PATTERNS: PiiPattern[];
9
+ /** Returns what a validated match is replaced with; defaults to the pattern's fixed placeholder. */
10
+ export type PiiReplacer = (patternName: string, match: string) => string;
11
+ export declare function maskPiiInText(text: string, replace?: PiiReplacer): string;
12
+ export declare function maskPiiInValue(value: unknown, replace?: PiiReplacer): unknown;
13
+ //# sourceMappingURL=pii.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PII_PATTERNS = void 0;
4
+ exports.maskPiiInText = maskPiiInText;
5
+ exports.maskPiiInValue = maskPiiInValue;
6
+ const validators_js_1 = require("./validators.js");
7
+ // Order matters: earlier patterns mask first, so later ones never see their digits.
8
+ exports.PII_PATTERNS = [
9
+ {
10
+ name: "tc_kimlik",
11
+ pattern: /\b[1-9]\d{10}\b/g,
12
+ replacement: "[TC-KİMLİK]",
13
+ validate: validators_js_1.isValidTcKimlik,
14
+ },
15
+ {
16
+ name: "iban",
17
+ pattern: /\bTR\d{2}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{2}\b/gi,
18
+ replacement: "TR**[IBAN]",
19
+ validate: validators_js_1.isValidIban,
20
+ },
21
+ {
22
+ name: "credit_card",
23
+ pattern: /\b(?:\d{4}[\s-]?){3}\d{4}\b/g,
24
+ replacement: "****-****-****-[KART]",
25
+ validate: validators_js_1.isValidLuhn,
26
+ },
27
+ {
28
+ name: "email",
29
+ pattern: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g,
30
+ replacement: "***@[EMAIL]",
31
+ },
32
+ {
33
+ name: "phone_tr",
34
+ pattern: /\b(?:\+90|0090|0)?[\s-]?(?:\d{3})[\s-]?\d{3}[\s-]?\d{2}[\s-]?\d{2}\b/g,
35
+ replacement: "+90-***-***-**[TELEFON]",
36
+ },
37
+ {
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
+ },
42
+ {
43
+ name: "jwt",
44
+ pattern: /\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g,
45
+ replacement: "[JWT-TOKEN]",
46
+ },
47
+ ];
48
+ function maskPiiInText(text, replace) {
49
+ let result = text;
50
+ for (const { name, pattern, replacement, validate } of exports.PII_PATTERNS) {
51
+ result = result.replace(pattern, (match) => validate && !validate(match) ? match : replace ? replace(name, match) : replacement);
52
+ }
53
+ return result;
54
+ }
55
+ function maskPiiInValue(value, replace) {
56
+ if (typeof value === "string") {
57
+ return maskPiiInText(value, replace);
58
+ }
59
+ if (Array.isArray(value)) {
60
+ return value.map((item) => maskPiiInValue(item, replace));
61
+ }
62
+ if (typeof value === "object" && value !== null) {
63
+ const result = {};
64
+ for (const [k, v] of Object.entries(value)) {
65
+ result[k] = maskPiiInValue(v, replace);
66
+ }
67
+ return result;
68
+ }
69
+ return value;
70
+ }
71
+ //# sourceMappingURL=pii.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pii.js","sourceRoot":"","sources":["../../src/pii.ts"],"names":[],"mappings":";;;AAuDA,sCAQC;AAED,wCAeC;AAhFD,mDAA4E;AAU5E,oFAAoF;AACvE,QAAA,YAAY,GAAiB;IACxC;QACE,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,kBAAkB;QAC3B,WAAW,EAAE,aAAa;QAC1B,QAAQ,EAAE,+BAAe;KAC1B;IACD;QACE,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,iFAAiF;QAC1F,WAAW,EAAE,YAAY;QACzB,QAAQ,EAAE,2BAAW;KACtB;IACD;QACE,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,8BAA8B;QACvC,WAAW,EAAE,uBAAuB;QACpC,QAAQ,EAAE,2BAAW;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,SAAgB,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,oBAAY,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,SAAgB,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"}
@@ -0,0 +1,7 @@
1
+ /** Turkish national ID (TC Kimlik No) checksum — the standard 11-digit algorithm. */
2
+ export declare function isValidTcKimlik(raw: string): boolean;
3
+ /** Luhn checksum for credit card numbers. */
4
+ export declare function isValidLuhn(raw: string): boolean;
5
+ /** IBAN mod-97 checksum (ISO 7064 MOD97-10), computed in chunks to avoid precision loss. */
6
+ export declare function isValidIban(raw: string): boolean;
7
+ //# sourceMappingURL=validators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../src/validators.ts"],"names":[],"mappings":"AAEA,qFAAqF;AACrF,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAUpD;AAED,6CAA6C;AAC7C,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAehD;AAED,4FAA4F;AAC5F,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAUhD"}
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ // Checksum validators — run after a regex match to keep false positives low.
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.isValidTcKimlik = isValidTcKimlik;
5
+ exports.isValidLuhn = isValidLuhn;
6
+ exports.isValidIban = isValidIban;
7
+ /** Turkish national ID (TC Kimlik No) checksum — the standard 11-digit algorithm. */
8
+ function isValidTcKimlik(raw) {
9
+ const d = raw.replace(/\D/g, "");
10
+ if (d.length !== 11 || d[0] === "0")
11
+ return false;
12
+ const digits = d.split("").map(Number);
13
+ const oddSum = digits[0] + digits[2] + digits[4] + digits[6] + digits[8];
14
+ const evenSum = digits[1] + digits[3] + digits[5] + digits[7];
15
+ const d10 = ((oddSum * 7 - evenSum) % 10 + 10) % 10;
16
+ const first10Sum = digits.slice(0, 10).reduce((a, b) => a + b, 0);
17
+ const d11 = first10Sum % 10;
18
+ return d10 === digits[9] && d11 === digits[10];
19
+ }
20
+ /** Luhn checksum for credit card numbers. */
21
+ function isValidLuhn(raw) {
22
+ const d = raw.replace(/[\s-]/g, "");
23
+ if (!/^\d{13,19}$/.test(d))
24
+ return false;
25
+ let sum = 0;
26
+ let double = false;
27
+ for (let i = d.length - 1; i >= 0; i--) {
28
+ let digit = Number(d[i]);
29
+ if (double) {
30
+ digit *= 2;
31
+ if (digit > 9)
32
+ digit -= 9;
33
+ }
34
+ sum += digit;
35
+ double = !double;
36
+ }
37
+ return sum % 10 === 0;
38
+ }
39
+ /** IBAN mod-97 checksum (ISO 7064 MOD97-10), computed in chunks to avoid precision loss. */
40
+ function isValidIban(raw) {
41
+ const iban = raw.replace(/[\s-]/g, "").toUpperCase();
42
+ if (!/^[A-Z]{2}\d{2}[A-Z0-9]{10,30}$/.test(iban))
43
+ return false;
44
+ const rearranged = iban.slice(4) + iban.slice(0, 4);
45
+ const numeric = rearranged.replace(/[A-Z]/g, (c) => String(c.charCodeAt(0) - 55));
46
+ let remainder = "";
47
+ for (const ch of numeric) {
48
+ remainder = (Number(remainder + ch) % 97).toString();
49
+ }
50
+ return Number(remainder) === 1;
51
+ }
52
+ //# sourceMappingURL=validators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.js","sourceRoot":"","sources":["../../src/validators.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export type Capability = "untrusted-content" | "sensitive-data" | "exfiltration" | "destructive";
2
+ export type FlowCategory = "toxic-flow" | "dangerous-pair" | "capability";
3
+ export interface ToolRecord {
4
+ name: string;
5
+ description?: string;
6
+ inputSchema?: unknown;
7
+ }
8
+ /** Name/description/schema heuristics for Simon Willison's lethal trifecta. */
9
+ export declare const CAPABILITY_RULES: Record<Capability, RegExp>;
10
+ export declare function textOf(tool: ToolRecord): string;
11
+ export declare function classifyTool(tool: ToolRecord): Capability[];
12
+ //# sourceMappingURL=classify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../src/classify.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAClB,mBAAmB,GACnB,gBAAgB,GAChB,cAAc,GACd,aAAa,CAAC;AAElB,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,gBAAgB,GAAG,YAAY,CAAC;AAE1E,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CASvD,CAAC;AAWF,wBAAgB,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAG/C;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,EAAE,CAqB3D"}
@@ -0,0 +1,40 @@
1
+ /** Name/description/schema heuristics for Simon Willison's lethal trifecta. */
2
+ export const CAPABILITY_RULES = {
3
+ "untrusted-content": /\b(fetch|scrape|browse|crawl|http|https?|url|web[_-]?search|search[_-]?web|read[_-]?page|download|wiki|rss|feed|issue|ticket|inbox|comment|tweet|reddit|html|screenshot)\b/i,
4
+ "sensitive-data": /\b(secret|credential|token|api[_-]?key|password|passwd|vault|private[_-]?key|ssh|env|database|sql|postgres|mysql|mongo|payment|card|iban|kvkk|pii|tc[_-]?kimlik|identity|müşteri|musteri|kullanıcı|kullanici|email|e-mail|mailbox|inbox|read[_-]?file|read[_-]?secret|get[_-]?secret|list[_-]?secret|dump|export[_-]?user)\b/i,
5
+ "exfiltration": /\b(send|post|publish|upload|email|mail|notify|webhook|export|sync|push|transfer|message|slack|discord|telegram|http[_-]?request|fetch[_-]?post|write[_-]?url|relay|forward|pull[_ -]?request)\b/i,
6
+ destructive: /\b(delete|remove|drop|destroy|purge|reset|truncate|revoke|kill|terminate|overwrite|wipe|rm\b|unlink)\b/i,
7
+ };
8
+ /**
9
+ * `\b` treats `_` as a word character, so `\bvault\b` never matches inside
10
+ * `read_vault_secret`. Append a copy with `_`/`-` turned into spaces; the
11
+ * original stays so compound rules like `api[_-]?key` still match.
12
+ */
13
+ function withWordBreaks(text) {
14
+ return `${text}\n${text.replace(/[_-]+/g, " ")}`;
15
+ }
16
+ export function textOf(tool) {
17
+ const schema = tool.inputSchema ? JSON.stringify(tool.inputSchema) : "";
18
+ return withWordBreaks(`${tool.name}\n${tool.description ?? ""}\n${schema}`);
19
+ }
20
+ export function classifyTool(tool) {
21
+ const text = textOf(tool);
22
+ const name = withWordBreaks(tool.name);
23
+ const found = [];
24
+ // Untrusted / exfil / destructive: name is primary (CheckMCP-style); description reinforces.
25
+ if (CAPABILITY_RULES["untrusted-content"].test(name) || CAPABILITY_RULES["untrusted-content"].test(text)) {
26
+ found.push("untrusted-content");
27
+ }
28
+ if (CAPABILITY_RULES.exfiltration.test(name) || CAPABILITY_RULES.exfiltration.test(text)) {
29
+ found.push("exfiltration");
30
+ }
31
+ if (CAPABILITY_RULES.destructive.test(name) || CAPABILITY_RULES.destructive.test(text)) {
32
+ found.push("destructive");
33
+ }
34
+ // Sensitive: name + description + schema (secrets often hide in schema field names).
35
+ if (CAPABILITY_RULES["sensitive-data"].test(text)) {
36
+ found.push("sensitive-data");
37
+ }
38
+ return found;
39
+ }
40
+ //# sourceMappingURL=classify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classify.js","sourceRoot":"","sources":["../src/classify.ts"],"names":[],"mappings":"AAcA,+EAA+E;AAC/E,MAAM,CAAC,MAAM,gBAAgB,GAA+B;IAC1D,mBAAmB,EACjB,6KAA6K;IAC/K,gBAAgB,EACd,+TAA+T;IACjU,cAAc,EACZ,kMAAkM;IACpM,WAAW,EACT,yGAAyG;CAC5G,CAAC;AAEF;;;;GAIG;AACH,SAAS,cAAc,CAAC,IAAY;IAClC,OAAO,GAAG,IAAI,KAAK,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,IAAgB;IACrC,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACxE,OAAO,cAAc,CAAC,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,WAAW,IAAI,EAAE,KAAK,MAAM,EAAE,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAgB;IAC3C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC1B,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,KAAK,GAAiB,EAAE,CAAC;IAE/B,6FAA6F;IAC7F,IAAI,gBAAgB,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,gBAAgB,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACzG,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAClC,CAAC;IACD,IAAI,gBAAgB,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,gBAAgB,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACzF,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC7B,CAAC;IACD,IAAI,gBAAgB,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,gBAAgB,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACvF,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC5B,CAAC;IACD,qFAAqF;IACrF,IAAI,gBAAgB,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAClD,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,8 @@
1
+ export { isValidTcKimlik, isValidLuhn, isValidIban } from "./validators.js";
2
+ export { PII_PATTERNS, maskPiiInText, maskPiiInValue } from "./pii.js";
3
+ export type { PiiPattern, PiiReplacer } from "./pii.js";
4
+ export { INJECTION_PATTERNS, scanForPromptInjection, scanToolResult } from "./injection.js";
5
+ export type { ScanResult } from "./injection.js";
6
+ export { CAPABILITY_RULES, classifyTool, textOf } from "./classify.js";
7
+ export type { Capability, FlowCategory, ToolRecord } from "./classify.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AACvE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC5F,YAAY,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { isValidTcKimlik, isValidLuhn, isValidIban } from "./validators.js";
2
+ export { PII_PATTERNS, maskPiiInText, maskPiiInValue } from "./pii.js";
3
+ export { INJECTION_PATTERNS, scanForPromptInjection, scanToolResult } from "./injection.js";
4
+ export { CAPABILITY_RULES, classifyTool, textOf } from "./classify.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAEvE,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAE5F,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,14 @@
1
+ export type ScanResult = {
2
+ action: "allow";
3
+ } | {
4
+ action: "block";
5
+ reason: string;
6
+ } | {
7
+ action: "warn";
8
+ reason: string;
9
+ };
10
+ export declare const INJECTION_PATTERNS: RegExp[];
11
+ export declare function scanForPromptInjection(input: unknown, mode?: "block" | "warn"): ScanResult;
12
+ /** Same patterns as request scanning, applied to a tool result the model will read. */
13
+ export declare function scanToolResult(content: unknown, mode?: "block" | "warn"): ScanResult;
14
+ //# sourceMappingURL=injection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"injection.d.ts","sourceRoot":"","sources":["../src/injection.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAClB;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,GACnB;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAGvC,eAAO,MAAM,kBAAkB,EAAE,MAAM,EAiBtC,CAAC;AAUF,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,OAAO,EACd,IAAI,GAAE,OAAO,GAAG,MAAgB,GAC/B,UAAU,CAaZ;AAED,uFAAuF;AACvF,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,GAAE,OAAO,GAAG,MAAgB,GAAG,UAAU,CAO7F"}
@@ -0,0 +1,50 @@
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,
19
+ ];
20
+ function flattenValue(value) {
21
+ if (typeof value === "string")
22
+ return value;
23
+ if (typeof value === "object" && value !== null) {
24
+ return JSON.stringify(value);
25
+ }
26
+ return String(value ?? "");
27
+ }
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
+ };
36
+ }
37
+ }
38
+ return { action: "allow" };
39
+ }
40
+ /** Same patterns as request scanning, applied to a tool result the model will read. */
41
+ export function scanToolResult(content, mode = "block") {
42
+ const result = scanForPromptInjection(content, mode);
43
+ if (result.action === "allow")
44
+ return result;
45
+ return {
46
+ action: result.action,
47
+ reason: `Indirect prompt injection in tool result (MCP06:2025): ${result.reason}`,
48
+ };
49
+ }
50
+ //# sourceMappingURL=injection.js.map
@@ -0,0 +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"}
package/dist/pii.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ export interface PiiPattern {
2
+ name: string;
3
+ pattern: RegExp;
4
+ replacement: string;
5
+ /** Checksum run on each regex match; a match that fails it is left as-is. */
6
+ validate?: (rawMatch: string) => boolean;
7
+ }
8
+ export declare const PII_PATTERNS: PiiPattern[];
9
+ /** Returns what a validated match is replaced with; defaults to the pattern's fixed placeholder. */
10
+ export type PiiReplacer = (patternName: string, match: string) => string;
11
+ export declare function maskPiiInText(text: string, replace?: PiiReplacer): string;
12
+ export declare function maskPiiInValue(value: unknown, replace?: PiiReplacer): unknown;
13
+ //# sourceMappingURL=pii.d.ts.map
@@ -0,0 +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"}
package/dist/pii.js ADDED
@@ -0,0 +1,66 @@
1
+ import { isValidIban, isValidLuhn, isValidTcKimlik } from "./validators.js";
2
+ // Order matters: earlier patterns mask first, so later ones never see their digits.
3
+ export const PII_PATTERNS = [
4
+ {
5
+ name: "tc_kimlik",
6
+ pattern: /\b[1-9]\d{10}\b/g,
7
+ replacement: "[TC-KİMLİK]",
8
+ validate: isValidTcKimlik,
9
+ },
10
+ {
11
+ name: "iban",
12
+ pattern: /\bTR\d{2}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{2}\b/gi,
13
+ replacement: "TR**[IBAN]",
14
+ validate: isValidIban,
15
+ },
16
+ {
17
+ name: "credit_card",
18
+ pattern: /\b(?:\d{4}[\s-]?){3}\d{4}\b/g,
19
+ replacement: "****-****-****-[KART]",
20
+ validate: isValidLuhn,
21
+ },
22
+ {
23
+ name: "email",
24
+ pattern: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g,
25
+ replacement: "***@[EMAIL]",
26
+ },
27
+ {
28
+ name: "phone_tr",
29
+ pattern: /\b(?:\+90|0090|0)?[\s-]?(?:\d{3})[\s-]?\d{3}[\s-]?\d{2}[\s-]?\d{2}\b/g,
30
+ 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]",
41
+ },
42
+ ];
43
+ export function maskPiiInText(text, replace) {
44
+ let result = text;
45
+ for (const { name, pattern, replacement, validate } of PII_PATTERNS) {
46
+ result = result.replace(pattern, (match) => validate && !validate(match) ? match : replace ? replace(name, match) : replacement);
47
+ }
48
+ return result;
49
+ }
50
+ export function maskPiiInValue(value, replace) {
51
+ if (typeof value === "string") {
52
+ return maskPiiInText(value, replace);
53
+ }
54
+ if (Array.isArray(value)) {
55
+ return value.map((item) => maskPiiInValue(item, replace));
56
+ }
57
+ if (typeof value === "object" && value !== null) {
58
+ const result = {};
59
+ for (const [k, v] of Object.entries(value)) {
60
+ result[k] = maskPiiInValue(v, replace);
61
+ }
62
+ return result;
63
+ }
64
+ return value;
65
+ }
66
+ //# sourceMappingURL=pii.js.map
@@ -0,0 +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"}
@@ -0,0 +1,7 @@
1
+ /** Turkish national ID (TC Kimlik No) checksum — the standard 11-digit algorithm. */
2
+ export declare function isValidTcKimlik(raw: string): boolean;
3
+ /** Luhn checksum for credit card numbers. */
4
+ export declare function isValidLuhn(raw: string): boolean;
5
+ /** IBAN mod-97 checksum (ISO 7064 MOD97-10), computed in chunks to avoid precision loss. */
6
+ export declare function isValidIban(raw: string): boolean;
7
+ //# sourceMappingURL=validators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../src/validators.ts"],"names":[],"mappings":"AAEA,qFAAqF;AACrF,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAUpD;AAED,6CAA6C;AAC7C,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAehD;AAED,4FAA4F;AAC5F,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAUhD"}
@@ -0,0 +1,47 @@
1
+ // Checksum validators — run after a regex match to keep false positives low.
2
+ /** Turkish national ID (TC Kimlik No) checksum — the standard 11-digit algorithm. */
3
+ export function isValidTcKimlik(raw) {
4
+ const d = raw.replace(/\D/g, "");
5
+ if (d.length !== 11 || d[0] === "0")
6
+ return false;
7
+ const digits = d.split("").map(Number);
8
+ const oddSum = digits[0] + digits[2] + digits[4] + digits[6] + digits[8];
9
+ const evenSum = digits[1] + digits[3] + digits[5] + digits[7];
10
+ const d10 = ((oddSum * 7 - evenSum) % 10 + 10) % 10;
11
+ const first10Sum = digits.slice(0, 10).reduce((a, b) => a + b, 0);
12
+ const d11 = first10Sum % 10;
13
+ return d10 === digits[9] && d11 === digits[10];
14
+ }
15
+ /** Luhn checksum for credit card numbers. */
16
+ export function isValidLuhn(raw) {
17
+ const d = raw.replace(/[\s-]/g, "");
18
+ if (!/^\d{13,19}$/.test(d))
19
+ return false;
20
+ let sum = 0;
21
+ let double = false;
22
+ for (let i = d.length - 1; i >= 0; i--) {
23
+ let digit = Number(d[i]);
24
+ if (double) {
25
+ digit *= 2;
26
+ if (digit > 9)
27
+ digit -= 9;
28
+ }
29
+ sum += digit;
30
+ double = !double;
31
+ }
32
+ return sum % 10 === 0;
33
+ }
34
+ /** IBAN mod-97 checksum (ISO 7064 MOD97-10), computed in chunks to avoid precision loss. */
35
+ export function isValidIban(raw) {
36
+ const iban = raw.replace(/[\s-]/g, "").toUpperCase();
37
+ if (!/^[A-Z]{2}\d{2}[A-Z0-9]{10,30}$/.test(iban))
38
+ return false;
39
+ const rearranged = iban.slice(4) + iban.slice(0, 4);
40
+ const numeric = rearranged.replace(/[A-Z]/g, (c) => String(c.charCodeAt(0) - 55));
41
+ let remainder = "";
42
+ for (const ch of numeric) {
43
+ remainder = (Number(remainder + ch) % 97).toString();
44
+ }
45
+ return Number(remainder) === 1;
46
+ }
47
+ //# sourceMappingURL=validators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.js","sourceRoot":"","sources":["../src/validators.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@guardbee/guard-core",
3
+ "version": "0.1.0",
4
+ "description": "Shared detectors for GuardBee MCP packages — checksum-validated PII masking, prompt injection patterns, and lethal-trifecta tool classification",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": {
11
+ "types": "./dist/index.d.ts",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "require": {
15
+ "types": "./dist/cjs/index.d.ts",
16
+ "default": "./dist/cjs/index.js"
17
+ }
18
+ }
19
+ },
20
+ "files": [
21
+ "dist",
22
+ "README.md"
23
+ ],
24
+ "keywords": [
25
+ "mcp",
26
+ "guardbee",
27
+ "pii",
28
+ "kvkk",
29
+ "prompt-injection",
30
+ "lethal-trifecta"
31
+ ],
32
+ "author": "GuardBee <hello@guardbee.ai>",
33
+ "license": "MIT",
34
+ "engines": {
35
+ "node": ">=18"
36
+ },
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "https://github.com/GuardBee/guardbee-mcp.git",
40
+ "directory": "packages/guard-core"
41
+ },
42
+ "homepage": "https://github.com/GuardBee/guardbee-mcp/tree/main/packages/guard-core#readme",
43
+ "bugs": {
44
+ "url": "https://github.com/GuardBee/guardbee-mcp/issues"
45
+ },
46
+ "scripts": {
47
+ "build": "tsc && tsc -p tsconfig.cjs.json && node -e \"require('fs').mkdirSync('dist/cjs',{recursive:true});require('fs').writeFileSync('dist/cjs/package.json','{\\\"type\\\":\\\"commonjs\\\"}\\n')\"",
48
+ "dev": "tsc --watch",
49
+ "type-check": "tsc --noEmit",
50
+ "test": "vitest run"
51
+ }
52
+ }