@kevinrabun/judges 3.53.0 → 3.55.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/CHANGELOG.md +24 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +112 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/approve-chain.d.ts +8 -0
- package/dist/commands/approve-chain.d.ts.map +1 -0
- package/dist/commands/approve-chain.js +235 -0
- package/dist/commands/approve-chain.js.map +1 -0
- package/dist/commands/build-optimize.d.ts +7 -0
- package/dist/commands/build-optimize.d.ts.map +1 -0
- package/dist/commands/build-optimize.js +257 -0
- package/dist/commands/build-optimize.js.map +1 -0
- package/dist/commands/coach-mode.d.ts +8 -0
- package/dist/commands/coach-mode.d.ts.map +1 -0
- package/dist/commands/coach-mode.js +230 -0
- package/dist/commands/coach-mode.js.map +1 -0
- package/dist/commands/commit-hygiene.d.ts +6 -0
- package/dist/commands/commit-hygiene.d.ts.map +1 -0
- package/dist/commands/commit-hygiene.js +176 -0
- package/dist/commands/commit-hygiene.js.map +1 -0
- package/dist/commands/context-inject.d.ts +9 -0
- package/dist/commands/context-inject.d.ts.map +1 -0
- package/dist/commands/context-inject.js +212 -0
- package/dist/commands/context-inject.js.map +1 -0
- package/dist/commands/deploy-readiness.d.ts +6 -0
- package/dist/commands/deploy-readiness.d.ts.map +1 -0
- package/dist/commands/deploy-readiness.js +212 -0
- package/dist/commands/deploy-readiness.js.map +1 -0
- package/dist/commands/finding-contest.d.ts +8 -0
- package/dist/commands/finding-contest.d.ts.map +1 -0
- package/dist/commands/finding-contest.js +193 -0
- package/dist/commands/finding-contest.js.map +1 -0
- package/dist/commands/habit-tracker.d.ts +8 -0
- package/dist/commands/habit-tracker.d.ts.map +1 -0
- package/dist/commands/habit-tracker.js +195 -0
- package/dist/commands/habit-tracker.js.map +1 -0
- package/dist/commands/migration-safety.d.ts +6 -0
- package/dist/commands/migration-safety.d.ts.map +1 -0
- package/dist/commands/migration-safety.js +257 -0
- package/dist/commands/migration-safety.js.map +1 -0
- package/dist/commands/observability-gap.d.ts +6 -0
- package/dist/commands/observability-gap.d.ts.map +1 -0
- package/dist/commands/observability-gap.js +212 -0
- package/dist/commands/observability-gap.js.map +1 -0
- package/dist/commands/prompt-replay.d.ts +8 -0
- package/dist/commands/prompt-replay.d.ts.map +1 -0
- package/dist/commands/prompt-replay.js +177 -0
- package/dist/commands/prompt-replay.js.map +1 -0
- package/dist/commands/review-replay.d.ts +9 -0
- package/dist/commands/review-replay.d.ts.map +1 -0
- package/dist/commands/review-replay.js +265 -0
- package/dist/commands/review-replay.js.map +1 -0
- package/dist/commands/rollback-safety.d.ts +5 -0
- package/dist/commands/rollback-safety.d.ts.map +1 -0
- package/dist/commands/rollback-safety.js +192 -0
- package/dist/commands/rollback-safety.js.map +1 -0
- package/dist/commands/secret-age.d.ts +6 -0
- package/dist/commands/secret-age.d.ts.map +1 -0
- package/dist/commands/secret-age.js +215 -0
- package/dist/commands/secret-age.js.map +1 -0
- package/dist/commands/snippet-eval.d.ts +8 -0
- package/dist/commands/snippet-eval.d.ts.map +1 -0
- package/dist/commands/snippet-eval.js +224 -0
- package/dist/commands/snippet-eval.js.map +1 -0
- package/dist/commands/test-quality.d.ts +6 -0
- package/dist/commands/test-quality.d.ts.map +1 -0
- package/dist/commands/test-quality.js +161 -0
- package/dist/commands/test-quality.js.map +1 -0
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rollback safety — detect changes that are unsafe or impossible to roll back.
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, readdirSync, statSync } from "fs";
|
|
5
|
+
import { join, extname } from "path";
|
|
6
|
+
// ─── File Collection ────────────────────────────────────────────────────────
|
|
7
|
+
const CODE_EXTS = new Set([".ts", ".tsx", ".js", ".jsx", ".py", ".java", ".go", ".rs", ".sql", ".yaml", ".yml"]);
|
|
8
|
+
function collectFiles(dir, max = 300) {
|
|
9
|
+
const files = [];
|
|
10
|
+
function walk(d) {
|
|
11
|
+
if (files.length >= max)
|
|
12
|
+
return;
|
|
13
|
+
let entries;
|
|
14
|
+
try {
|
|
15
|
+
entries = readdirSync(d);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
for (const e of entries) {
|
|
21
|
+
if (files.length >= max)
|
|
22
|
+
return;
|
|
23
|
+
if (e.startsWith(".") || e === "node_modules" || e === "dist" || e === "build")
|
|
24
|
+
continue;
|
|
25
|
+
const full = join(d, e);
|
|
26
|
+
try {
|
|
27
|
+
if (statSync(full).isDirectory())
|
|
28
|
+
walk(full);
|
|
29
|
+
else if (CODE_EXTS.has(extname(full)))
|
|
30
|
+
files.push(full);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
/* skip */
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
walk(dir);
|
|
38
|
+
return files;
|
|
39
|
+
}
|
|
40
|
+
// ─── Analysis ───────────────────────────────────────────────────────────────
|
|
41
|
+
const RISK_PATTERNS = [
|
|
42
|
+
{
|
|
43
|
+
pattern: /DROP\s+TABLE/i,
|
|
44
|
+
risk: "Destructive migration",
|
|
45
|
+
severity: "critical",
|
|
46
|
+
detail: "Drops entire table — data unrecoverable without backup",
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
pattern: /DROP\s+COLUMN/i,
|
|
50
|
+
risk: "Column removal",
|
|
51
|
+
severity: "critical",
|
|
52
|
+
detail: "Dropped column data lost — add deprecation period first",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
pattern: /ALTER\s+TABLE.*RENAME/i,
|
|
56
|
+
risk: "Table/column rename",
|
|
57
|
+
severity: "high",
|
|
58
|
+
detail: "Rename breaks old queries — use alias during transition",
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
pattern: /TRUNCATE\s+/i,
|
|
62
|
+
risk: "Table truncation",
|
|
63
|
+
severity: "critical",
|
|
64
|
+
detail: "Removes all rows — cannot undo without backup",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
pattern: /DELETE\s+FROM\s+\w+\s*(?:;|$)/im,
|
|
68
|
+
risk: "Mass delete",
|
|
69
|
+
severity: "high",
|
|
70
|
+
detail: "Delete without WHERE — removes all rows",
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
pattern: /ALTER\s+TYPE|CHANGE\s+COLUMN.*\bTYPE\b/i,
|
|
74
|
+
risk: "Column type change",
|
|
75
|
+
severity: "high",
|
|
76
|
+
detail: "Type narrowing can lose data silently",
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
pattern: /removeField|removeColumn|dropIndex/i,
|
|
80
|
+
risk: "ORM schema removal",
|
|
81
|
+
severity: "high",
|
|
82
|
+
detail: "Field/index removal in ORM migration — deploy new code first",
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
pattern: /\.destroy\(\)|\.deleteMany\(\{?\s*\}?\)|\.remove\(\{?\s*\}?\)/i,
|
|
86
|
+
risk: "Bulk data deletion",
|
|
87
|
+
severity: "high",
|
|
88
|
+
detail: "Bulk delete in application code — ensure filters are correct",
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
pattern: /(?:api|endpoint|route).*(?:removed|deprecated|deleted)/i,
|
|
92
|
+
risk: "API endpoint removal",
|
|
93
|
+
severity: "high",
|
|
94
|
+
detail: "Removing endpoints breaks consumers — deprecate first",
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
pattern: /(?:encryption|crypto).*(?:changed|migrated|switched)/i,
|
|
98
|
+
risk: "Encryption scheme change",
|
|
99
|
+
severity: "critical",
|
|
100
|
+
detail: "Changing encryption makes old data unreadable — migrate gradually",
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
pattern: /(?:partition|shard).*(?:key|strategy).*(?:change|update)/i,
|
|
104
|
+
risk: "Partition key change",
|
|
105
|
+
severity: "critical",
|
|
106
|
+
detail: "Partition key change requires full data re-distribution",
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
pattern: /irreversible|no.?rollback|one.?way/i,
|
|
110
|
+
risk: "Explicit irreversibility marker",
|
|
111
|
+
severity: "high",
|
|
112
|
+
detail: "Code explicitly marked as irreversible",
|
|
113
|
+
},
|
|
114
|
+
];
|
|
115
|
+
function analyzeFile(filepath) {
|
|
116
|
+
const risks = [];
|
|
117
|
+
let content;
|
|
118
|
+
try {
|
|
119
|
+
content = readFileSync(filepath, "utf-8");
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
return risks;
|
|
123
|
+
}
|
|
124
|
+
const lines = content.split("\n");
|
|
125
|
+
for (let i = 0; i < lines.length; i++) {
|
|
126
|
+
const line = lines[i];
|
|
127
|
+
for (const rp of RISK_PATTERNS) {
|
|
128
|
+
if (rp.pattern.test(line)) {
|
|
129
|
+
risks.push({ file: filepath, line: i + 1, risk: rp.risk, severity: rp.severity, detail: rp.detail });
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return risks;
|
|
134
|
+
}
|
|
135
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
136
|
+
export function runRollbackSafety(argv) {
|
|
137
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
138
|
+
console.log(`
|
|
139
|
+
judges rollback-safety — Detect changes unsafe or impossible to roll back
|
|
140
|
+
|
|
141
|
+
Usage:
|
|
142
|
+
judges rollback-safety [dir]
|
|
143
|
+
judges rollback-safety migrations/ --format json
|
|
144
|
+
|
|
145
|
+
Options:
|
|
146
|
+
[dir] Directory to scan (default: .)
|
|
147
|
+
--format json JSON output
|
|
148
|
+
--help, -h Show this help
|
|
149
|
+
|
|
150
|
+
Detects: destructive DB migrations, bulk deletes, API removals, encryption changes,
|
|
151
|
+
partition key changes, and code explicitly marked irreversible.
|
|
152
|
+
`);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
156
|
+
const dir = argv.find((a) => !a.startsWith("-") && argv.indexOf(a) > 0) || ".";
|
|
157
|
+
const files = collectFiles(dir);
|
|
158
|
+
const risks = [];
|
|
159
|
+
for (const f of files)
|
|
160
|
+
risks.push(...analyzeFile(f));
|
|
161
|
+
risks.sort((a, b) => {
|
|
162
|
+
const order = { critical: 0, high: 1, medium: 2 };
|
|
163
|
+
return order[a.severity] - order[b.severity];
|
|
164
|
+
});
|
|
165
|
+
const critCount = risks.filter((r) => r.severity === "critical").length;
|
|
166
|
+
const highCount = risks.filter((r) => r.severity === "high").length;
|
|
167
|
+
const score = risks.length === 0 ? 100 : Math.max(0, 100 - critCount * 25 - highCount * 10);
|
|
168
|
+
if (format === "json") {
|
|
169
|
+
console.log(JSON.stringify({
|
|
170
|
+
risks,
|
|
171
|
+
score,
|
|
172
|
+
summary: { critical: critCount, high: highCount, total: risks.length },
|
|
173
|
+
timestamp: new Date().toISOString(),
|
|
174
|
+
}, null, 2));
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
const badge = critCount > 0 ? "🚫 UNSAFE" : highCount > 0 ? "⚠️ CAUTION" : "✅ SAFE";
|
|
178
|
+
console.log(`\n Rollback Safety: ${badge} (score ${score}/100)\n ─────────────────────────`);
|
|
179
|
+
if (risks.length === 0) {
|
|
180
|
+
console.log(" No rollback risks detected.\n");
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
for (const r of risks) {
|
|
184
|
+
const icon = r.severity === "critical" ? "🚫" : r.severity === "high" ? "🔴" : "🟡";
|
|
185
|
+
console.log(` ${icon} [${r.severity.toUpperCase()}] ${r.risk}`);
|
|
186
|
+
console.log(` ${r.file}:${r.line}`);
|
|
187
|
+
console.log(` ${r.detail}`);
|
|
188
|
+
}
|
|
189
|
+
console.log(`\n Total: ${risks.length} risks | Critical: ${critCount} | High: ${highCount} | Score: ${score}/100\n`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=rollback-safety.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rollback-safety.js","sourceRoot":"","sources":["../../src/commands/rollback-safety.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-age.d.ts","sourceRoot":"","sources":["../../src/commands/secret-age.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAkLH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAiEjD"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret age — detect credentials with no rotation policy, hardcoded expiry,
|
|
3
|
+
* missing vault references, and shared service-account credentials.
|
|
4
|
+
*/
|
|
5
|
+
import { readFileSync, readdirSync, statSync } from "fs";
|
|
6
|
+
import { join, extname } from "path";
|
|
7
|
+
// ─── File Collection ────────────────────────────────────────────────────────
|
|
8
|
+
const SCAN_EXTS = new Set([
|
|
9
|
+
".ts",
|
|
10
|
+
".tsx",
|
|
11
|
+
".js",
|
|
12
|
+
".jsx",
|
|
13
|
+
".py",
|
|
14
|
+
".java",
|
|
15
|
+
".go",
|
|
16
|
+
".rs",
|
|
17
|
+
".yaml",
|
|
18
|
+
".yml",
|
|
19
|
+
".json",
|
|
20
|
+
".env",
|
|
21
|
+
".toml",
|
|
22
|
+
".cfg",
|
|
23
|
+
".ini",
|
|
24
|
+
".xml",
|
|
25
|
+
]);
|
|
26
|
+
function collectFiles(dir, max = 400) {
|
|
27
|
+
const files = [];
|
|
28
|
+
function walk(d) {
|
|
29
|
+
if (files.length >= max)
|
|
30
|
+
return;
|
|
31
|
+
let entries;
|
|
32
|
+
try {
|
|
33
|
+
entries = readdirSync(d);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
for (const e of entries) {
|
|
39
|
+
if (files.length >= max)
|
|
40
|
+
return;
|
|
41
|
+
if (e.startsWith(".") || e === "node_modules" || e === "dist" || e === "build")
|
|
42
|
+
continue;
|
|
43
|
+
const full = join(d, e);
|
|
44
|
+
try {
|
|
45
|
+
if (statSync(full).isDirectory())
|
|
46
|
+
walk(full);
|
|
47
|
+
else if (SCAN_EXTS.has(extname(full)))
|
|
48
|
+
files.push(full);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
/* skip */
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
walk(dir);
|
|
56
|
+
return files;
|
|
57
|
+
}
|
|
58
|
+
// ─── Patterns ───────────────────────────────────────────────────────────────
|
|
59
|
+
const SECRET_PATTERNS = [
|
|
60
|
+
{
|
|
61
|
+
pattern: /(?:api[_-]?key|apikey)\s*[:=]\s*['"][A-Za-z0-9]{16,}['"]/i,
|
|
62
|
+
finding: "Hardcoded API key",
|
|
63
|
+
severity: "critical",
|
|
64
|
+
recommendation: "Move to vault or environment variable",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
pattern: /(?:password|passwd|pwd)\s*[:=]\s*['"][^'"]{4,}['"]/i,
|
|
68
|
+
finding: "Hardcoded password",
|
|
69
|
+
severity: "critical",
|
|
70
|
+
recommendation: "Use a secrets manager",
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
pattern: /(?:secret|token)\s*[:=]\s*['"][A-Za-z0-9+/=]{16,}['"]/i,
|
|
74
|
+
finding: "Hardcoded secret/token",
|
|
75
|
+
severity: "critical",
|
|
76
|
+
recommendation: "Store in vault (AWS SSM, Azure Key Vault, HashiCorp Vault)",
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
pattern: /(?:private[_-]?key|privateKey)\s*[:=]\s*['"`]-----BEGIN/i,
|
|
80
|
+
finding: "Embedded private key",
|
|
81
|
+
severity: "critical",
|
|
82
|
+
recommendation: "Store private keys in a secure key store",
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
pattern: /(?:connection[_-]?string|connStr)\s*[:=]\s*['"][^'"]{20,}['"]/i,
|
|
86
|
+
finding: "Hardcoded connection string",
|
|
87
|
+
severity: "high",
|
|
88
|
+
recommendation: "Reference from vault; use managed identity where possible",
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
pattern: /expires?\s*[:=]\s*['"]?\d{4}[-/]\d{2}[-/]\d{2}/i,
|
|
92
|
+
finding: "Hardcoded expiry date",
|
|
93
|
+
severity: "medium",
|
|
94
|
+
recommendation: "Implement dynamic rotation; avoid static expiry",
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
pattern: /rotation|rotate.*(?:never|disabled|false)/i,
|
|
98
|
+
finding: "Rotation disabled",
|
|
99
|
+
severity: "high",
|
|
100
|
+
recommendation: "Enable automatic credential rotation",
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
pattern: /(?:aws_access_key_id|aws_secret_access_key)\s*[:=]\s*['"][A-Z0-9]{16,}['"]/i,
|
|
104
|
+
finding: "AWS credentials in source",
|
|
105
|
+
severity: "critical",
|
|
106
|
+
recommendation: "Use IAM roles or environment credentials",
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
pattern: /(?:GOOGLE_APPLICATION_CREDENTIALS|gcp_credentials)\s*[:=]\s*['"][^'"]+['"]/i,
|
|
110
|
+
finding: "GCP credentials in source",
|
|
111
|
+
severity: "high",
|
|
112
|
+
recommendation: "Use workload identity or service account key file outside repo",
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
pattern: /(?:shared|common)[_-]?(?:service)?[_-]?(?:account|credential|key)/i,
|
|
116
|
+
finding: "Shared service credentials",
|
|
117
|
+
severity: "high",
|
|
118
|
+
recommendation: "Use per-environment, per-service credentials",
|
|
119
|
+
},
|
|
120
|
+
];
|
|
121
|
+
function analyzeFile(filepath) {
|
|
122
|
+
const findings = [];
|
|
123
|
+
let content;
|
|
124
|
+
try {
|
|
125
|
+
content = readFileSync(filepath, "utf-8");
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return findings;
|
|
129
|
+
}
|
|
130
|
+
const lines = content.split("\n");
|
|
131
|
+
for (let i = 0; i < lines.length; i++) {
|
|
132
|
+
const line = lines[i];
|
|
133
|
+
// Skip comments
|
|
134
|
+
if (/^\s*(?:\/\/|#|\/\*|\*)/.test(line))
|
|
135
|
+
continue;
|
|
136
|
+
for (const sp of SECRET_PATTERNS) {
|
|
137
|
+
if (sp.pattern.test(line)) {
|
|
138
|
+
findings.push({
|
|
139
|
+
file: filepath,
|
|
140
|
+
line: i + 1,
|
|
141
|
+
finding: sp.finding,
|
|
142
|
+
severity: sp.severity,
|
|
143
|
+
recommendation: sp.recommendation,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// Check for vault integration
|
|
149
|
+
const hasVaultRef = /vault|keyVault|ssm|secretsmanager|VAULT_ADDR|SecretClient/i.test(content);
|
|
150
|
+
const hasSecrets = findings.length > 0;
|
|
151
|
+
if (hasSecrets && !hasVaultRef) {
|
|
152
|
+
findings.push({
|
|
153
|
+
file: filepath,
|
|
154
|
+
line: 1,
|
|
155
|
+
finding: "No vault integration detected",
|
|
156
|
+
severity: "medium",
|
|
157
|
+
recommendation: "Add a secrets manager reference for credential lifecycle management",
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
return findings;
|
|
161
|
+
}
|
|
162
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
163
|
+
export function runSecretAge(argv) {
|
|
164
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
165
|
+
console.log(`
|
|
166
|
+
judges secret-age — Credential lifecycle and rotation analysis
|
|
167
|
+
|
|
168
|
+
Usage:
|
|
169
|
+
judges secret-age [dir]
|
|
170
|
+
judges secret-age src/ --format json
|
|
171
|
+
|
|
172
|
+
Options:
|
|
173
|
+
[dir] Directory to scan (default: .)
|
|
174
|
+
--format json JSON output
|
|
175
|
+
--help, -h Show this help
|
|
176
|
+
|
|
177
|
+
Detects: hardcoded API keys, passwords, tokens, private keys, connection strings,
|
|
178
|
+
disabled rotation, hardcoded expiry, shared credentials, missing vault integration.
|
|
179
|
+
`);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
183
|
+
const dir = argv.find((a) => !a.startsWith("-") && argv.indexOf(a) > 0) || ".";
|
|
184
|
+
const files = collectFiles(dir);
|
|
185
|
+
const allFindings = [];
|
|
186
|
+
for (const f of files)
|
|
187
|
+
allFindings.push(...analyzeFile(f));
|
|
188
|
+
const critCount = allFindings.filter((f) => f.severity === "critical").length;
|
|
189
|
+
const highCount = allFindings.filter((f) => f.severity === "high").length;
|
|
190
|
+
const score = allFindings.length === 0 ? 100 : Math.max(0, 100 - critCount * 20 - highCount * 10);
|
|
191
|
+
if (format === "json") {
|
|
192
|
+
console.log(JSON.stringify({
|
|
193
|
+
findings: allFindings,
|
|
194
|
+
score,
|
|
195
|
+
summary: { critical: critCount, high: highCount, total: allFindings.length },
|
|
196
|
+
timestamp: new Date().toISOString(),
|
|
197
|
+
}, null, 2));
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
const badge = critCount > 0 ? "🚫 EXPOSED" : highCount > 0 ? "⚠️ AT RISK" : allFindings.length > 0 ? "🟡 REVIEW" : "✅ CLEAN";
|
|
201
|
+
console.log(`\n Secret Age Analysis: ${badge} (${score}/100)\n ─────────────────────────────`);
|
|
202
|
+
if (allFindings.length === 0) {
|
|
203
|
+
console.log(" No credential lifecycle issues detected.\n");
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
for (const f of allFindings) {
|
|
207
|
+
const icon = f.severity === "critical" ? "🚫" : f.severity === "high" ? "🔴" : "🟡";
|
|
208
|
+
console.log(` ${icon} [${f.severity.toUpperCase()}] ${f.finding}`);
|
|
209
|
+
console.log(` ${f.file}:${f.line}`);
|
|
210
|
+
console.log(` → ${f.recommendation}`);
|
|
211
|
+
}
|
|
212
|
+
console.log(`\n Total: ${allFindings.length} | Critical: ${critCount} | High: ${highCount} | Score: ${score}/100\n`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=secret-age.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-age.js","sourceRoot":"","sources":["../../src/commands/secret-age.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Snippet eval — evaluate a code snippet from stdin or a string
|
|
3
|
+
* argument without needing a file, with instant formatted output.
|
|
4
|
+
*
|
|
5
|
+
* Zero-friction entry point for evaluating AI-generated code snippets.
|
|
6
|
+
*/
|
|
7
|
+
export declare function runSnippetEval(argv: string[]): void;
|
|
8
|
+
//# sourceMappingURL=snippet-eval.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snippet-eval.d.ts","sourceRoot":"","sources":["../../src/commands/snippet-eval.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAkJH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAwGnD"}
|