codegate-ai 0.8.0 → 0.9.1
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 +48 -15
- package/dist/cli.js +41 -7
- package/dist/commands/scan-command.d.ts +6 -1
- package/dist/commands/scan-command.js +1 -1
- package/dist/commands/scan-content-command.js +5 -1
- package/dist/config/inline-ignore.d.ts +11 -0
- package/dist/config/inline-ignore.js +57 -0
- package/dist/config/suppression-policy.d.ts +8 -0
- package/dist/config/suppression-policy.js +66 -1
- package/dist/config.d.ts +19 -1
- package/dist/config.js +160 -1
- package/dist/layer2-static/action/parser.d.ts +3 -0
- package/dist/layer2-static/action/parser.js +165 -0
- package/dist/layer2-static/action/types.d.ts +39 -0
- package/dist/layer2-static/action/types.js +1 -0
- package/dist/layer2-static/advisories/cache.d.ts +6 -0
- package/dist/layer2-static/advisories/cache.js +44 -0
- package/dist/layer2-static/advisories/cache.ts +62 -0
- package/dist/layer2-static/advisories/gha-advisory-client.d.ts +7 -0
- package/dist/layer2-static/advisories/gha-advisory-client.js +4 -0
- package/dist/layer2-static/advisories/gha-advisory-client.ts +13 -0
- package/dist/layer2-static/advisories/gha-known-vulnerable-actions.json +4 -0
- package/dist/layer2-static/audits/registry.d.ts +3 -0
- package/dist/layer2-static/audits/registry.js +29 -0
- package/dist/layer2-static/audits/types.d.ts +12 -0
- package/dist/layer2-static/audits/types.js +1 -0
- package/dist/layer2-static/dependabot/parser.d.ts +3 -0
- package/dist/layer2-static/dependabot/parser.js +189 -0
- package/dist/layer2-static/dependabot/types.d.ts +50 -0
- package/dist/layer2-static/dependabot/types.js +1 -0
- package/dist/layer2-static/detectors/dependabot-cooldown.d.ts +7 -0
- package/dist/layer2-static/detectors/dependabot-cooldown.js +54 -0
- package/dist/layer2-static/detectors/dependabot-execution.d.ts +7 -0
- package/dist/layer2-static/detectors/dependabot-execution.js +68 -0
- package/dist/layer2-static/detectors/workflow-anonymous-definition.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-anonymous-definition.js +48 -0
- package/dist/layer2-static/detectors/workflow-archived-uses.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-archived-uses.js +147 -0
- package/dist/layer2-static/detectors/workflow-artipacked.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-artipacked.js +62 -0
- package/dist/layer2-static/detectors/workflow-bot-conditions.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-bot-conditions.js +108 -0
- package/dist/layer2-static/detectors/workflow-cache-poisoning.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-cache-poisoning.js +67 -0
- package/dist/layer2-static/detectors/workflow-concurrency-limits.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-concurrency-limits.js +76 -0
- package/dist/layer2-static/detectors/workflow-dangerous-triggers.d.ts +6 -0
- package/dist/layer2-static/detectors/workflow-dangerous-triggers.js +38 -0
- package/dist/layer2-static/detectors/workflow-excessive-permissions.d.ts +6 -0
- package/dist/layer2-static/detectors/workflow-excessive-permissions.js +65 -0
- package/dist/layer2-static/detectors/workflow-forbidden-uses.d.ts +12 -0
- package/dist/layer2-static/detectors/workflow-forbidden-uses.js +148 -0
- package/dist/layer2-static/detectors/workflow-github-env.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-github-env.js +49 -0
- package/dist/layer2-static/detectors/workflow-hardcoded-container-credentials.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-hardcoded-container-credentials.js +90 -0
- package/dist/layer2-static/detectors/workflow-impostor-commit.d.ts +9 -0
- package/dist/layer2-static/detectors/workflow-impostor-commit.js +127 -0
- package/dist/layer2-static/detectors/workflow-insecure-commands.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-insecure-commands.js +72 -0
- package/dist/layer2-static/detectors/workflow-known-vuln-action.d.ts +8 -0
- package/dist/layer2-static/detectors/workflow-known-vuln-action.js +70 -0
- package/dist/layer2-static/detectors/workflow-misfeature.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-misfeature.js +101 -0
- package/dist/layer2-static/detectors/workflow-obfuscation.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-obfuscation.js +79 -0
- package/dist/layer2-static/detectors/workflow-overprovisioned-secrets.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-overprovisioned-secrets.js +81 -0
- package/dist/layer2-static/detectors/workflow-ref-confusion.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-ref-confusion.js +69 -0
- package/dist/layer2-static/detectors/workflow-ref-version-mismatch.d.ts +9 -0
- package/dist/layer2-static/detectors/workflow-ref-version-mismatch.js +179 -0
- package/dist/layer2-static/detectors/workflow-secrets-inherit.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-secrets-inherit.js +59 -0
- package/dist/layer2-static/detectors/workflow-secrets-outside-env.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-secrets-outside-env.js +99 -0
- package/dist/layer2-static/detectors/workflow-self-hosted-runner.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-self-hosted-runner.js +67 -0
- package/dist/layer2-static/detectors/workflow-stale-action-refs.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-stale-action-refs.js +178 -0
- package/dist/layer2-static/detectors/workflow-superfluous-actions.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-superfluous-actions.js +70 -0
- package/dist/layer2-static/detectors/workflow-template-injection.d.ts +6 -0
- package/dist/layer2-static/detectors/workflow-template-injection.js +94 -0
- package/dist/layer2-static/detectors/workflow-undocumented-permissions.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-undocumented-permissions.js +101 -0
- package/dist/layer2-static/detectors/workflow-unpinned-images.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-unpinned-images.js +108 -0
- package/dist/layer2-static/detectors/workflow-unpinned-uses.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-unpinned-uses.js +60 -0
- package/dist/layer2-static/detectors/workflow-unredacted-secrets.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-unredacted-secrets.js +92 -0
- package/dist/layer2-static/detectors/workflow-unsound-condition.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-unsound-condition.js +90 -0
- package/dist/layer2-static/detectors/workflow-unsound-contains.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-unsound-contains.js +88 -0
- package/dist/layer2-static/detectors/workflow-use-trusted-publishing.d.ts +7 -0
- package/dist/layer2-static/detectors/workflow-use-trusted-publishing.js +66 -0
- package/dist/layer2-static/engine.d.ts +9 -1
- package/dist/layer2-static/engine.js +490 -50
- package/dist/layer2-static/github/cache.d.ts +8 -0
- package/dist/layer2-static/github/cache.js +41 -0
- package/dist/layer2-static/github/client.d.ts +17 -0
- package/dist/layer2-static/github/client.js +43 -0
- package/dist/layer2-static/rules/claude-code.json +16 -0
- package/dist/layer2-static/rules/codex.json +16 -0
- package/dist/layer2-static/rules/common.json +15 -0
- package/dist/layer2-static/rules/copilot.json +15 -0
- package/dist/layer2-static/rules/cursor.json +15 -0
- package/dist/layer2-static/rules/opencode.json +15 -0
- package/dist/layer2-static/workflow/injection-sinks.json +5 -0
- package/dist/layer2-static/workflow/parser.d.ts +3 -0
- package/dist/layer2-static/workflow/parser.js +88 -0
- package/dist/layer2-static/workflow/types.d.ts +15 -0
- package/dist/layer2-static/workflow/types.js +1 -0
- package/dist/pipeline.d.ts +1 -1
- package/dist/pipeline.js +3 -3
- package/dist/reporter/sarif.js +23 -5
- package/dist/reporter/terminal.js +12 -0
- package/dist/scan.d.ts +7 -1
- package/dist/scan.js +154 -40
- package/dist/types/finding.d.ts +1 -1
- package/dist/types/finding.js +5 -0
- package/package.json +1 -1
package/dist/scan.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
|
-
import { join, relative, resolve, sep } from "node:path";
|
|
3
|
+
import { basename, join, relative, resolve, sep } from "node:path";
|
|
4
4
|
import { collectLocalTextAnalysisTargets, } from "./layer3-dynamic/local-text-analysis.js";
|
|
5
5
|
import { runStaticPipeline } from "./pipeline.js";
|
|
6
6
|
import { applyReportSummary } from "./report-summary.js";
|
|
@@ -9,11 +9,28 @@ import { loadKnowledgeBase, } from "./layer1-discovery/knowledge-base.js";
|
|
|
9
9
|
import { detectTools } from "./layer1-discovery/tool-detector.js";
|
|
10
10
|
import { walkProjectTree } from "./layer1-discovery/file-walker.js";
|
|
11
11
|
import { evaluateScanStateSnapshots, extractMcpServerSnapshots, loadScanState, saveScanState, } from "./layer2-static/state/scan-state.js";
|
|
12
|
+
import { applyInlineIgnoreDirectives, collectInlineIgnoreDirectives, } from "./config/inline-ignore.js";
|
|
13
|
+
import { isGitHubDependabotPath } from "./layer2-static/dependabot/parser.js";
|
|
12
14
|
const MCP_SERVER_CONTAINER_KEYS = ["mcpServers", "mcp_servers", "context_servers"];
|
|
13
15
|
const REMOTE_MCP_SERVER_ARRAY_KEYS = ["remoteMCPServers", "remote_mcp_servers"];
|
|
14
16
|
const USER_SCOPE_WILDCARD_MAX_DEPTH = 6;
|
|
15
17
|
const USER_SCOPE_WILDCARD_MAX_FILES = 500;
|
|
16
18
|
const INFERRED_ARTIFACT_RULES = [
|
|
19
|
+
{
|
|
20
|
+
pattern: /(?:^|\/)\.github\/workflows\/[^/]+\.ya?ml$/iu,
|
|
21
|
+
format: "yaml",
|
|
22
|
+
tool: "github-actions",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
pattern: /(?:^|\/)\.github\/dependabot\.ya?ml$/iu,
|
|
26
|
+
format: "yaml",
|
|
27
|
+
tool: "dependabot",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
pattern: /(?:^|\/)action\.ya?ml$/iu,
|
|
31
|
+
format: "yaml",
|
|
32
|
+
tool: "github-actions",
|
|
33
|
+
},
|
|
17
34
|
{ pattern: /(?:^|\/)agents\.md$/iu, format: "markdown", tool: "claude-code" },
|
|
18
35
|
{ pattern: /(?:^|\/)claude\.md$/iu, format: "markdown", tool: "claude-code" },
|
|
19
36
|
{ pattern: /(?:^|\/)codex\.md$/iu, format: "markdown", tool: "codex-cli" },
|
|
@@ -37,6 +54,12 @@ function wildcardToRegex(pattern) {
|
|
|
37
54
|
function normalizePathForMatch(path) {
|
|
38
55
|
return path.split(sep).join("/");
|
|
39
56
|
}
|
|
57
|
+
function normalizeCollectionKinds(input) {
|
|
58
|
+
if (!input || input.length === 0) {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
return new Set(input);
|
|
62
|
+
}
|
|
40
63
|
function normalizeUserScopePattern(pattern) {
|
|
41
64
|
return normalizePathForMatch(pattern).replace(/^~\//u, "").replace(/^\/+/u, "");
|
|
42
65
|
}
|
|
@@ -63,6 +86,32 @@ function gatherCandidatePatterns(kb) {
|
|
|
63
86
|
}
|
|
64
87
|
return candidates;
|
|
65
88
|
}
|
|
89
|
+
function isWorkflowCollectionCandidate(reportPath) {
|
|
90
|
+
return /(?:^|\/)\.github\/workflows\/[^/]+\.ya?ml$/iu.test(normalizePathForMatch(reportPath));
|
|
91
|
+
}
|
|
92
|
+
function isActionCollectionCandidate(reportPath) {
|
|
93
|
+
const fileName = basename(normalizePathForMatch(reportPath)).toLowerCase();
|
|
94
|
+
return fileName === "action.yml" || fileName === "action.yaml";
|
|
95
|
+
}
|
|
96
|
+
function inferCollectionKind(reportPath) {
|
|
97
|
+
if (isWorkflowCollectionCandidate(reportPath)) {
|
|
98
|
+
return "workflows";
|
|
99
|
+
}
|
|
100
|
+
if (isActionCollectionCandidate(reportPath)) {
|
|
101
|
+
return "actions";
|
|
102
|
+
}
|
|
103
|
+
if (isGitHubDependabotPath(reportPath)) {
|
|
104
|
+
return "dependabot";
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
function matchesCollectionKinds(reportPath, collectKinds) {
|
|
109
|
+
if (!collectKinds) {
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
const kind = inferCollectionKind(reportPath);
|
|
113
|
+
return kind !== null && collectKinds.has(kind);
|
|
114
|
+
}
|
|
66
115
|
function isRegularFile(path) {
|
|
67
116
|
try {
|
|
68
117
|
return statSync(path).isFile();
|
|
@@ -149,6 +198,11 @@ function collectUserScopeWildcardMatches(homeDir, pattern) {
|
|
|
149
198
|
}
|
|
150
199
|
function collectSelectedCandidates(absoluteTarget, walkedFiles, patterns, options) {
|
|
151
200
|
const selected = new Map();
|
|
201
|
+
const includeAll = options.collectModes.has("all");
|
|
202
|
+
const includeProject = includeAll || options.collectModes.has("default") || options.collectModes.has("project");
|
|
203
|
+
const includeUser = includeAll ||
|
|
204
|
+
options.collectModes.has("user") ||
|
|
205
|
+
(options.collectModes.has("default") && options.includeUserScope);
|
|
152
206
|
const filesByRelativePath = walkedFiles
|
|
153
207
|
.map((filePath) => ({
|
|
154
208
|
absolutePath: filePath,
|
|
@@ -156,6 +210,9 @@ function collectSelectedCandidates(absoluteTarget, walkedFiles, patterns, option
|
|
|
156
210
|
}))
|
|
157
211
|
.filter((entry) => !entry.relativePath.startsWith(".."));
|
|
158
212
|
for (const file of filesByRelativePath) {
|
|
213
|
+
if (!includeProject) {
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
159
216
|
for (const candidate of patterns) {
|
|
160
217
|
if (candidate.scope !== "project") {
|
|
161
218
|
continue;
|
|
@@ -163,6 +220,9 @@ function collectSelectedCandidates(absoluteTarget, walkedFiles, patterns, option
|
|
|
163
220
|
if (!wildcardToRegex(candidate.pattern).test(file.relativePath)) {
|
|
164
221
|
continue;
|
|
165
222
|
}
|
|
223
|
+
if (!matchesCollectionKinds(file.relativePath, options.collectKinds)) {
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
166
226
|
if (!selected.has(file.relativePath)) {
|
|
167
227
|
selected.set(file.relativePath, {
|
|
168
228
|
reportPath: file.relativePath,
|
|
@@ -173,8 +233,14 @@ function collectSelectedCandidates(absoluteTarget, walkedFiles, patterns, option
|
|
|
173
233
|
}
|
|
174
234
|
}
|
|
175
235
|
}
|
|
176
|
-
if (!
|
|
236
|
+
if (!includeUser) {
|
|
177
237
|
for (const file of filesByRelativePath) {
|
|
238
|
+
if (!includeProject) {
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
if (!matchesCollectionKinds(file.relativePath, options.collectKinds)) {
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
178
244
|
if (selected.has(file.relativePath)) {
|
|
179
245
|
continue;
|
|
180
246
|
}
|
|
@@ -186,40 +252,54 @@ function collectSelectedCandidates(absoluteTarget, walkedFiles, patterns, option
|
|
|
186
252
|
}
|
|
187
253
|
return Array.from(selected.values());
|
|
188
254
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
255
|
+
if (includeUser) {
|
|
256
|
+
for (const candidate of patterns) {
|
|
257
|
+
if (candidate.scope !== "user") {
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
const userPattern = normalizeUserScopePattern(candidate.pattern);
|
|
261
|
+
if (userPattern.includes("*")) {
|
|
262
|
+
for (const match of collectUserScopeWildcardMatches(options.homeDir, userPattern)) {
|
|
263
|
+
const reportPath = toUserReportPath(match.relativePath);
|
|
264
|
+
if (!matchesCollectionKinds(reportPath, options.collectKinds)) {
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
if (!selected.has(reportPath)) {
|
|
268
|
+
selected.set(reportPath, {
|
|
269
|
+
reportPath,
|
|
270
|
+
absolutePath: match.absolutePath,
|
|
271
|
+
format: candidate.format,
|
|
272
|
+
tool: candidate.tool,
|
|
273
|
+
});
|
|
274
|
+
}
|
|
204
275
|
}
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
const absolutePath = resolve(options.homeDir, userPattern);
|
|
279
|
+
if (!existsSync(absolutePath) || !isRegularFile(absolutePath)) {
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
const reportPath = toUserReportPath(userPattern);
|
|
283
|
+
if (!matchesCollectionKinds(reportPath, options.collectKinds)) {
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
if (!selected.has(reportPath)) {
|
|
287
|
+
selected.set(reportPath, {
|
|
288
|
+
reportPath,
|
|
289
|
+
absolutePath,
|
|
290
|
+
format: candidate.format,
|
|
291
|
+
tool: candidate.tool,
|
|
292
|
+
});
|
|
205
293
|
}
|
|
206
|
-
continue;
|
|
207
294
|
}
|
|
208
|
-
|
|
209
|
-
|
|
295
|
+
}
|
|
296
|
+
for (const file of filesByRelativePath) {
|
|
297
|
+
if (!includeProject && !includeAll) {
|
|
210
298
|
continue;
|
|
211
299
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
selected.set(reportPath, {
|
|
215
|
-
reportPath,
|
|
216
|
-
absolutePath,
|
|
217
|
-
format: candidate.format,
|
|
218
|
-
tool: candidate.tool,
|
|
219
|
-
});
|
|
300
|
+
if (!matchesCollectionKinds(file.relativePath, options.collectKinds)) {
|
|
301
|
+
continue;
|
|
220
302
|
}
|
|
221
|
-
}
|
|
222
|
-
for (const file of filesByRelativePath) {
|
|
223
303
|
if (selected.has(file.relativePath)) {
|
|
224
304
|
continue;
|
|
225
305
|
}
|
|
@@ -231,7 +311,17 @@ function collectSelectedCandidates(absoluteTarget, walkedFiles, patterns, option
|
|
|
231
311
|
}
|
|
232
312
|
return Array.from(selected.values());
|
|
233
313
|
}
|
|
234
|
-
function
|
|
314
|
+
function normalizeCollectionModes(input) {
|
|
315
|
+
const normalized = new Set();
|
|
316
|
+
for (const mode of input ?? []) {
|
|
317
|
+
normalized.add(mode);
|
|
318
|
+
}
|
|
319
|
+
if (normalized.size === 0) {
|
|
320
|
+
normalized.add("default");
|
|
321
|
+
}
|
|
322
|
+
return normalized;
|
|
323
|
+
}
|
|
324
|
+
function mergeExplicitCandidates(selected, explicitCandidates, collectKinds) {
|
|
235
325
|
if (!explicitCandidates || explicitCandidates.length === 0) {
|
|
236
326
|
return selected;
|
|
237
327
|
}
|
|
@@ -240,6 +330,9 @@ function mergeExplicitCandidates(selected, explicitCandidates) {
|
|
|
240
330
|
merged.set(candidate.reportPath, candidate);
|
|
241
331
|
}
|
|
242
332
|
for (const candidate of explicitCandidates) {
|
|
333
|
+
if (!matchesCollectionKinds(candidate.reportPath, collectKinds)) {
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
243
336
|
merged.set(candidate.reportPath, candidate);
|
|
244
337
|
}
|
|
245
338
|
return Array.from(merged.values());
|
|
@@ -272,11 +365,11 @@ function ensureParsedCandidates(context) {
|
|
|
272
365
|
}
|
|
273
366
|
return context.parsedCandidates;
|
|
274
367
|
}
|
|
275
|
-
function makeParseErrorFinding(filePath, tool, message) {
|
|
368
|
+
function makeParseErrorFinding(filePath, tool, message, strictCollection) {
|
|
276
369
|
return {
|
|
277
370
|
rule_id: "parse-error",
|
|
278
371
|
finding_id: `PARSE_ERROR-${filePath}`,
|
|
279
|
-
severity: "LOW",
|
|
372
|
+
severity: strictCollection ? "HIGH" : "LOW",
|
|
280
373
|
category: "PARSE_ERROR",
|
|
281
374
|
layer: "L1",
|
|
282
375
|
file_path: filePath,
|
|
@@ -455,6 +548,8 @@ export function discoverDeepScanResources(scanTarget, kbInput, options = {}) {
|
|
|
455
548
|
const context = createScanDiscoveryContext(scanTarget, kbInput, {
|
|
456
549
|
includeUserScope: options.includeUserScope,
|
|
457
550
|
homeDir: options.homeDir,
|
|
551
|
+
collectModes: options.collectModes,
|
|
552
|
+
collectKinds: options.collectKinds,
|
|
458
553
|
parseSelected: true,
|
|
459
554
|
});
|
|
460
555
|
return discoverDeepScanResourcesFromContext(context);
|
|
@@ -468,10 +563,17 @@ export function createScanDiscoveryContext(scanTarget, kbInput, options = {}) {
|
|
|
468
563
|
const kb = kbInput ?? loadKnowledgeBase();
|
|
469
564
|
const patterns = gatherCandidatePatterns(kb);
|
|
470
565
|
const walked = walkProjectTree(absoluteTarget);
|
|
471
|
-
const
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
566
|
+
const collectModes = normalizeCollectionModes(options.collectModes);
|
|
567
|
+
const collectKinds = normalizeCollectionKinds(options.collectKinds);
|
|
568
|
+
const explicitOnly = collectModes.size === 1 && collectModes.has("explicit");
|
|
569
|
+
const selected = mergeExplicitCandidates(explicitOnly
|
|
570
|
+
? []
|
|
571
|
+
: collectSelectedCandidates(absoluteTarget, walked.files, patterns, {
|
|
572
|
+
includeUserScope: options.includeUserScope === true,
|
|
573
|
+
homeDir: resolve(options.homeDir ?? homedir()),
|
|
574
|
+
collectModes,
|
|
575
|
+
collectKinds,
|
|
576
|
+
}), options.explicitCandidates, collectKinds);
|
|
475
577
|
return {
|
|
476
578
|
absoluteTarget,
|
|
477
579
|
kb,
|
|
@@ -494,6 +596,8 @@ export function collectScanSurface(scanTarget, kbInput, options = {}) {
|
|
|
494
596
|
const context = createScanDiscoveryContext(scanTarget, kbInput, {
|
|
495
597
|
includeUserScope: options.includeUserScope === true,
|
|
496
598
|
homeDir: options.homeDir,
|
|
599
|
+
collectModes: options.collectModes,
|
|
600
|
+
collectKinds: options.collectKinds,
|
|
497
601
|
});
|
|
498
602
|
const surface = new Set(context.walked.files);
|
|
499
603
|
for (const item of context.selected) {
|
|
@@ -513,6 +617,8 @@ export async function runScanEngine(input) {
|
|
|
513
617
|
const context = input.discoveryContext ??
|
|
514
618
|
createScanDiscoveryContext(input.scanTarget, input.kb, {
|
|
515
619
|
includeUserScope: input.config.scan_user_scope === true,
|
|
620
|
+
collectModes: input.config.scan_collection_modes,
|
|
621
|
+
collectKinds: input.config.scan_collection_kinds,
|
|
516
622
|
homeDir: input.homeDir,
|
|
517
623
|
parseSelected: true,
|
|
518
624
|
});
|
|
@@ -522,7 +628,7 @@ export async function runScanEngine(input) {
|
|
|
522
628
|
const staticFiles = [];
|
|
523
629
|
for (const item of ensureParsedCandidates(context)) {
|
|
524
630
|
if (!item.parsed.ok) {
|
|
525
|
-
parseErrors.push(makeParseErrorFinding(item.reportPath, item.tool, item.parsed.error));
|
|
631
|
+
parseErrors.push(makeParseErrorFinding(item.reportPath, item.tool, item.parsed.error, input.config.strict_collection === true));
|
|
526
632
|
continue;
|
|
527
633
|
}
|
|
528
634
|
staticFiles.push({
|
|
@@ -548,7 +654,7 @@ export async function runScanEngine(input) {
|
|
|
548
654
|
executable: (mode & 0o111) !== 0,
|
|
549
655
|
};
|
|
550
656
|
});
|
|
551
|
-
const report = runStaticPipeline({
|
|
657
|
+
const report = await runStaticPipeline({
|
|
552
658
|
version: input.version,
|
|
553
659
|
kbVersion: kb.schemaVersion,
|
|
554
660
|
scanTarget: input.scanTarget,
|
|
@@ -574,6 +680,10 @@ export async function runScanEngine(input) {
|
|
|
574
680
|
rulePackPaths: input.config.rule_pack_paths,
|
|
575
681
|
allowedRules: input.config.allowed_rules,
|
|
576
682
|
skipRules: input.config.skip_rules,
|
|
683
|
+
persona: input.config.persona,
|
|
684
|
+
runtimeMode: input.config.runtime_mode,
|
|
685
|
+
workflowAuditsEnabled: input.config.workflow_audits?.enabled === true,
|
|
686
|
+
rulePolicies: input.config.rules,
|
|
577
687
|
},
|
|
578
688
|
});
|
|
579
689
|
const snapshots = new Map();
|
|
@@ -588,7 +698,11 @@ export async function runScanEngine(input) {
|
|
|
588
698
|
previousState,
|
|
589
699
|
});
|
|
590
700
|
saveScanState(stateResult.nextState, input.scanStatePath);
|
|
591
|
-
const
|
|
701
|
+
const inlineIgnores = collectInlineIgnoreDirectives(staticFiles.map((file) => ({
|
|
702
|
+
filePath: file.filePath,
|
|
703
|
+
textContent: file.textContent,
|
|
704
|
+
})));
|
|
705
|
+
const findings = applyInlineIgnoreDirectives([...report.findings, ...parseErrors, ...stateResult.findings], inlineIgnores);
|
|
592
706
|
return applyReportSummary({
|
|
593
707
|
...report,
|
|
594
708
|
findings,
|
package/dist/types/finding.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare const SEVERITIES: readonly ["CRITICAL", "HIGH", "MEDIUM", "LOW", "INFO"];
|
|
2
2
|
export type Severity = (typeof SEVERITIES)[number];
|
|
3
|
-
export declare const FINDING_CATEGORIES: readonly ["ENV_OVERRIDE", "COMMAND_EXEC", "CONSENT_BYPASS", "RULE_INJECTION", "IDE_SETTINGS", "SYMLINK_ESCAPE", "GIT_HOOK", "CONFIG_PRESENT", "PARSE_ERROR", "CONFIG_CHANGE", "NEW_SERVER", "TOXIC_FLOW"];
|
|
3
|
+
export declare const FINDING_CATEGORIES: readonly ["ENV_OVERRIDE", "COMMAND_EXEC", "CONSENT_BYPASS", "RULE_INJECTION", "IDE_SETTINGS", "SYMLINK_ESCAPE", "GIT_HOOK", "CONFIG_PRESENT", "PARSE_ERROR", "CONFIG_CHANGE", "NEW_SERVER", "TOXIC_FLOW", "CI_SUPPLY_CHAIN", "CI_TRIGGER", "CI_PERMISSIONS", "CI_TEMPLATE_INJECTION", "CI_VULNERABLE_ACTION"];
|
|
4
4
|
export type FindingCategory = (typeof FINDING_CATEGORIES)[number];
|
|
5
5
|
export type FindingLayer = "L1" | "L2" | "L3";
|
|
6
6
|
export type FindingConfidence = "HIGH" | "MEDIUM" | "LOW";
|
package/dist/types/finding.js
CHANGED