project-athena 0.4.0 → 0.5.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 +31 -0
- package/README.md +10 -0
- package/dist/{activity-BKW7G4I5.js → activity-XCHKBZTG.js} +4 -4
- package/dist/{agents-DFSNEOP5.js → agents-HUJ4JXIB.js} +4 -4
- package/dist/{ai-ASL4FFQ7.js → ai-LGTLQKL4.js} +3 -3
- package/dist/{analyze-ZY3MXBOI.js → analyze-AP4XJT7D.js} +7 -7
- package/dist/{chunk-ZB7LC6FP.js → chunk-3KFOI2X4.js} +2 -2
- package/dist/{chunk-MPG3IEGB.js → chunk-44EGCEB2.js} +23 -14
- package/dist/{chunk-GGXPG6OE.js → chunk-4FETKOY3.js} +8 -7
- package/dist/chunk-4IIBVTBS.js +76 -0
- package/dist/{chunk-LEMPCNAY.js → chunk-56EXAGTM.js} +3 -3
- package/dist/{chunk-DZDI2HRT.js → chunk-6OSQMXUP.js} +5 -5
- package/dist/{chunk-OLPSEQS5.js → chunk-AKOI4VTD.js} +10 -1
- package/dist/{chunk-FVCDMQUQ.js → chunk-C25FDXOO.js} +133 -23
- package/dist/{chunk-7DZK6WSQ.js → chunk-DH5AGULY.js} +2 -2
- package/dist/{chunk-TDNZ2RYA.js → chunk-F65QINMR.js} +2 -2
- package/dist/{chunk-WVQC2EGO.js → chunk-GU3ZX2J7.js} +2 -2
- package/dist/{chunk-UAZLPNVC.js → chunk-GYQG4Q2N.js} +4 -4
- package/dist/chunk-IDODPGTX.js +595 -0
- package/dist/chunk-KJYSNZXS.js +934 -0
- package/dist/{chunk-3XSDI5WF.js → chunk-L2EHJCH4.js} +5 -5
- package/dist/{chunk-65TSRDQ3.js → chunk-P4TRQMES.js} +2 -2
- package/dist/{chunk-KHMBNT66.js → chunk-PZPMWCXS.js} +5 -5
- package/dist/{chunk-XDCKZ5TV.js → chunk-R5AX7VST.js} +2 -2
- package/dist/{chunk-QLW657NT.js → chunk-RQKGT2EK.js} +2 -2
- package/dist/{chunk-VSYBC3VY.js → chunk-UMWX4UTK.js} +2 -2
- package/dist/{chunk-RXNRMIZP.js → chunk-WUIC65QO.js} +2 -2
- package/dist/{chunk-JCGDR4UV.js → chunk-WWQ5NKEC.js} +3 -1
- package/dist/{chunk-RVTNSNGK.js → chunk-X7EYOAEX.js} +2 -2
- package/dist/chunk-Y6SDMZET.js +278 -0
- package/dist/{clean-MDBYH62P.js → clean-LQOG56AM.js} +2 -2
- package/dist/cli.js +2 -2
- package/dist/{context-PLPCAPCO.js → context-G5YHY3L2.js} +8 -8
- package/dist/{doctor-BX677KRE.js → doctor-L34QJ7WR.js} +8 -8
- package/dist/{event-TNT6CQZR.js → event-6YW6TGFI.js} +3 -3
- package/dist/{git-hook-YZNZGAAP.js → git-hook-Y7Y262F7.js} +2 -2
- package/dist/{init-WQCAOJ2R.js → init-427QR5AS.js} +7 -7
- package/dist/{mcp-U7EPH43L.js → mcp-DWNWRGJW.js} +51 -14
- package/dist/{memory-VSVNLEJC.js → memory-XBZCYQLW.js} +3 -3
- package/dist/{open-UJZRYF4E.js → open-LJMOB6U2.js} +33 -31
- package/dist/{program-CWJNGCTZ.js → program-DCP526LU.js} +46 -32
- package/dist/{review-OOKXSYMP.js → review-VEJBPACX.js} +10 -9
- package/dist/{rules-4FXJUCXB.js → rules-M4DLLXBL.js} +4 -4
- package/dist/scan-JVKCVHPD.js +939 -0
- package/dist/{security-LME3XFL3.js → security-JTJN3E7K.js} +13 -11
- package/dist/{staged-check-X24C3YRD.js → staged-check-PQSLGQBW.js} +11 -11
- package/dist/{status-RR57ZNGI.js → status-PO27BSOZ.js} +4 -4
- package/dist/{sync-KFJANRXF.js → sync-GVO2VHPI.js} +10 -10
- package/dist/{watch-CY7QHIYN.js → watch-TEHFO47V.js} +10 -10
- package/package.json +3 -1
- package/dist/chunk-SJ4DQFIJ.js +0 -379
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
committedAiWarning
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-WUIC65QO.js";
|
|
5
5
|
import {
|
|
6
6
|
whichExecutable
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-UMWX4UTK.js";
|
|
8
8
|
import {
|
|
9
9
|
readRecentEvents
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-P4TRQMES.js";
|
|
11
11
|
import {
|
|
12
12
|
listRules,
|
|
13
13
|
parseRules
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
import {
|
|
22
22
|
gitAvailable,
|
|
23
23
|
isGitRepo
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-AKOI4VTD.js";
|
|
25
25
|
import {
|
|
26
26
|
ADAPTERS
|
|
27
27
|
} from "./chunk-YRIS7ZS6.js";
|
|
@@ -176,4 +176,4 @@ export {
|
|
|
176
176
|
findRunningInstance,
|
|
177
177
|
runDoctor
|
|
178
178
|
};
|
|
179
|
-
//# sourceMappingURL=chunk-
|
|
179
|
+
//# sourceMappingURL=chunk-L2EHJCH4.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
redact
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-WWQ5NKEC.js";
|
|
5
5
|
import {
|
|
6
6
|
toPosix
|
|
7
7
|
} from "./chunk-XW3MLHI2.js";
|
|
@@ -121,4 +121,4 @@ export {
|
|
|
121
121
|
readRecentEvents,
|
|
122
122
|
summarizeSessions
|
|
123
123
|
};
|
|
124
|
-
//# sourceMappingURL=chunk-
|
|
124
|
+
//# sourceMappingURL=chunk-P4TRQMES.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
projectSession
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-GU3ZX2J7.js";
|
|
5
5
|
import {
|
|
6
6
|
impactOf
|
|
7
7
|
} from "./chunk-GR4DL2VM.js";
|
|
@@ -11,13 +11,13 @@ import {
|
|
|
11
11
|
indexWithIntegrations,
|
|
12
12
|
planKnowledge,
|
|
13
13
|
writePlannedKnowledge
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-4FETKOY3.js";
|
|
15
15
|
import {
|
|
16
16
|
analyzeProject
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-44EGCEB2.js";
|
|
18
18
|
import {
|
|
19
19
|
headMovement
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-AKOI4VTD.js";
|
|
21
21
|
import {
|
|
22
22
|
KNOWLEDGE_DOCS
|
|
23
23
|
} from "./chunk-FQEGEVLY.js";
|
|
@@ -396,4 +396,4 @@ export {
|
|
|
396
396
|
HISTORY_SECTIONS,
|
|
397
397
|
staleForCheck
|
|
398
398
|
};
|
|
399
|
-
//# sourceMappingURL=chunk-
|
|
399
|
+
//# sourceMappingURL=chunk-PZPMWCXS.js.map
|
|
@@ -33,7 +33,7 @@ import {
|
|
|
33
33
|
} from "./chunk-XFN7UZCS.js";
|
|
34
34
|
import {
|
|
35
35
|
runPipeline
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-4FETKOY3.js";
|
|
37
37
|
import {
|
|
38
38
|
ADAPTERS,
|
|
39
39
|
resolveAdapters
|
|
@@ -433,4 +433,4 @@ export {
|
|
|
433
433
|
printSummary,
|
|
434
434
|
summarize
|
|
435
435
|
};
|
|
436
|
-
//# sourceMappingURL=chunk-
|
|
436
|
+
//# sourceMappingURL=chunk-R5AX7VST.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
readRecentEvents,
|
|
4
4
|
summarizeSessions
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-P4TRQMES.js";
|
|
6
6
|
import {
|
|
7
7
|
ADAPTERS,
|
|
8
8
|
applyChanges,
|
|
@@ -92,4 +92,4 @@ export {
|
|
|
92
92
|
configureAgents,
|
|
93
93
|
removeAgents
|
|
94
94
|
};
|
|
95
|
-
//# sourceMappingURL=chunk-
|
|
95
|
+
//# sourceMappingURL=chunk-RQKGT2EK.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
// src/
|
|
3
|
+
// src/core/util/which.ts
|
|
4
4
|
import { promises as fs } from "fs";
|
|
5
5
|
import path from "path";
|
|
6
6
|
async function whichExecutable(command) {
|
|
@@ -25,4 +25,4 @@ async function whichExecutable(command) {
|
|
|
25
25
|
export {
|
|
26
26
|
whichExecutable
|
|
27
27
|
};
|
|
28
|
-
//# sourceMappingURL=chunk-
|
|
28
|
+
//# sourceMappingURL=chunk-UMWX4UTK.js.map
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
redact,
|
|
7
7
|
scanText
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-WWQ5NKEC.js";
|
|
9
9
|
import {
|
|
10
10
|
KNOWLEDGE_DOCS
|
|
11
11
|
} from "./chunk-FQEGEVLY.js";
|
|
@@ -387,4 +387,4 @@ export {
|
|
|
387
387
|
buildEnrichPayload,
|
|
388
388
|
enrich
|
|
389
389
|
};
|
|
390
|
-
//# sourceMappingURL=chunk-
|
|
390
|
+
//# sourceMappingURL=chunk-WUIC65QO.js.map
|
|
@@ -174,9 +174,11 @@ function isSecretLikeName(name) {
|
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
export {
|
|
177
|
+
MAX_GENERIC_LINE,
|
|
178
|
+
SECRET_PATTERNS,
|
|
177
179
|
ephemeralFingerprint,
|
|
178
180
|
scanText,
|
|
179
181
|
redact,
|
|
180
182
|
isSecretLikeName
|
|
181
183
|
};
|
|
182
|
-
//# sourceMappingURL=chunk-
|
|
184
|
+
//# sourceMappingURL=chunk-WWQ5NKEC.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
planSnapshot,
|
|
4
4
|
planSync
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-PZPMWCXS.js";
|
|
6
6
|
|
|
7
7
|
// src/services/scheduler.ts
|
|
8
8
|
var DEFAULT_FULL_WALK_EVERY_MS = 5 * 6e4;
|
|
@@ -179,4 +179,4 @@ var AnalysisScheduler = class {
|
|
|
179
179
|
export {
|
|
180
180
|
AnalysisScheduler
|
|
181
181
|
};
|
|
182
|
-
//# sourceMappingURL=chunk-
|
|
182
|
+
//# sourceMappingURL=chunk-X7EYOAEX.js.map
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
MAX_SECRET_FINDINGS,
|
|
4
|
+
scanFilesForSecrets
|
|
5
|
+
} from "./chunk-44EGCEB2.js";
|
|
6
|
+
import {
|
|
7
|
+
walkProject
|
|
8
|
+
} from "./chunk-ELKFRTZT.js";
|
|
9
|
+
import {
|
|
10
|
+
MAX_GENERIC_LINE,
|
|
11
|
+
SECRET_PATTERNS,
|
|
12
|
+
ephemeralFingerprint
|
|
13
|
+
} from "./chunk-WWQ5NKEC.js";
|
|
14
|
+
|
|
15
|
+
// src/core/findings/finding.ts
|
|
16
|
+
import { z } from "zod";
|
|
17
|
+
var CATEGORIES = ["secret", "dependency", "sast", "iac", "license", "quality", "review", "memory"];
|
|
18
|
+
var SEVERITIES = ["critical", "high", "medium", "low", "info", "unrated"];
|
|
19
|
+
var SEVERITY_RANK = { critical: 5, high: 4, medium: 3, low: 2, info: 1, unrated: 0 };
|
|
20
|
+
var CONFIDENCES = ["high", "medium", "low"];
|
|
21
|
+
var CONFIDENCE_RANK = { high: 3, medium: 2, low: 1 };
|
|
22
|
+
var Location = z.object({
|
|
23
|
+
file: z.string(),
|
|
24
|
+
startLine: z.number().int().positive().optional(),
|
|
25
|
+
startColumn: z.number().int().positive().optional(),
|
|
26
|
+
endLine: z.number().int().positive().optional(),
|
|
27
|
+
endColumn: z.number().int().positive().optional()
|
|
28
|
+
});
|
|
29
|
+
var PackageRef = z.object({
|
|
30
|
+
ecosystem: z.string(),
|
|
31
|
+
name: z.string(),
|
|
32
|
+
version: z.string().optional(),
|
|
33
|
+
/** Manifest or lockfile the package comes from, if known. */
|
|
34
|
+
manifest: z.string().optional(),
|
|
35
|
+
advisoryIds: z.array(z.string()).default([]),
|
|
36
|
+
vulnerableRange: z.string().optional(),
|
|
37
|
+
fixedIn: z.string().optional(),
|
|
38
|
+
fixAvailable: z.boolean().optional()
|
|
39
|
+
});
|
|
40
|
+
var Finding = z.object({
|
|
41
|
+
/** Stable identity (32 hex). Never derived from a secret's value; see fingerprint.ts. */
|
|
42
|
+
fingerprint: z.string().regex(/^[a-f0-9]{32}$/),
|
|
43
|
+
/** e.g. `secret/stripe-key`, `dependency/vulnerable-package`, `review/env-file`, `sast/js/sql-concat`. */
|
|
44
|
+
ruleId: z.string().regex(/^[a-z0-9][a-z0-9._/-]{1,120}$/),
|
|
45
|
+
category: z.enum(CATEGORIES),
|
|
46
|
+
severity: z.enum(SEVERITIES),
|
|
47
|
+
confidence: z.enum(CONFIDENCES),
|
|
48
|
+
label: z.enum(["FACT", "DETECTED", "INFERRED"]),
|
|
49
|
+
/** Heuristic: "worth checking", not a confirmed problem. Rendered as "Potential …". */
|
|
50
|
+
potential: z.boolean().default(false),
|
|
51
|
+
title: z.string(),
|
|
52
|
+
message: z.string(),
|
|
53
|
+
cwe: z.array(z.string().regex(/^CWE-\d+$/)).default([]),
|
|
54
|
+
owasp: z.array(z.string()).default([]),
|
|
55
|
+
location: Location.optional(),
|
|
56
|
+
package: PackageRef.optional(),
|
|
57
|
+
/** Which engine produced it: `athena`, `npm-audit`, `semgrep`, … */
|
|
58
|
+
engine: z.object({ id: z.string(), version: z.string().optional() }),
|
|
59
|
+
/** Other engines that reported the same problem (after de-duplication). */
|
|
60
|
+
alsoReportedBy: z.array(z.string()).default([]),
|
|
61
|
+
help: z.object({ text: z.string(), url: z.string().optional() }).optional()
|
|
62
|
+
});
|
|
63
|
+
var Coverage = z.object({
|
|
64
|
+
engine: z.string(),
|
|
65
|
+
category: z.enum(CATEGORIES),
|
|
66
|
+
/** ok: ran · unavailable: not installed / nothing to scan · skipped: excluded by policy or options · failed/timeout: ran without usable output */
|
|
67
|
+
status: z.enum(["ok", "unavailable", "skipped", "failed", "timeout"]),
|
|
68
|
+
reason: z.string().optional(),
|
|
69
|
+
/** What was scanned when an engine runs per input (e.g. a requirements file). */
|
|
70
|
+
target: z.string().optional(),
|
|
71
|
+
languages: z.array(z.string()).default([]),
|
|
72
|
+
filesScanned: z.number().int().nonnegative().optional(),
|
|
73
|
+
filesSkipped: z.object({
|
|
74
|
+
tooLarge: z.number().int().nonnegative().default(0),
|
|
75
|
+
binary: z.number().int().nonnegative().default(0),
|
|
76
|
+
minified: z.number().int().nonnegative().default(0),
|
|
77
|
+
unreadable: z.number().int().nonnegative().default(0),
|
|
78
|
+
unsupported: z.number().int().nonnegative().default(0)
|
|
79
|
+
}).optional(),
|
|
80
|
+
/** Whether the engine contacted the network (e.g. an audit tool querying an advisory database). */
|
|
81
|
+
network: z.boolean().default(false),
|
|
82
|
+
durationMs: z.number().nonnegative()
|
|
83
|
+
});
|
|
84
|
+
var SCAN_SCOPES = ["all", "base", "staged", "changed"];
|
|
85
|
+
var ScanResult = z.object({
|
|
86
|
+
schemaVersion: z.literal(1),
|
|
87
|
+
scannedAt: z.string(),
|
|
88
|
+
durationMs: z.number().nonnegative(),
|
|
89
|
+
scope: z.object({ mode: z.enum(SCAN_SCOPES), base: z.string().optional(), files: z.number().int().nonnegative().optional() }),
|
|
90
|
+
findings: z.array(Finding),
|
|
91
|
+
coverage: z.array(Coverage)
|
|
92
|
+
});
|
|
93
|
+
function compareFindings(a, b) {
|
|
94
|
+
return SEVERITY_RANK[b.severity] - SEVERITY_RANK[a.severity] || CONFIDENCE_RANK[b.confidence] - CONFIDENCE_RANK[a.confidence] || a.category.localeCompare(b.category) || a.ruleId.localeCompare(b.ruleId) || (a.location?.file ?? "").localeCompare(b.location?.file ?? "") || (a.location?.startLine ?? 0) - (b.location?.startLine ?? 0) || a.fingerprint.localeCompare(b.fingerprint);
|
|
95
|
+
}
|
|
96
|
+
function dedupeFindings(findings) {
|
|
97
|
+
const byFp = /* @__PURE__ */ new Map();
|
|
98
|
+
for (const f of findings) {
|
|
99
|
+
const prev = byFp.get(f.fingerprint);
|
|
100
|
+
if (!prev) {
|
|
101
|
+
byFp.set(f.fingerprint, { ...f, alsoReportedBy: [...f.alsoReportedBy] });
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const other = f.engine.id;
|
|
105
|
+
if (other !== prev.engine.id && !prev.alsoReportedBy.includes(other)) prev.alsoReportedBy.push(other);
|
|
106
|
+
if (SEVERITY_RANK[f.severity] > SEVERITY_RANK[prev.severity]) prev.severity = f.severity;
|
|
107
|
+
if (CONFIDENCE_RANK[f.confidence] > CONFIDENCE_RANK[prev.confidence]) prev.confidence = f.confidence;
|
|
108
|
+
}
|
|
109
|
+
return [...byFp.values()].sort(compareFindings);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// src/core/scanners/secrets.ts
|
|
113
|
+
import { promises as fs } from "fs";
|
|
114
|
+
import path from "path";
|
|
115
|
+
|
|
116
|
+
// src/core/findings/fingerprint.ts
|
|
117
|
+
import crypto from "crypto";
|
|
118
|
+
var FINGERPRINT_VERSION = 1;
|
|
119
|
+
var hash = (parts) => crypto.createHash("sha256").update(parts.join("\0")).digest("hex").slice(0, 32);
|
|
120
|
+
function normalizeLine(text, mask) {
|
|
121
|
+
const masked = mask ? `${text.slice(0, mask[0])}\u27E8v\u27E9${text.slice(mask[1])}` : text;
|
|
122
|
+
return masked.replace(/\s+/g, " ").trim();
|
|
123
|
+
}
|
|
124
|
+
function codeFingerprint(input) {
|
|
125
|
+
return hash(["v1", "code", input.ruleId, input.file, normalizeLine(input.lineText, input.mask), String(input.occurrence ?? 0)]);
|
|
126
|
+
}
|
|
127
|
+
function packageFingerprint(input) {
|
|
128
|
+
return hash(["v1", "package", input.ruleId, input.ecosystem, input.name, input.manifest ?? "", input.advisoryId ?? ""]);
|
|
129
|
+
}
|
|
130
|
+
function fileFingerprint(input) {
|
|
131
|
+
return hash(["v1", "file", input.ruleId, input.file ?? "", input.key ?? ""]);
|
|
132
|
+
}
|
|
133
|
+
function occurrenceCounter() {
|
|
134
|
+
const seen = /* @__PURE__ */ new Map();
|
|
135
|
+
return (ruleId, file, normalized) => {
|
|
136
|
+
const key = `${ruleId}\0${file}\0${normalized}`;
|
|
137
|
+
const n = seen.get(key) ?? 0;
|
|
138
|
+
seen.set(key, n + 1);
|
|
139
|
+
return n;
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// src/core/scanners/secrets.ts
|
|
144
|
+
var SECRETS_ENGINE = "athena-secrets";
|
|
145
|
+
var CRITICAL = /* @__PURE__ */ new Set(["private-key", "aws-access-key-id", "aws-secret-access-key", "gcp-service-account", "azure-storage-key"]);
|
|
146
|
+
var GENERIC = /* @__PURE__ */ new Set(["generic-secret-assignment", "env-secret-assignment"]);
|
|
147
|
+
var MEDIUM_CONFIDENCE = /* @__PURE__ */ new Set(["jwt", "connection-string-credentials"]);
|
|
148
|
+
var DESCRIPTION = new Map(SECRET_PATTERNS.map((p) => [p.id, p.description]));
|
|
149
|
+
function secretSeverity(type) {
|
|
150
|
+
if (CRITICAL.has(type)) return { severity: "critical", confidence: "high", potential: false };
|
|
151
|
+
if (GENERIC.has(type)) return { severity: "medium", confidence: "low", potential: true };
|
|
152
|
+
return { severity: "high", confidence: MEDIUM_CONFIDENCE.has(type) ? "medium" : "high", potential: false };
|
|
153
|
+
}
|
|
154
|
+
function secretFinding(hit, occurrence = 0, engineId = "athena") {
|
|
155
|
+
const ruleId = `secret/${hit.type}`;
|
|
156
|
+
const { severity, confidence, potential } = secretSeverity(hit.type);
|
|
157
|
+
const description = DESCRIPTION.get(hit.type) ?? hit.type;
|
|
158
|
+
return {
|
|
159
|
+
fingerprint: codeFingerprint({ ruleId, file: hit.file, lineText: hit.lineText, mask: hit.mask, occurrence }),
|
|
160
|
+
ruleId,
|
|
161
|
+
category: "secret",
|
|
162
|
+
severity,
|
|
163
|
+
confidence,
|
|
164
|
+
label: "DETECTED",
|
|
165
|
+
potential,
|
|
166
|
+
title: potential ? `Potential hardcoded secret (${description.toLowerCase()})` : `Hardcoded ${description}`,
|
|
167
|
+
message: `${potential ? "A value that looks like a secret" : `A ${description}`} appears in ${hit.file}:${hit.line}. Athena does not store the value.`,
|
|
168
|
+
cwe: ["CWE-798"],
|
|
169
|
+
owasp: ["A07:2021"],
|
|
170
|
+
location: {
|
|
171
|
+
file: hit.file,
|
|
172
|
+
startLine: hit.line,
|
|
173
|
+
...hit.column ? { startColumn: hit.column } : {},
|
|
174
|
+
...hit.endLine ? { endLine: hit.endLine } : {},
|
|
175
|
+
...hit.endColumn ? { endColumn: hit.endColumn } : {}
|
|
176
|
+
},
|
|
177
|
+
engine: { id: engineId },
|
|
178
|
+
help: {
|
|
179
|
+
text: potential ? "Check whether this is a real credential. If it is, move it to an environment variable or secret manager and rotate it." : "Remove the value, load it from an environment variable or secret manager, and rotate the credential \u2014 assume it is compromised once committed."
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
function hitsFromMatches(file, text, matches) {
|
|
184
|
+
const lineStart = (offset) => text.lastIndexOf("\n", offset - 1) + 1;
|
|
185
|
+
return matches.map((m) => {
|
|
186
|
+
const start = lineStart(m.start);
|
|
187
|
+
let end = text.indexOf("\n", m.start);
|
|
188
|
+
if (end < 0) end = text.length;
|
|
189
|
+
let lineText = text.slice(start, end);
|
|
190
|
+
if (lineText.endsWith("\r")) lineText = lineText.slice(0, -1);
|
|
191
|
+
const maskEnd = Math.min(m.end, start + lineText.length) - start;
|
|
192
|
+
const span = text.slice(m.start, m.end);
|
|
193
|
+
const extraLines = (span.match(/\n/g) ?? []).length;
|
|
194
|
+
const lastStart = extraLines ? lineStart(m.end) : start;
|
|
195
|
+
return {
|
|
196
|
+
type: m.type,
|
|
197
|
+
file,
|
|
198
|
+
line: m.line,
|
|
199
|
+
column: m.start - start + 1,
|
|
200
|
+
endLine: m.line + extraLines,
|
|
201
|
+
endColumn: m.end - lastStart + 1,
|
|
202
|
+
lineText,
|
|
203
|
+
mask: [m.start - start, Math.max(maskEnd, m.start - start)]
|
|
204
|
+
};
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
function secretFindings(hits, engineId = "athena") {
|
|
208
|
+
const occurrence = occurrenceCounter();
|
|
209
|
+
return hits.map((h) => secretFinding(h, occurrence(`secret/${h.type}`, h.file, normalizeLine(h.lineText, h.mask)), engineId));
|
|
210
|
+
}
|
|
211
|
+
async function scanSecrets(ctx, opts = {}) {
|
|
212
|
+
const started = Date.now();
|
|
213
|
+
let files = opts.walk ?? (await walkProject(ctx.root, { config: ctx.config, signal: ctx.signal })).files;
|
|
214
|
+
if (ctx.files) {
|
|
215
|
+
const scope = new Set(ctx.files);
|
|
216
|
+
files = files.filter((f) => scope.has(f.path));
|
|
217
|
+
}
|
|
218
|
+
const hits = [];
|
|
219
|
+
const read = async (rel) => fs.readFile(path.join(ctx.root, rel), "utf8").catch(() => null);
|
|
220
|
+
const r = await scanFilesForSecrets(files, read, {
|
|
221
|
+
fingerprint: ephemeralFingerprint,
|
|
222
|
+
signal: ctx.signal,
|
|
223
|
+
onFile: (file, text, matches) => hits.push(...hitsFromMatches(file, text, matches))
|
|
224
|
+
});
|
|
225
|
+
const notes = [];
|
|
226
|
+
if (r.truncated) notes.push(`stopped after ${MAX_SECRET_FINDINGS} findings; remaining files were not scanned`);
|
|
227
|
+
if (r.skippedLongLines) notes.push(`generic keyword patterns not applied to ${r.skippedLongLines} line(s) longer than ${MAX_GENERIC_LINE} characters`);
|
|
228
|
+
if (r.files.excluded) notes.push(`${r.files.excluded} lockfile/snapshot/SVG file(s) not scanned`);
|
|
229
|
+
const coverage = {
|
|
230
|
+
engine: SECRETS_ENGINE,
|
|
231
|
+
category: "secret",
|
|
232
|
+
status: "ok",
|
|
233
|
+
...notes.length ? { reason: notes.join("; ") } : {},
|
|
234
|
+
filesScanned: r.files.scanned,
|
|
235
|
+
filesSkipped: { tooLarge: r.files.tooLarge, binary: r.files.binary, minified: r.files.minified, unreadable: r.files.unreadable, unsupported: r.files.excluded },
|
|
236
|
+
network: false,
|
|
237
|
+
durationMs: Date.now() - started
|
|
238
|
+
};
|
|
239
|
+
return {
|
|
240
|
+
findings: secretFindings(hits),
|
|
241
|
+
coverage: [coverage],
|
|
242
|
+
summary: { count: hits.length, files: [...new Set(hits.map((h) => h.file))], skippedLongLines: r.skippedLongLines, truncated: r.truncated }
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
var secretsScanner = {
|
|
246
|
+
id: SECRETS_ENGINE,
|
|
247
|
+
category: "secret",
|
|
248
|
+
title: "Hardcoded secrets",
|
|
249
|
+
async run(ctx) {
|
|
250
|
+
const { findings, coverage } = await scanSecrets(ctx);
|
|
251
|
+
return { findings, coverage };
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
export {
|
|
256
|
+
FINGERPRINT_VERSION,
|
|
257
|
+
normalizeLine,
|
|
258
|
+
codeFingerprint,
|
|
259
|
+
packageFingerprint,
|
|
260
|
+
fileFingerprint,
|
|
261
|
+
occurrenceCounter,
|
|
262
|
+
SECRETS_ENGINE,
|
|
263
|
+
hitsFromMatches,
|
|
264
|
+
secretFindings,
|
|
265
|
+
scanSecrets,
|
|
266
|
+
secretsScanner,
|
|
267
|
+
CATEGORIES,
|
|
268
|
+
SEVERITIES,
|
|
269
|
+
SEVERITY_RANK,
|
|
270
|
+
CONFIDENCES,
|
|
271
|
+
CONFIDENCE_RANK,
|
|
272
|
+
Finding,
|
|
273
|
+
Coverage,
|
|
274
|
+
ScanResult,
|
|
275
|
+
compareFindings,
|
|
276
|
+
dedupeFindings
|
|
277
|
+
};
|
|
278
|
+
//# sourceMappingURL=chunk-Y6SDMZET.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
cleanCommand,
|
|
4
4
|
confirm
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-DH5AGULY.js";
|
|
6
6
|
import "./chunk-Z6QWMJLK.js";
|
|
7
7
|
import "./chunk-XFN7UZCS.js";
|
|
8
8
|
import "./chunk-KBO7XRBW.js";
|
|
@@ -20,4 +20,4 @@ export {
|
|
|
20
20
|
cleanCommand,
|
|
21
21
|
confirm
|
|
22
22
|
};
|
|
23
|
-
//# sourceMappingURL=clean-
|
|
23
|
+
//# sourceMappingURL=clean-LQOG56AM.js.map
|
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/cli/index.ts
|
|
4
4
|
async function runEvent(args) {
|
|
5
|
-
const { parseEventArgs, eventCommand } = await import("./event-
|
|
5
|
+
const { parseEventArgs, eventCommand } = await import("./event-6YW6TGFI.js");
|
|
6
6
|
const opts = parseEventArgs(args);
|
|
7
7
|
if (!opts) return false;
|
|
8
8
|
let signalled = false;
|
|
@@ -21,7 +21,7 @@ function eventFailed(err) {
|
|
|
21
21
|
return true;
|
|
22
22
|
}
|
|
23
23
|
if (process.argv[2] !== "event" || !await runEvent(process.argv.slice(3)).catch(eventFailed)) {
|
|
24
|
-
const { main } = await import("./program-
|
|
24
|
+
const { main } = await import("./program-DCP526LU.js");
|
|
25
25
|
await main();
|
|
26
26
|
}
|
|
27
27
|
//# sourceMappingURL=cli.js.map
|
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
getRelevantContext,
|
|
4
4
|
graphSummary,
|
|
5
5
|
refreshGraph
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-GYQG4Q2N.js";
|
|
7
7
|
import {
|
|
8
8
|
formatContext
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-F65QINMR.js";
|
|
10
10
|
import "./chunk-3IS2X2Z7.js";
|
|
11
11
|
import {
|
|
12
12
|
bullet,
|
|
@@ -24,17 +24,17 @@ import {
|
|
|
24
24
|
requireProjectRoot
|
|
25
25
|
} from "./chunk-XFN7UZCS.js";
|
|
26
26
|
import "./chunk-KBO7XRBW.js";
|
|
27
|
-
import "./chunk-
|
|
28
|
-
import "./chunk-
|
|
29
|
-
import "./chunk-ELKFRTZT.js";
|
|
27
|
+
import "./chunk-GU3ZX2J7.js";
|
|
28
|
+
import "./chunk-44EGCEB2.js";
|
|
30
29
|
import "./chunk-PVCIGUIT.js";
|
|
31
|
-
import "./chunk-
|
|
30
|
+
import "./chunk-ELKFRTZT.js";
|
|
31
|
+
import "./chunk-AKOI4VTD.js";
|
|
32
32
|
import {
|
|
33
33
|
loadGraph,
|
|
34
34
|
neighbors
|
|
35
35
|
} from "./chunk-SVTEJYMS.js";
|
|
36
36
|
import "./chunk-QCC4VJUH.js";
|
|
37
|
-
import "./chunk-
|
|
37
|
+
import "./chunk-WWQ5NKEC.js";
|
|
38
38
|
import "./chunk-673EPYYH.js";
|
|
39
39
|
import "./chunk-FQEGEVLY.js";
|
|
40
40
|
import "./chunk-2DY4PUR4.js";
|
|
@@ -158,4 +158,4 @@ export {
|
|
|
158
158
|
contextCommand,
|
|
159
159
|
graphCommand
|
|
160
160
|
};
|
|
161
|
-
//# sourceMappingURL=context-
|
|
161
|
+
//# sourceMappingURL=context-G5YHY3L2.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
runDoctor
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-L2EHJCH4.js";
|
|
5
|
+
import "./chunk-WUIC65QO.js";
|
|
6
|
+
import "./chunk-UMWX4UTK.js";
|
|
7
|
+
import "./chunk-P4TRQMES.js";
|
|
8
8
|
import "./chunk-3IS2X2Z7.js";
|
|
9
9
|
import {
|
|
10
10
|
c,
|
|
@@ -21,8 +21,8 @@ import {
|
|
|
21
21
|
import "./chunk-KBO7XRBW.js";
|
|
22
22
|
import "./chunk-2R6PXY6Z.js";
|
|
23
23
|
import "./chunk-PVCIGUIT.js";
|
|
24
|
-
import "./chunk-
|
|
25
|
-
import "./chunk-
|
|
24
|
+
import "./chunk-AKOI4VTD.js";
|
|
25
|
+
import "./chunk-WWQ5NKEC.js";
|
|
26
26
|
import "./chunk-YRIS7ZS6.js";
|
|
27
27
|
import "./chunk-GHFRQAYT.js";
|
|
28
28
|
import "./chunk-INT3IGMQ.js";
|
|
@@ -39,7 +39,7 @@ async function doctorCommand(opts) {
|
|
|
39
39
|
const cwd = await resolveCwd(opts);
|
|
40
40
|
const { checks, root } = await runDoctor(cwd);
|
|
41
41
|
if (root) {
|
|
42
|
-
const m = await (await import("./memory-
|
|
42
|
+
const m = await (await import("./memory-XBZCYQLW.js")).memorySummary(root);
|
|
43
43
|
if (m?.total) {
|
|
44
44
|
const pending = [m.unreviewed ? `${m.unreviewed} unreviewed` : "", m.stale ? `${m.stale} stale` : ""].filter(Boolean);
|
|
45
45
|
checks.push({ area: "Memory", level: "info", message: `${m.total} project memory ${m.total === 1 ? "entry" : "entries"}${pending.length ? ` (${pending.join(", ")})` : ""}`, hint: pending.length ? "Review with `athena memory review` and `athena memory stale`." : void 0 });
|
|
@@ -66,4 +66,4 @@ async function doctorCommand(opts) {
|
|
|
66
66
|
export {
|
|
67
67
|
doctorCommand
|
|
68
68
|
};
|
|
69
|
-
//# sourceMappingURL=doctor-
|
|
69
|
+
//# sourceMappingURL=doctor-L34QJ7WR.js.map
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
appendEvent
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-P4TRQMES.js";
|
|
5
5
|
import {
|
|
6
6
|
findProjectRoot
|
|
7
7
|
} from "./chunk-KBO7XRBW.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-WWQ5NKEC.js";
|
|
9
9
|
import {
|
|
10
10
|
normalizeHookEvent
|
|
11
11
|
} from "./chunk-INT3IGMQ.js";
|
|
@@ -98,4 +98,4 @@ export {
|
|
|
98
98
|
eventCommand,
|
|
99
99
|
parseEventArgs
|
|
100
100
|
};
|
|
101
|
-
//# sourceMappingURL=event-
|
|
101
|
+
//# sourceMappingURL=event-6YW6TGFI.js.map
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
import "./chunk-KBO7XRBW.js";
|
|
16
16
|
import {
|
|
17
17
|
git
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-AKOI4VTD.js";
|
|
19
19
|
import {
|
|
20
20
|
hookCommand
|
|
21
21
|
} from "./chunk-GHFRQAYT.js";
|
|
@@ -249,4 +249,4 @@ export {
|
|
|
249
249
|
gitHookStatusCommand,
|
|
250
250
|
gitHookUninstallCommand
|
|
251
251
|
};
|
|
252
|
-
//# sourceMappingURL=git-hook-
|
|
252
|
+
//# sourceMappingURL=git-hook-Y7Y262F7.js.map
|
|
@@ -5,19 +5,19 @@ import {
|
|
|
5
5
|
printSummary,
|
|
6
6
|
runWithProgress,
|
|
7
7
|
summarize
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-R5AX7VST.js";
|
|
9
9
|
import "./chunk-SHKXELUX.js";
|
|
10
10
|
import "./chunk-Z6QWMJLK.js";
|
|
11
11
|
import "./chunk-XFN7UZCS.js";
|
|
12
12
|
import "./chunk-KBO7XRBW.js";
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-MPG3IEGB.js";
|
|
15
|
-
import "./chunk-ELKFRTZT.js";
|
|
13
|
+
import "./chunk-4FETKOY3.js";
|
|
16
14
|
import "./chunk-2R6PXY6Z.js";
|
|
15
|
+
import "./chunk-44EGCEB2.js";
|
|
17
16
|
import "./chunk-PVCIGUIT.js";
|
|
18
|
-
import "./chunk-
|
|
17
|
+
import "./chunk-ELKFRTZT.js";
|
|
18
|
+
import "./chunk-AKOI4VTD.js";
|
|
19
19
|
import "./chunk-QCC4VJUH.js";
|
|
20
|
-
import "./chunk-
|
|
20
|
+
import "./chunk-WWQ5NKEC.js";
|
|
21
21
|
import "./chunk-YRIS7ZS6.js";
|
|
22
22
|
import "./chunk-GHFRQAYT.js";
|
|
23
23
|
import "./chunk-INT3IGMQ.js";
|
|
@@ -35,4 +35,4 @@ export {
|
|
|
35
35
|
runWithProgress,
|
|
36
36
|
summarize
|
|
37
37
|
};
|
|
38
|
-
//# sourceMappingURL=init-
|
|
38
|
+
//# sourceMappingURL=init-427QR5AS.js.map
|