@guardbee/mcp-prompt-leak-scanner 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.
- package/README.md +146 -0
- package/TR.md +146 -0
- package/dist/__tests__/proxy.test.d.ts +2 -0
- package/dist/__tests__/proxy.test.d.ts.map +1 -0
- package/dist/__tests__/proxy.test.js +107 -0
- package/dist/__tests__/proxy.test.js.map +1 -0
- package/dist/__tests__/scanner.test.d.ts +2 -0
- package/dist/__tests__/scanner.test.d.ts.map +1 -0
- package/dist/__tests__/scanner.test.js +111 -0
- package/dist/__tests__/scanner.test.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +205 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +101 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/patterns.d.ts +13 -0
- package/dist/patterns.d.ts.map +1 -0
- package/dist/patterns.js +169 -0
- package/dist/patterns.js.map +1 -0
- package/dist/proxy.d.ts +34 -0
- package/dist/proxy.d.ts.map +1 -0
- package/dist/proxy.js +92 -0
- package/dist/proxy.js.map +1 -0
- package/dist/sarif.d.ts +3 -0
- package/dist/sarif.d.ts.map +1 -0
- package/dist/sarif.js +54 -0
- package/dist/sarif.js.map +1 -0
- package/dist/scanner.d.ts +44 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +237 -0
- package/dist/scanner.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +85 -0
- package/dist/server.js.map +1 -0
- package/package.json +50 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { startServer } from "./server.js";
|
|
3
|
+
import { scanFile, scanDirectory } from "./scanner.js";
|
|
4
|
+
import { buildSarif } from "./sarif.js";
|
|
5
|
+
import { loadConfig, configFilePath } from "./config.js";
|
|
6
|
+
import { startProxy } from "./proxy.js";
|
|
7
|
+
import { statSync, readFileSync } from "fs";
|
|
8
|
+
import { resolve, dirname } from "path";
|
|
9
|
+
import { fileURLToPath } from "url";
|
|
10
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
function getVersion() {
|
|
12
|
+
try {
|
|
13
|
+
const pkg = JSON.parse(readFileSync(resolve(__dirname, "../package.json"), "utf8"));
|
|
14
|
+
return pkg.version;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return "0.0.0";
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const SEV_ICON = { critical: "🔴", high: "🟠", medium: "🟡", low: "🔵" };
|
|
21
|
+
function printText(findings, scannedFiles, durationMs) {
|
|
22
|
+
if (findings.length === 0) {
|
|
23
|
+
console.log(`✅ No leaked credentials or PII found in ${scannedFiles} file(s) (${durationMs}ms)`);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const counts = {};
|
|
27
|
+
for (const f of findings)
|
|
28
|
+
counts[f.severity] = (counts[f.severity] ?? 0) + 1;
|
|
29
|
+
console.log(`⚠️ Found ${findings.length} finding(s) in ${scannedFiles} file(s) (${durationMs}ms)`);
|
|
30
|
+
console.log(` Critical: ${counts["critical"] ?? 0} High: ${counts["high"] ?? 0} Medium: ${counts["medium"] ?? 0} Low: ${counts["low"] ?? 0}`);
|
|
31
|
+
console.log("");
|
|
32
|
+
for (const f of findings) {
|
|
33
|
+
const icon = SEV_ICON[f.severity] ?? "⚪";
|
|
34
|
+
console.log(`${icon} [${f.severity.toUpperCase()}] ${f.patternName} (${f.category})`);
|
|
35
|
+
console.log(` Location : ${f.location}:${f.line}:${f.column}`);
|
|
36
|
+
console.log(` Value : ${f.maskedMatch} (masked)`);
|
|
37
|
+
console.log(` Recommendation : ${f.recommendation}`);
|
|
38
|
+
console.log("");
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function parseScanArgs(args) {
|
|
42
|
+
const positionals = [];
|
|
43
|
+
let failOn = "any";
|
|
44
|
+
let format = "text";
|
|
45
|
+
let maxFiles = 5000;
|
|
46
|
+
for (const arg of args) {
|
|
47
|
+
if (arg.startsWith("--fail-on="))
|
|
48
|
+
failOn = arg.split("=")[1] ?? "any";
|
|
49
|
+
else if (arg.startsWith("--format="))
|
|
50
|
+
format = arg.split("=")[1] ?? "text";
|
|
51
|
+
else if (arg.startsWith("--max-files="))
|
|
52
|
+
maxFiles = parseInt(arg.split("=")[1] ?? "5000", 10);
|
|
53
|
+
else if (!arg.startsWith("--"))
|
|
54
|
+
positionals.push(arg);
|
|
55
|
+
}
|
|
56
|
+
return { positionals, failOn, format, maxFiles };
|
|
57
|
+
}
|
|
58
|
+
function shouldFail(findings, failOn) {
|
|
59
|
+
if (failOn === "none")
|
|
60
|
+
return false;
|
|
61
|
+
if (failOn === "any")
|
|
62
|
+
return findings.length > 0;
|
|
63
|
+
const RANK = { critical: 0, high: 1, medium: 2, low: 3 };
|
|
64
|
+
const threshold = RANK[failOn] ?? 1;
|
|
65
|
+
return findings.some((f) => (RANK[f.severity] ?? 3) <= threshold);
|
|
66
|
+
}
|
|
67
|
+
async function runScan(rawArgs) {
|
|
68
|
+
const { positionals, failOn: cliFail, format, maxFiles: cliMax } = parseScanArgs(rawArgs);
|
|
69
|
+
const target = positionals[0];
|
|
70
|
+
if (!target) {
|
|
71
|
+
console.error("Usage: guardbee-prompt-leak-scanner scan <path> [--fail-on=any] [--format=text|json|sarif]");
|
|
72
|
+
process.exit(2);
|
|
73
|
+
}
|
|
74
|
+
const cfg = loadConfig(target, {
|
|
75
|
+
...(cliFail !== "any" ? { failOn: cliFail } : {}),
|
|
76
|
+
...(cliMax !== 5000 ? { maxFiles: cliMax } : {}),
|
|
77
|
+
});
|
|
78
|
+
const cfgPath = configFilePath(target);
|
|
79
|
+
if (cfgPath && format === "text")
|
|
80
|
+
process.stderr.write(`[guardbee] Using config: ${cfgPath}\n`);
|
|
81
|
+
let stat;
|
|
82
|
+
try {
|
|
83
|
+
stat = statSync(target);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
console.error(`Path not found: ${target}`);
|
|
87
|
+
process.exit(2);
|
|
88
|
+
}
|
|
89
|
+
let findings;
|
|
90
|
+
let scannedFiles;
|
|
91
|
+
let durationMs;
|
|
92
|
+
if (stat.isDirectory()) {
|
|
93
|
+
const result = scanDirectory(target, { maxFiles: cfg.maxFiles, exclude: cfg.exclude });
|
|
94
|
+
findings = result.findings;
|
|
95
|
+
scannedFiles = result.scannedFiles;
|
|
96
|
+
durationMs = result.durationMs;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
const start = Date.now();
|
|
100
|
+
const result = scanFile(target);
|
|
101
|
+
findings = result.findings;
|
|
102
|
+
scannedFiles = result.skipped ? 0 : 1;
|
|
103
|
+
durationMs = Date.now() - start;
|
|
104
|
+
}
|
|
105
|
+
if (format === "json") {
|
|
106
|
+
console.log(JSON.stringify({ findings, scannedFiles, durationMs }, null, 2));
|
|
107
|
+
}
|
|
108
|
+
else if (format === "sarif") {
|
|
109
|
+
console.log(JSON.stringify(buildSarif(getVersion(), findings), null, 2));
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
printText(findings, scannedFiles, durationMs);
|
|
113
|
+
}
|
|
114
|
+
process.exit(shouldFail(findings, cfg.failOn) ? 1 : 0);
|
|
115
|
+
}
|
|
116
|
+
function parseProxyArgs(args) {
|
|
117
|
+
let port = 8788;
|
|
118
|
+
let upstream;
|
|
119
|
+
let mode = "monitor";
|
|
120
|
+
let failOnSeverity;
|
|
121
|
+
for (const arg of args) {
|
|
122
|
+
if (arg.startsWith("--port="))
|
|
123
|
+
port = parseInt(arg.split("=")[1] ?? "8788", 10);
|
|
124
|
+
else if (arg.startsWith("--upstream="))
|
|
125
|
+
upstream = arg.split("=")[1];
|
|
126
|
+
else if (arg.startsWith("--mode="))
|
|
127
|
+
mode = arg.split("=")[1] ?? "monitor";
|
|
128
|
+
else if (arg.startsWith("--fail-on-severity="))
|
|
129
|
+
failOnSeverity = arg.split("=")[1];
|
|
130
|
+
}
|
|
131
|
+
return { port, upstream, mode, failOnSeverity };
|
|
132
|
+
}
|
|
133
|
+
function runProxy(rawArgs) {
|
|
134
|
+
const { port, upstream, mode, failOnSeverity } = parseProxyArgs(rawArgs);
|
|
135
|
+
if (!upstream) {
|
|
136
|
+
console.error("Usage: guardbee-prompt-leak-scanner proxy --upstream=https://api.openai.com [--port=8788] [--mode=monitor|redact|block] [--fail-on-severity=high]");
|
|
137
|
+
process.exit(2);
|
|
138
|
+
}
|
|
139
|
+
startProxy({
|
|
140
|
+
port,
|
|
141
|
+
upstream,
|
|
142
|
+
mode,
|
|
143
|
+
failOnSeverity,
|
|
144
|
+
onAudit: (event) => {
|
|
145
|
+
process.stdout.write(JSON.stringify(event) + "\n");
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
process.stderr.write(`[guardbee-prompt-leak-scanner] Proxying :${port} -> ${upstream} (mode: ${mode})\n`);
|
|
149
|
+
}
|
|
150
|
+
function printHelp() {
|
|
151
|
+
console.log(`@guardbee/mcp-prompt-leak-scanner
|
|
152
|
+
|
|
153
|
+
Usage (MCP server):
|
|
154
|
+
guardbee-prompt-leak-scanner [serve]
|
|
155
|
+
|
|
156
|
+
Usage (CLI):
|
|
157
|
+
guardbee-prompt-leak-scanner scan <path> Scan a file/directory (prompt logs, request-body fixtures)
|
|
158
|
+
guardbee-prompt-leak-scanner proxy --upstream=<url> Run a live reverse proxy in front of a real LLM API
|
|
159
|
+
|
|
160
|
+
scan options:
|
|
161
|
+
--fail-on=<level> Exit 1 if issues at this severity or above are found
|
|
162
|
+
Levels: any (default) | critical | high | medium | low | none
|
|
163
|
+
--format=<fmt> Output format: text (default) | json | sarif
|
|
164
|
+
--max-files=<n> Max files to scan (default: 5000)
|
|
165
|
+
|
|
166
|
+
proxy options:
|
|
167
|
+
--upstream=<url> Real API base URL to forward to (required), e.g. https://api.openai.com
|
|
168
|
+
--port=<n> Local port to listen on (default: 8788)
|
|
169
|
+
--mode=<mode> monitor (default, forward unchanged + log) | redact (forward with matches replaced) | block (reject the request)
|
|
170
|
+
--fail-on-severity=<sev> In block mode, minimum severity that triggers a block (default: high)
|
|
171
|
+
|
|
172
|
+
Audit events (JSON lines, no leaked values included) are written to stdout as the proxy runs.
|
|
173
|
+
|
|
174
|
+
Exit codes (scan):
|
|
175
|
+
0 No issues found (or none above --fail-on threshold)
|
|
176
|
+
1 Issues found at or above threshold
|
|
177
|
+
2 Error / bad arguments
|
|
178
|
+
`);
|
|
179
|
+
}
|
|
180
|
+
const [, , firstArg, ...rest] = process.argv;
|
|
181
|
+
if (!firstArg || firstArg === "serve") {
|
|
182
|
+
startServer().catch((err) => {
|
|
183
|
+
process.stderr.write(`[guardbee-prompt-leak-scanner] Fatal error: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
184
|
+
process.exit(1);
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
else if (firstArg === "--help" || firstArg === "-h") {
|
|
188
|
+
printHelp();
|
|
189
|
+
process.exit(0);
|
|
190
|
+
}
|
|
191
|
+
else if (firstArg === "scan") {
|
|
192
|
+
runScan(rest).catch((err) => {
|
|
193
|
+
console.error("Error:", err.message);
|
|
194
|
+
process.exit(2);
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
else if (firstArg === "proxy") {
|
|
198
|
+
runProxy(rest);
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
console.error(`Unknown command: ${firstArg}`);
|
|
202
|
+
console.error("Run with --help for usage.");
|
|
203
|
+
process.exit(2);
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAEvD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,UAAU,EAAmC,MAAM,YAAY,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,SAAS,UAAU;IACjB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC,CAAwB,CAAC;QAC3G,OAAO,GAAG,CAAC,OAAO,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,QAAQ,GAA2B,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;AAEjG,SAAS,SAAS,CAAC,QAAmB,EAAE,YAAoB,EAAE,UAAkB;IAC9E,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,2CAA2C,YAAY,aAAa,UAAU,KAAK,CAAC,CAAC;QACjG,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,CAAC,IAAI,QAAQ;QAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAE7E,OAAO,CAAC,GAAG,CAAC,aAAa,QAAQ,CAAC,MAAM,kBAAkB,YAAY,aAAa,UAAU,KAAK,CAAC,CAAC;IACpG,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnJ,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,KAAK,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC;QACtF,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QACvE,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC,WAAW,WAAW,CAAC,CAAC;QAC7D,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,IAAc;IACnC,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,MAAM,GAAG,MAAM,CAAC;IACpB,IAAI,QAAQ,GAAG,IAAI,CAAC;IAEpB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,CAAC,UAAU,CAAC,YAAY,CAAC;YAAE,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC;aACjE,IAAI,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC;YAAE,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC;aACtE,IAAI,GAAG,CAAC,UAAU,CAAC,cAAc,CAAC;YAAE,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;aACzF,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AACnD,CAAC;AAED,SAAS,UAAU,CAAC,QAAmB,EAAE,MAAc;IACrD,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IACpC,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IACjD,MAAM,IAAI,GAA2B,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;IACjF,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACpC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC;AACpE,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,OAAiB;IACtC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IAE1F,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,4FAA4F,CAAC,CAAC;QAC5G,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,EAAE;QAC7B,GAAG,CAAC,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACjD,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IACvC,IAAI,OAAO,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,OAAO,IAAI,CAAC,CAAC;IAEhG,IAAI,IAAI,CAAC;IACT,IAAI,CAAC;QACH,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAC;QAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,QAAmB,CAAC;IACxB,IAAI,YAAoB,CAAC;IACzB,IAAI,UAAkB,CAAC;IAEvB,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACvF,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;QAC3B,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;QACnC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;IACjC,CAAC;SAAM,CAAC;QACN,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;QAChC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;QAC3B,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;IAClC,CAAC;IAED,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/E,CAAC;SAAM,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,UAAU,EAAE,EAAE,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3E,CAAC;SAAM,CAAC;QACN,SAAS,CAAC,QAAQ,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;IAChD,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,SAAS,cAAc,CAAC,IAAc;IACpC,IAAI,IAAI,GAAG,IAAI,CAAC;IAChB,IAAI,QAA4B,CAAC;IACjC,IAAI,IAAI,GAAc,SAAS,CAAC;IAChC,IAAI,cAA+C,CAAC;IAEpD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;aAC3E,IAAI,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC;YAAE,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;aAChE,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,IAAI,GAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAe,IAAI,SAAS,CAAC;aACpF,IAAI,GAAG,CAAC,UAAU,CAAC,qBAAqB,CAAC;YAAE,cAAc,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAwB,CAAC;IAC5G,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;AAClD,CAAC;AAED,SAAS,QAAQ,CAAC,OAAiB;IACjC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IACzE,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,mJAAmJ,CAAC,CAAC;QACnK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,UAAU,CAAC;QACT,IAAI;QACJ,QAAQ;QACR,IAAI;QACJ,cAAc;QACd,OAAO,EAAE,CAAC,KAAiB,EAAE,EAAE;YAC7B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;QACrD,CAAC;KACF,CAAC,CAAC;IAEH,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,4CAA4C,IAAI,OAAO,QAAQ,WAAW,IAAI,KAAK,CAAC,CAAC;AAC5G,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2Bb,CAAC,CAAC;AACH,CAAC;AAED,MAAM,CAAC,EAAE,AAAD,EAAG,QAAQ,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;AAE7C,IAAI,CAAC,QAAQ,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;IACtC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,+CAA+C,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1H,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;KAAM,IAAI,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;IACtD,SAAS,EAAE,CAAC;IACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;KAAM,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;IAC/B,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QAC1B,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAG,GAAa,CAAC,OAAO,CAAC,CAAC;QAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;KAAM,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;IAChC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACjB,CAAC;KAAM,CAAC;IACN,OAAO,CAAC,KAAK,CAAC,oBAAoB,QAAQ,EAAE,CAAC,CAAC;IAC9C,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface PromptLeakScannerConfig {
|
|
2
|
+
failOn: string;
|
|
3
|
+
maxFiles: number;
|
|
4
|
+
exclude: string[];
|
|
5
|
+
}
|
|
6
|
+
export declare function loadConfig(searchDir: string, cliOverrides?: Partial<PromptLeakScannerConfig>): PromptLeakScannerConfig;
|
|
7
|
+
export declare function configFilePath(searchDir: string): string | null;
|
|
8
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAiFD,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,GAAE,OAAO,CAAC,uBAAuB,CAAM,GAAG,uBAAuB,CAmB1H;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE/D"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from "fs";
|
|
2
|
+
import { resolve, join } from "path";
|
|
3
|
+
const DEFAULTS = {
|
|
4
|
+
failOn: "any",
|
|
5
|
+
maxFiles: 5000,
|
|
6
|
+
exclude: [],
|
|
7
|
+
};
|
|
8
|
+
function findConfigFile(startDir) {
|
|
9
|
+
const names = ["guardbee.yml", "guardbee.yaml", ".guardbee.yml"];
|
|
10
|
+
let dir = resolve(startDir);
|
|
11
|
+
for (let i = 0; i < 5; i++) {
|
|
12
|
+
for (const name of names) {
|
|
13
|
+
const p = join(dir, name);
|
|
14
|
+
if (existsSync(p))
|
|
15
|
+
return p;
|
|
16
|
+
}
|
|
17
|
+
const parent = resolve(dir, "..");
|
|
18
|
+
if (parent === dir)
|
|
19
|
+
break;
|
|
20
|
+
dir = parent;
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
function parseYaml(content) {
|
|
25
|
+
const root = {};
|
|
26
|
+
let currentSection = null;
|
|
27
|
+
let currentKey = null;
|
|
28
|
+
let currentList = null;
|
|
29
|
+
for (const rawLine of content.split("\n")) {
|
|
30
|
+
const line = rawLine.replace(/#.*$/, "");
|
|
31
|
+
if (!line.trim())
|
|
32
|
+
continue;
|
|
33
|
+
const indent = line.match(/^(\s*)/)?.[1].length ?? 0;
|
|
34
|
+
if (indent === 0 && line.trim().endsWith(":")) {
|
|
35
|
+
if (currentKey && currentList) {
|
|
36
|
+
root[currentSection][currentKey] = currentList;
|
|
37
|
+
currentList = null;
|
|
38
|
+
currentKey = null;
|
|
39
|
+
}
|
|
40
|
+
currentSection = line.trim().slice(0, -1);
|
|
41
|
+
root[currentSection] = {};
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (indent === 2 && currentSection) {
|
|
45
|
+
if (currentKey && currentList) {
|
|
46
|
+
root[currentSection][currentKey] = currentList;
|
|
47
|
+
currentList = null;
|
|
48
|
+
currentKey = null;
|
|
49
|
+
}
|
|
50
|
+
const colonIdx = line.indexOf(":");
|
|
51
|
+
if (colonIdx === -1)
|
|
52
|
+
continue;
|
|
53
|
+
const key = line.slice(0, colonIdx).trim();
|
|
54
|
+
const value = line.slice(colonIdx + 1).trim();
|
|
55
|
+
if (value === "") {
|
|
56
|
+
currentKey = key;
|
|
57
|
+
currentList = [];
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
root[currentSection][key] = value;
|
|
61
|
+
}
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (indent === 4 && currentList !== null) {
|
|
65
|
+
const item = line.trim().replace(/^-\s*/, "").replace(/^['"]|['"]$/g, "");
|
|
66
|
+
currentList.push(item);
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (currentKey && currentList && currentSection) {
|
|
71
|
+
root[currentSection][currentKey] = currentList;
|
|
72
|
+
}
|
|
73
|
+
return root;
|
|
74
|
+
}
|
|
75
|
+
export function loadConfig(searchDir, cliOverrides = {}) {
|
|
76
|
+
const configPath = findConfigFile(searchDir);
|
|
77
|
+
if (!configPath)
|
|
78
|
+
return { ...DEFAULTS, ...cliOverrides };
|
|
79
|
+
let fileConfig = {};
|
|
80
|
+
try {
|
|
81
|
+
const raw = readFileSync(configPath, "utf8");
|
|
82
|
+
const parsed = parseYaml(raw);
|
|
83
|
+
const section = parsed["prompt-leak-scanner"];
|
|
84
|
+
if (section) {
|
|
85
|
+
if (typeof section["fail-on"] === "string")
|
|
86
|
+
fileConfig.failOn = section["fail-on"];
|
|
87
|
+
if (typeof section["max-files"] === "string")
|
|
88
|
+
fileConfig.maxFiles = parseInt(section["max-files"], 10);
|
|
89
|
+
if (Array.isArray(section["exclude"]))
|
|
90
|
+
fileConfig.exclude = section["exclude"];
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// ignore parse errors, use defaults
|
|
95
|
+
}
|
|
96
|
+
return { ...DEFAULTS, ...fileConfig, ...cliOverrides };
|
|
97
|
+
}
|
|
98
|
+
export function configFilePath(searchDir) {
|
|
99
|
+
return findConfigFile(searchDir);
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { scanText, scanAndRedactText, scanBody, redactBody, scanFile, scanDirectory } from "./scanner.js";
|
|
2
|
+
export type { Finding, ScanResult } from "./scanner.js";
|
|
3
|
+
export { LEAK_PATTERNS } from "./patterns.js";
|
|
4
|
+
export type { LeakPattern, LeakCategory } from "./patterns.js";
|
|
5
|
+
export { startProxy } from "./proxy.js";
|
|
6
|
+
export type { ProxyOptions, ProxyMode, AuditEvent } from "./proxy.js";
|
|
7
|
+
//# 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,QAAQ,EAAE,iBAAiB,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC1G,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE1G,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type LeakCategory = "credential" | "financial-pii" | "national-id" | "contact-pii";
|
|
2
|
+
export interface LeakPattern {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
category: LeakCategory;
|
|
6
|
+
pattern: RegExp;
|
|
7
|
+
severity: "critical" | "high" | "medium" | "low";
|
|
8
|
+
recommendation: string;
|
|
9
|
+
/** Extra checksum/structure validation beyond the regex, to keep false positives low. */
|
|
10
|
+
validate?: (rawMatch: string) => boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare const LEAK_PATTERNS: LeakPattern[];
|
|
13
|
+
//# sourceMappingURL=patterns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../src/patterns.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,eAAe,GAAG,aAAa,GAAG,aAAa,CAAC;AAE1F,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACjD,cAAc,EAAE,MAAM,CAAC;IACvB,yFAAyF;IACzF,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CAC1C;AAkDD,eAAO,MAAM,aAAa,EAAE,WAAW,EA2HtC,CAAC"}
|
package/dist/patterns.js
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// ── Checksum validators ──────────────────────────────────────────────────────
|
|
2
|
+
/** Turkish national ID (TC Kimlik No) checksum — the standard 11-digit algorithm. */
|
|
3
|
+
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
|
+
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
|
+
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
|
+
// ── Patterns ──────────────────────────────────────────────────────────────────
|
|
48
|
+
export const LEAK_PATTERNS = [
|
|
49
|
+
// ── Credentials — sending these to a third-party LLM is a direct secret leak ──
|
|
50
|
+
{
|
|
51
|
+
id: "openai_api_key",
|
|
52
|
+
name: "OpenAI API key",
|
|
53
|
+
category: "credential",
|
|
54
|
+
pattern: /\bsk-[A-Za-z0-9]{20,}\b/g,
|
|
55
|
+
severity: "critical",
|
|
56
|
+
recommendation: "Never let an API key flow into a prompt. Strip it before the request leaves your application, and rotate the key — it may already have been sent to a third party.",
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
id: "anthropic_api_key",
|
|
60
|
+
name: "Anthropic API key",
|
|
61
|
+
category: "credential",
|
|
62
|
+
pattern: /\bsk-ant-[A-Za-z0-9_-]{20,}\b/g,
|
|
63
|
+
severity: "critical",
|
|
64
|
+
recommendation: "Never let an API key flow into a prompt. Strip it before the request leaves your application, and rotate the key.",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
id: "aws_access_key_id",
|
|
68
|
+
name: "AWS access key ID",
|
|
69
|
+
category: "credential",
|
|
70
|
+
pattern: /\bAKIA[0-9A-Z]{16}\b/g,
|
|
71
|
+
severity: "critical",
|
|
72
|
+
recommendation: "An AWS access key in a prompt is a direct cloud-account compromise risk. Strip it and rotate the key immediately.",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
id: "github_pat",
|
|
76
|
+
name: "GitHub personal access token",
|
|
77
|
+
category: "credential",
|
|
78
|
+
pattern: /\bghp_[A-Za-z0-9]{36}\b/g,
|
|
79
|
+
severity: "critical",
|
|
80
|
+
recommendation: "Strip GitHub tokens before they reach a prompt, and revoke/rotate this one.",
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
id: "slack_token",
|
|
84
|
+
name: "Slack token",
|
|
85
|
+
category: "credential",
|
|
86
|
+
pattern: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/g,
|
|
87
|
+
severity: "critical",
|
|
88
|
+
recommendation: "Strip Slack tokens before they reach a prompt, and rotate this one.",
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
id: "google_api_key",
|
|
92
|
+
name: "Google API key",
|
|
93
|
+
category: "credential",
|
|
94
|
+
pattern: /\bAIza[0-9A-Za-z_-]{35}\b/g,
|
|
95
|
+
severity: "critical",
|
|
96
|
+
recommendation: "Strip Google API keys before they reach a prompt, and rotate this one.",
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
id: "stripe_secret_key",
|
|
100
|
+
name: "Stripe secret key",
|
|
101
|
+
category: "credential",
|
|
102
|
+
pattern: /\bsk_live_[0-9a-zA-Z]{24,}\b/g,
|
|
103
|
+
severity: "critical",
|
|
104
|
+
recommendation: "A live Stripe secret key in a prompt is a direct payments-account compromise risk. Strip it and rotate the key immediately.",
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
id: "private_key_block",
|
|
108
|
+
name: "PEM private key block",
|
|
109
|
+
category: "credential",
|
|
110
|
+
pattern: /-----BEGIN (?:RSA |EC |OPENSSH |DSA |)PRIVATE KEY-----/g,
|
|
111
|
+
severity: "critical",
|
|
112
|
+
recommendation: "A private key must never enter a prompt. Strip it and rotate/reissue the key pair.",
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
id: "jwt_token",
|
|
116
|
+
name: "JWT (JSON Web Token)",
|
|
117
|
+
category: "credential",
|
|
118
|
+
pattern: /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g,
|
|
119
|
+
severity: "high",
|
|
120
|
+
recommendation: "A JWT often carries session/identity claims. Strip it before the request leaves your application.",
|
|
121
|
+
},
|
|
122
|
+
// ── Financial PII ─────────────────────────────────────────────────────────────
|
|
123
|
+
{
|
|
124
|
+
id: "credit_card_number",
|
|
125
|
+
name: "Credit card number",
|
|
126
|
+
category: "financial-pii",
|
|
127
|
+
pattern: /\b(?:\d[ -]?){13,19}\b/g,
|
|
128
|
+
severity: "high",
|
|
129
|
+
recommendation: "Card numbers sent to a third-party LLM are a PCI-DSS and KVKK/GDPR data-transfer concern. Redact or tokenize before the prompt is built.",
|
|
130
|
+
validate: isValidLuhn,
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
id: "iban",
|
|
134
|
+
name: "IBAN",
|
|
135
|
+
category: "financial-pii",
|
|
136
|
+
pattern: /\b[A-Z]{2}\d{2}[A-Z0-9]{10,30}\b/g,
|
|
137
|
+
severity: "high",
|
|
138
|
+
recommendation: "An IBAN is regulated financial PII. Redact or tokenize before the prompt is built.",
|
|
139
|
+
validate: isValidIban,
|
|
140
|
+
},
|
|
141
|
+
// ── National ID ───────────────────────────────────────────────────────────────
|
|
142
|
+
{
|
|
143
|
+
id: "tc_kimlik_no",
|
|
144
|
+
name: "Turkish national ID (TC Kimlik No)",
|
|
145
|
+
category: "national-id",
|
|
146
|
+
pattern: /\b\d{11}\b/g,
|
|
147
|
+
severity: "high",
|
|
148
|
+
recommendation: "A validated TC Kimlik No is regulated personal data under KVKK. Redact or tokenize before the prompt is built.",
|
|
149
|
+
validate: isValidTcKimlik,
|
|
150
|
+
},
|
|
151
|
+
// ── Contact PII ───────────────────────────────────────────────────────────────
|
|
152
|
+
{
|
|
153
|
+
id: "email_address",
|
|
154
|
+
name: "Email address",
|
|
155
|
+
category: "contact-pii",
|
|
156
|
+
pattern: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g,
|
|
157
|
+
severity: "medium",
|
|
158
|
+
recommendation: "Consider whether the model needs the real email address, or a placeholder/tokenized reference would do.",
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
id: "turkish_phone_number",
|
|
162
|
+
name: "Turkish phone number",
|
|
163
|
+
category: "contact-pii",
|
|
164
|
+
pattern: /\b(?:\+90|0)\s?5\d{2}[\s.-]?\d{3}[\s.-]?\d{2}[\s.-]?\d{2}\b/g,
|
|
165
|
+
severity: "medium",
|
|
166
|
+
recommendation: "Consider whether the model needs the real phone number, or a placeholder/tokenized reference would do.",
|
|
167
|
+
},
|
|
168
|
+
];
|
|
169
|
+
//# sourceMappingURL=patterns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patterns.js","sourceRoot":"","sources":["../src/patterns.ts"],"names":[],"mappings":"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"}
|
package/dist/proxy.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type Server } from "http";
|
|
2
|
+
import type { Finding } from "./scanner.js";
|
|
3
|
+
export type ProxyMode = "monitor" | "redact" | "block";
|
|
4
|
+
export interface ProxyOptions {
|
|
5
|
+
port: number;
|
|
6
|
+
/** Base URL of the real LLM API this proxy sits in front of, e.g. https://api.openai.com */
|
|
7
|
+
upstream: string;
|
|
8
|
+
mode: ProxyMode;
|
|
9
|
+
/** In "block" mode, the minimum severity that triggers a block (default: "high"). */
|
|
10
|
+
failOnSeverity?: Finding["severity"];
|
|
11
|
+
onAudit?: (event: AuditEvent) => void;
|
|
12
|
+
}
|
|
13
|
+
export interface AuditEvent {
|
|
14
|
+
timestamp: string;
|
|
15
|
+
method: string;
|
|
16
|
+
path: string;
|
|
17
|
+
mode: ProxyMode;
|
|
18
|
+
blocked: boolean;
|
|
19
|
+
findingCount: number;
|
|
20
|
+
findingCodes: string[];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* A reverse proxy that sits between your application and a real LLM API
|
|
24
|
+
* (OpenAI/Anthropic-compatible). It buffers and inspects only the outbound
|
|
25
|
+
* REQUEST body — message/system text fields — for leaked credentials and PII,
|
|
26
|
+
* then streams the upstream response straight back unmodified (so SSE/streaming
|
|
27
|
+
* completions pass through untouched; only the prompt going *out* is inspected).
|
|
28
|
+
*
|
|
29
|
+
* The audit trail never stores the actual matched text — only which pattern
|
|
30
|
+
* fired and where — so the proxy's own logs can't become a second copy of the
|
|
31
|
+
* leak it just caught.
|
|
32
|
+
*/
|
|
33
|
+
export declare function startProxy(options: ProxyOptions): Server;
|
|
34
|
+
//# sourceMappingURL=proxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwC,KAAK,MAAM,EAAE,MAAM,MAAM,CAAC;AAIzE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEvD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,4FAA4F;IAC5F,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,SAAS,CAAC;IAChB,qFAAqF;IACrF,cAAc,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IACrC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAoFxD"}
|