@guardbee/mcp-secret-scanner 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +141 -4
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -84,6 +84,62 @@ Bu araç tarama sonuçlarında eşleşen değerleri **kısmen redakte eder** (`s
|
|
|
84
84
|
|
|
85
85
|
---
|
|
86
86
|
|
|
87
|
+
## CLI — CI/CD Entegrasyonu
|
|
88
|
+
|
|
89
|
+
MCP server moduna ek olarak doğrudan CLI olarak da kullanılabilir:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# Proje dizinini tara
|
|
93
|
+
npx @guardbee/mcp-secret-scanner scan ./my-project
|
|
94
|
+
|
|
95
|
+
# Tek dosya tara
|
|
96
|
+
npx @guardbee/mcp-secret-scanner scan .env
|
|
97
|
+
|
|
98
|
+
# Sadece critical/high'da başarısız ol
|
|
99
|
+
npx @guardbee/mcp-secret-scanner scan . --fail-on=high
|
|
100
|
+
|
|
101
|
+
# JSON çıktı (CI raporlama için)
|
|
102
|
+
npx @guardbee/mcp-secret-scanner scan . --format=json
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Exit kodları:** `0` = secret bulunamadı · `1` = secret bulundu · `2` = hata
|
|
106
|
+
|
|
107
|
+
### GitHub Actions
|
|
108
|
+
|
|
109
|
+
```yaml
|
|
110
|
+
name: Secret Scan
|
|
111
|
+
on: [push, pull_request]
|
|
112
|
+
|
|
113
|
+
jobs:
|
|
114
|
+
secret-scan:
|
|
115
|
+
runs-on: ubuntu-latest
|
|
116
|
+
steps:
|
|
117
|
+
- uses: actions/checkout@v4
|
|
118
|
+
- name: Scan for exposed secrets
|
|
119
|
+
run: npx @guardbee/mcp-secret-scanner scan . --fail-on=high
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### GitLab CI
|
|
123
|
+
|
|
124
|
+
```yaml
|
|
125
|
+
secret-scan:
|
|
126
|
+
image: node:20
|
|
127
|
+
script:
|
|
128
|
+
- npx @guardbee/mcp-secret-scanner scan . --fail-on=high
|
|
129
|
+
only:
|
|
130
|
+
- merge_requests
|
|
131
|
+
- main
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Pre-commit Hook
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
# .git/hooks/pre-commit
|
|
138
|
+
npx @guardbee/mcp-secret-scanner scan . --fail-on=critical || exit 1
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
87
143
|
## Geliştirme
|
|
88
144
|
|
|
89
145
|
```bash
|
package/dist/cli.d.ts
CHANGED
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,143 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
1
2
|
import { startServer } from "./server.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import { scanFile, scanDirectory } from "./scanner.js";
|
|
4
|
+
import { statSync } from "fs";
|
|
5
|
+
// ── Output ─────────────────────────────────────────────────────────────────────
|
|
6
|
+
const SEV_ICON = {
|
|
7
|
+
critical: "🔴",
|
|
8
|
+
high: "🟠",
|
|
9
|
+
medium: "🟡",
|
|
10
|
+
low: "🔵",
|
|
11
|
+
};
|
|
12
|
+
function printText(findings, scannedFiles, durationMs) {
|
|
13
|
+
if (findings.length === 0) {
|
|
14
|
+
console.log(`✅ No secrets found in ${scannedFiles} file(s) (${durationMs}ms)`);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const counts = {};
|
|
18
|
+
for (const f of findings)
|
|
19
|
+
counts[f.severity] = (counts[f.severity] ?? 0) + 1;
|
|
20
|
+
console.log(`⚠️ Found ${findings.length} secret(s) in ${scannedFiles} file(s) (${durationMs}ms)`);
|
|
21
|
+
console.log(` Critical: ${counts["critical"] ?? 0} High: ${counts["high"] ?? 0} Medium: ${counts["medium"] ?? 0} Low: ${counts["low"] ?? 0}`);
|
|
22
|
+
console.log("");
|
|
23
|
+
for (const f of findings) {
|
|
24
|
+
const icon = SEV_ICON[f.severity] ?? "⚪";
|
|
25
|
+
console.log(`${icon} [${f.severity.toUpperCase()}] ${f.patternName}`);
|
|
26
|
+
if (f.file)
|
|
27
|
+
console.log(` File : ${f.file}:${f.line}:${f.column}`);
|
|
28
|
+
console.log(` Match : ${f.match}`);
|
|
29
|
+
console.log(` Context : ${f.context}`);
|
|
30
|
+
console.log("");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// ── CLI ────────────────────────────────────────────────────────────────────────
|
|
34
|
+
function parseArgs(args) {
|
|
35
|
+
const positionals = [];
|
|
36
|
+
let failOn = "any";
|
|
37
|
+
let format = "text";
|
|
38
|
+
let maxFiles = 5000;
|
|
39
|
+
for (const arg of args) {
|
|
40
|
+
if (arg.startsWith("--fail-on="))
|
|
41
|
+
failOn = arg.split("=")[1] ?? "any";
|
|
42
|
+
else if (arg.startsWith("--format="))
|
|
43
|
+
format = arg.split("=")[1] ?? "text";
|
|
44
|
+
else if (arg.startsWith("--max-files="))
|
|
45
|
+
maxFiles = parseInt(arg.split("=")[1] ?? "5000", 10);
|
|
46
|
+
else if (!arg.startsWith("--"))
|
|
47
|
+
positionals.push(arg);
|
|
48
|
+
}
|
|
49
|
+
return { positionals, failOn, format, maxFiles };
|
|
50
|
+
}
|
|
51
|
+
function shouldFail(findings, failOn) {
|
|
52
|
+
if (failOn === "none")
|
|
53
|
+
return false;
|
|
54
|
+
if (failOn === "any")
|
|
55
|
+
return findings.length > 0;
|
|
56
|
+
const RANK = { critical: 0, high: 1, medium: 2, low: 3 };
|
|
57
|
+
const threshold = RANK[failOn] ?? 1;
|
|
58
|
+
return findings.some((f) => (RANK[f.severity] ?? 3) <= threshold);
|
|
59
|
+
}
|
|
60
|
+
async function runCli(rawArgs) {
|
|
61
|
+
const { positionals, failOn, format, maxFiles } = parseArgs(rawArgs);
|
|
62
|
+
const target = positionals[0];
|
|
63
|
+
if (!target) {
|
|
64
|
+
console.error("Usage: guardbee-secret-scanner scan <path> [--fail-on=any] [--format=text|json]");
|
|
65
|
+
process.exit(2);
|
|
66
|
+
}
|
|
67
|
+
let stat;
|
|
68
|
+
try {
|
|
69
|
+
stat = statSync(target);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
console.error(`Path not found: ${target}`);
|
|
73
|
+
process.exit(2);
|
|
74
|
+
}
|
|
75
|
+
let findings;
|
|
76
|
+
let scannedFiles;
|
|
77
|
+
let durationMs;
|
|
78
|
+
if (stat.isDirectory()) {
|
|
79
|
+
const result = scanDirectory(target, { maxFiles });
|
|
80
|
+
findings = result.findings;
|
|
81
|
+
scannedFiles = result.scannedFiles;
|
|
82
|
+
durationMs = result.durationMs;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
const start = Date.now();
|
|
86
|
+
const result = scanFile(target);
|
|
87
|
+
findings = result.findings;
|
|
88
|
+
scannedFiles = result.skipped ? 0 : 1;
|
|
89
|
+
durationMs = Date.now() - start;
|
|
90
|
+
}
|
|
91
|
+
if (format === "json") {
|
|
92
|
+
console.log(JSON.stringify({ findings, scannedFiles, durationMs }, null, 2));
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
printText(findings, scannedFiles, durationMs);
|
|
96
|
+
}
|
|
97
|
+
process.exit(shouldFail(findings, failOn) ? 1 : 0);
|
|
98
|
+
}
|
|
99
|
+
function printHelp() {
|
|
100
|
+
console.log(`@guardbee/mcp-secret-scanner
|
|
101
|
+
|
|
102
|
+
Usage (MCP server):
|
|
103
|
+
guardbee-secret-scanner [serve]
|
|
104
|
+
|
|
105
|
+
Usage (CLI):
|
|
106
|
+
guardbee-secret-scanner scan <path> Scan a file or directory for secrets
|
|
107
|
+
|
|
108
|
+
Options:
|
|
109
|
+
--fail-on=<level> Exit 1 if secrets at this severity or above are found
|
|
110
|
+
Levels: any (default) | critical | high | medium | low | none
|
|
111
|
+
--format=<fmt> Output format: text (default) | json
|
|
112
|
+
--max-files=<n> Max files to scan (default: 5000)
|
|
113
|
+
|
|
114
|
+
Exit codes:
|
|
115
|
+
0 No secrets found (or none above --fail-on threshold)
|
|
116
|
+
1 Secrets found at or above threshold
|
|
117
|
+
2 Error / bad arguments
|
|
118
|
+
`);
|
|
119
|
+
}
|
|
120
|
+
// ── Entry point ────────────────────────────────────────────────────────────────
|
|
121
|
+
const [, , firstArg, ...rest] = process.argv;
|
|
122
|
+
if (!firstArg || firstArg === "serve") {
|
|
123
|
+
startServer().catch((err) => {
|
|
124
|
+
process.stderr.write(`[guardbee-secret-scanner] Fatal error: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
125
|
+
process.exit(1);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
else if (firstArg === "--help" || firstArg === "-h") {
|
|
129
|
+
printHelp();
|
|
130
|
+
process.exit(0);
|
|
131
|
+
}
|
|
132
|
+
else if (firstArg === "scan") {
|
|
133
|
+
runCli(rest).catch((err) => {
|
|
134
|
+
console.error("Error:", err.message);
|
|
135
|
+
process.exit(2);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
console.error(`Unknown command: ${firstArg}`);
|
|
140
|
+
console.error("Run with --help for usage.");
|
|
141
|
+
process.exit(2);
|
|
142
|
+
}
|
|
6
143
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|