@bouncesecurity/aghast 0.0.13
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/LICENSE +661 -0
- package/README.md +111 -0
- package/config/prompts/generic-instructions.md +56 -0
- package/config/prompts/test-cheaper-instructions.md +57 -0
- package/dist/check-library.d.ts +87 -0
- package/dist/check-library.d.ts.map +1 -0
- package/dist/check-library.js +374 -0
- package/dist/check-library.js.map +1 -0
- package/dist/claude-code-provider.d.ts +26 -0
- package/dist/claude-code-provider.d.ts.map +1 -0
- package/dist/claude-code-provider.js +247 -0
- package/dist/claude-code-provider.js.map +1 -0
- package/dist/cli.d.ts +13 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +78 -0
- package/dist/cli.js.map +1 -0
- package/dist/colors.d.ts +7 -0
- package/dist/colors.d.ts.map +1 -0
- package/dist/colors.js +18 -0
- package/dist/colors.js.map +1 -0
- package/dist/error-codes.d.ts +42 -0
- package/dist/error-codes.d.ts.map +1 -0
- package/dist/error-codes.js +60 -0
- package/dist/error-codes.js.map +1 -0
- package/dist/formatters/index.d.ts +10 -0
- package/dist/formatters/index.d.ts.map +1 -0
- package/dist/formatters/index.js +23 -0
- package/dist/formatters/index.js.map +1 -0
- package/dist/formatters/json-formatter.d.ts +11 -0
- package/dist/formatters/json-formatter.d.ts.map +1 -0
- package/dist/formatters/json-formatter.js +11 -0
- package/dist/formatters/json-formatter.js.map +1 -0
- package/dist/formatters/sarif-formatter.d.ts +18 -0
- package/dist/formatters/sarif-formatter.d.ts.map +1 -0
- package/dist/formatters/sarif-formatter.js +103 -0
- package/dist/formatters/sarif-formatter.js.map +1 -0
- package/dist/formatters/types.d.ts +11 -0
- package/dist/formatters/types.d.ts.map +1 -0
- package/dist/formatters/types.js +6 -0
- package/dist/formatters/types.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +406 -0
- package/dist/index.js.map +1 -0
- package/dist/logging.d.ts +26 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +79 -0
- package/dist/logging.js.map +1 -0
- package/dist/mock-ai-provider.d.ts +18 -0
- package/dist/mock-ai-provider.d.ts.map +1 -0
- package/dist/mock-ai-provider.js +28 -0
- package/dist/mock-ai-provider.js.map +1 -0
- package/dist/new-check.d.ts +13 -0
- package/dist/new-check.d.ts.map +1 -0
- package/dist/new-check.js +405 -0
- package/dist/new-check.js.map +1 -0
- package/dist/prompt-template.d.ts +12 -0
- package/dist/prompt-template.d.ts.map +1 -0
- package/dist/prompt-template.js +35 -0
- package/dist/prompt-template.js.map +1 -0
- package/dist/provider-registry.d.ts +15 -0
- package/dist/provider-registry.d.ts.map +1 -0
- package/dist/provider-registry.js +27 -0
- package/dist/provider-registry.js.map +1 -0
- package/dist/repository-analyzer.d.ts +68 -0
- package/dist/repository-analyzer.d.ts.map +1 -0
- package/dist/repository-analyzer.js +230 -0
- package/dist/repository-analyzer.js.map +1 -0
- package/dist/response-parser.d.ts +12 -0
- package/dist/response-parser.d.ts.map +1 -0
- package/dist/response-parser.js +109 -0
- package/dist/response-parser.js.map +1 -0
- package/dist/runtime-config.d.ts +15 -0
- package/dist/runtime-config.d.ts.map +1 -0
- package/dist/runtime-config.js +73 -0
- package/dist/runtime-config.js.map +1 -0
- package/dist/sarif-parser.d.ts +20 -0
- package/dist/sarif-parser.d.ts.map +1 -0
- package/dist/sarif-parser.js +76 -0
- package/dist/sarif-parser.js.map +1 -0
- package/dist/scan-runner.d.ts +29 -0
- package/dist/scan-runner.d.ts.map +1 -0
- package/dist/scan-runner.js +559 -0
- package/dist/scan-runner.js.map +1 -0
- package/dist/semgrep-runner.d.ts +25 -0
- package/dist/semgrep-runner.d.ts.map +1 -0
- package/dist/semgrep-runner.js +100 -0
- package/dist/semgrep-runner.js.map +1 -0
- package/dist/snippet-extractor.d.ts +25 -0
- package/dist/snippet-extractor.d.ts.map +1 -0
- package/dist/snippet-extractor.js +56 -0
- package/dist/snippet-extractor.js.map +1 -0
- package/dist/types.d.ts +206 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +19 -0
- package/dist/types.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SARIF 2.1.0 output formatter.
|
|
3
|
+
* Maps ScanResults to the SARIF schema for integration with
|
|
4
|
+
* code scanning UIs (e.g. GitHub Code Scanning) and SARIF viewers.
|
|
5
|
+
*/
|
|
6
|
+
/** Maps aghast severity to SARIF result level. */
|
|
7
|
+
export function mapSeverityToLevel(severity) {
|
|
8
|
+
switch (severity) {
|
|
9
|
+
case 'critical':
|
|
10
|
+
case 'high':
|
|
11
|
+
return 'error';
|
|
12
|
+
case 'medium':
|
|
13
|
+
return 'warning';
|
|
14
|
+
case 'low':
|
|
15
|
+
case 'informational':
|
|
16
|
+
default:
|
|
17
|
+
return 'note';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export class SarifFormatter {
|
|
21
|
+
id = 'sarif';
|
|
22
|
+
fileExtension = '.sarif';
|
|
23
|
+
format(results) {
|
|
24
|
+
const rules = this.buildRules(results);
|
|
25
|
+
const sarifResults = this.buildResults(results.issues);
|
|
26
|
+
const sarif = {
|
|
27
|
+
$schema: 'https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json',
|
|
28
|
+
version: '2.1.0',
|
|
29
|
+
runs: [
|
|
30
|
+
{
|
|
31
|
+
tool: {
|
|
32
|
+
driver: {
|
|
33
|
+
name: 'aghast',
|
|
34
|
+
semanticVersion: results.version,
|
|
35
|
+
rules,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
results: sarifResults,
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
};
|
|
42
|
+
return JSON.stringify(sarif, null, 2);
|
|
43
|
+
}
|
|
44
|
+
buildRules(results) {
|
|
45
|
+
const seen = new Map();
|
|
46
|
+
for (const check of results.checks) {
|
|
47
|
+
if (!seen.has(check.checkId)) {
|
|
48
|
+
seen.set(check.checkId, {
|
|
49
|
+
id: check.checkId,
|
|
50
|
+
name: check.checkName,
|
|
51
|
+
shortDescription: { text: check.checkName },
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return Array.from(seen.values());
|
|
56
|
+
}
|
|
57
|
+
buildResults(issues) {
|
|
58
|
+
return issues.map((issue) => {
|
|
59
|
+
const region = {
|
|
60
|
+
startLine: issue.startLine,
|
|
61
|
+
endLine: issue.endLine,
|
|
62
|
+
};
|
|
63
|
+
if (issue.codeSnippet) {
|
|
64
|
+
region.snippet = { text: issue.codeSnippet };
|
|
65
|
+
}
|
|
66
|
+
const result = {
|
|
67
|
+
ruleId: issue.checkId,
|
|
68
|
+
message: { text: issue.description },
|
|
69
|
+
level: mapSeverityToLevel(issue.severity),
|
|
70
|
+
locations: [
|
|
71
|
+
{
|
|
72
|
+
physicalLocation: {
|
|
73
|
+
artifactLocation: { uri: issue.file },
|
|
74
|
+
region,
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
};
|
|
79
|
+
if (issue.dataFlow && issue.dataFlow.length > 0) {
|
|
80
|
+
result.codeFlows = [this.buildCodeFlow(issue.dataFlow)];
|
|
81
|
+
}
|
|
82
|
+
return result;
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
buildCodeFlow(steps) {
|
|
86
|
+
return {
|
|
87
|
+
threadFlows: [
|
|
88
|
+
{
|
|
89
|
+
locations: steps.map((step) => ({
|
|
90
|
+
location: {
|
|
91
|
+
physicalLocation: {
|
|
92
|
+
artifactLocation: { uri: step.file },
|
|
93
|
+
region: { startLine: step.lineNumber },
|
|
94
|
+
},
|
|
95
|
+
message: { text: step.label },
|
|
96
|
+
},
|
|
97
|
+
})),
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=sarif-formatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sarif-formatter.js","sourceRoot":"","sources":["../../src/formatters/sarif-formatter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output formatter interface for scan results.
|
|
3
|
+
* Follows the AIProvider interface pattern from src/types.ts.
|
|
4
|
+
*/
|
|
5
|
+
import type { ScanResults } from '../types.js';
|
|
6
|
+
export interface OutputFormatter {
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly fileExtension: string;
|
|
9
|
+
format(results: ScanResults): string;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/formatters/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,MAAM,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAAC;CACtC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/formatters/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,eAAe,CAAC;AAmPvB,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsN3D"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI entry point for aghast.
|
|
3
|
+
* Usage: aghast scan <repository-path> --config-dir <path> [options]
|
|
4
|
+
*/
|
|
5
|
+
import 'dotenv/config';
|
|
6
|
+
import { readFile, writeFile, stat, mkdir, readdir } from 'node:fs/promises';
|
|
7
|
+
import { resolve, dirname } from 'node:path';
|
|
8
|
+
import { runMultiScan } from './scan-runner.js';
|
|
9
|
+
import { createProviderByName, getProviderNames, DEFAULT_PROVIDER_NAME } from './provider-registry.js';
|
|
10
|
+
import { loadCheckRegistry, discoverCheckFolders, resolveChecks, filterChecksForRepository, validateCheck, loadCheckDetails, } from './check-library.js';
|
|
11
|
+
import { analyzeRepository } from './repository-analyzer.js';
|
|
12
|
+
import { loadRuntimeConfig } from './runtime-config.js';
|
|
13
|
+
import { logProgress, logDebug, setLogLevel, createTimer } from './logging.js';
|
|
14
|
+
import { MOCK_MODEL_NAME, DEFAULT_AI_MODEL } from './types.js';
|
|
15
|
+
import { getFormatter } from './formatters/index.js';
|
|
16
|
+
import { verifySemgrepInstalled } from './semgrep-runner.js';
|
|
17
|
+
import { MockAIProvider } from './mock-ai-provider.js';
|
|
18
|
+
import { ERROR_CODES, formatError, formatFatalError } from './error-codes.js';
|
|
19
|
+
import { colorStatus } from './colors.js';
|
|
20
|
+
import { createRequire } from 'node:module';
|
|
21
|
+
const TAG = 'aghast';
|
|
22
|
+
async function createMockProvider() {
|
|
23
|
+
// AGHAST_MOCK_AI='true' → default empty response; AGHAST_MOCK_AI=<path> → read from that file
|
|
24
|
+
const mockAiValue = process.env.AGHAST_MOCK_AI;
|
|
25
|
+
let rawResponse = '{"issues": []}';
|
|
26
|
+
if (mockAiValue && mockAiValue !== 'true') {
|
|
27
|
+
try {
|
|
28
|
+
rawResponse = await readFile(resolve(mockAiValue), 'utf-8');
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
throw new Error(`Failed to read AGHAST_MOCK_AI response file: ${mockAiValue}`, { cause: err });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const provider = new MockAIProvider({ rawResponse });
|
|
35
|
+
await provider.initialize({});
|
|
36
|
+
return provider;
|
|
37
|
+
}
|
|
38
|
+
const SCAN_HELP = `Usage: aghast scan <repo-path> --config-dir <path> [options]
|
|
39
|
+
|
|
40
|
+
Run security checks against a repository.
|
|
41
|
+
|
|
42
|
+
Arguments:
|
|
43
|
+
<repo-path> Path to the repository to scan
|
|
44
|
+
|
|
45
|
+
Options:
|
|
46
|
+
--config-dir <path> Config directory containing checks-config.json,
|
|
47
|
+
checks/ folder, and optionally runtime-config.json.
|
|
48
|
+
Required unless AGHAST_CONFIG_DIR is set.
|
|
49
|
+
--output <path> Output file path for results
|
|
50
|
+
(default: <repo-path>/security_checks_results.<ext>)
|
|
51
|
+
--output-format json|sarif Output format (default: json)
|
|
52
|
+
--fail-on-check-failure Exit with code 1 if any check FAILs or ERRORs
|
|
53
|
+
--debug Enable verbose debug output
|
|
54
|
+
--model <model> AI model override (e.g. claude-sonnet-4-20250514)
|
|
55
|
+
--ai-provider <name> AI provider name (default: claude-code)
|
|
56
|
+
--generic-prompt <file> Generic prompt template filename in prompts/ dir
|
|
57
|
+
--runtime-config <path> Path to runtime config file (replaces individual flags
|
|
58
|
+
for persistent configuration)
|
|
59
|
+
-h, --help Show this help message
|
|
60
|
+
|
|
61
|
+
Environment variables:
|
|
62
|
+
ANTHROPIC_API_KEY API key for Claude (required for AI-based checks)
|
|
63
|
+
AGHAST_CONFIG_DIR Default config directory (CLI --config-dir takes precedence)
|
|
64
|
+
AGHAST_AI_MODEL AI model override (CLI --model takes precedence)
|
|
65
|
+
AGHAST_GENERIC_PROMPT Generic prompt template filename (CLI --generic-prompt takes precedence)
|
|
66
|
+
AGHAST_DEBUG Set to "true" to enable debug output (same as --debug)
|
|
67
|
+
|
|
68
|
+
Examples:
|
|
69
|
+
aghast scan ./my-repo --config-dir ./my-checks
|
|
70
|
+
aghast scan ./my-repo --config-dir ./my-checks --output results.sarif --output-format sarif
|
|
71
|
+
aghast scan ./my-repo --config-dir ./my-checks --fail-on-check-failure --debug
|
|
72
|
+
aghast scan ./my-repo --config-dir ./my-checks --model claude-sonnet-4-20250514`;
|
|
73
|
+
function parseArgs(args) {
|
|
74
|
+
if (args.length < 1 || args[0] === '--help' || args[0] === '-h') {
|
|
75
|
+
console.log(SCAN_HELP);
|
|
76
|
+
process.exit(0);
|
|
77
|
+
}
|
|
78
|
+
const repositoryPath = resolve(args[0]);
|
|
79
|
+
let configDir;
|
|
80
|
+
let outputFormat;
|
|
81
|
+
let outputPath;
|
|
82
|
+
const failOnCheckFailure = args.includes('--fail-on-check-failure');
|
|
83
|
+
const debug = args.includes('--debug');
|
|
84
|
+
let runtimeConfigPath;
|
|
85
|
+
let model;
|
|
86
|
+
let aiProvider;
|
|
87
|
+
let genericPrompt;
|
|
88
|
+
for (let i = 1; i < args.length; i++) {
|
|
89
|
+
switch (args[i]) {
|
|
90
|
+
case '--config-dir': {
|
|
91
|
+
configDir = args[i + 1];
|
|
92
|
+
if (!configDir) {
|
|
93
|
+
console.error(formatError(ERROR_CODES.E1001, '--config-dir requires a path argument'));
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
configDir = resolve(configDir);
|
|
97
|
+
i++;
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
case '--output': {
|
|
101
|
+
outputPath = args[i + 1];
|
|
102
|
+
if (!outputPath) {
|
|
103
|
+
console.error(formatError(ERROR_CODES.E1001, '--output requires a path argument'));
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
outputPath = resolve(outputPath);
|
|
107
|
+
i++;
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
case '--output-format': {
|
|
111
|
+
outputFormat = args[i + 1];
|
|
112
|
+
if (!outputFormat) {
|
|
113
|
+
console.error(formatError(ERROR_CODES.E1001, '--output-format requires a format argument'));
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
i++;
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
case '--runtime-config': {
|
|
120
|
+
runtimeConfigPath = args[i + 1];
|
|
121
|
+
if (!runtimeConfigPath) {
|
|
122
|
+
console.error(formatError(ERROR_CODES.E1001, '--runtime-config requires a path argument'));
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
runtimeConfigPath = resolve(runtimeConfigPath);
|
|
126
|
+
i++;
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
case '--model': {
|
|
130
|
+
model = args[i + 1];
|
|
131
|
+
if (!model) {
|
|
132
|
+
console.error(formatError(ERROR_CODES.E1001, '--model requires a model name argument'));
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
135
|
+
i++;
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
case '--ai-provider': {
|
|
139
|
+
aiProvider = args[i + 1];
|
|
140
|
+
if (!aiProvider) {
|
|
141
|
+
console.error(formatError(ERROR_CODES.E1001, '--ai-provider requires a provider name argument'));
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
144
|
+
i++;
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
case '--generic-prompt': {
|
|
148
|
+
genericPrompt = args[i + 1];
|
|
149
|
+
if (!genericPrompt) {
|
|
150
|
+
console.error(formatError(ERROR_CODES.E1001, '--generic-prompt requires a filename argument'));
|
|
151
|
+
process.exit(1);
|
|
152
|
+
}
|
|
153
|
+
i++;
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
// --fail-on-check-failure and --debug are handled above via includes()
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
repositoryPath, configDir, outputPath, outputFormat,
|
|
161
|
+
failOnCheckFailure, debug, runtimeConfigPath, model, aiProvider,
|
|
162
|
+
genericPrompt,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
async function createProvider(useMock, aiProviderName, modelOverride) {
|
|
166
|
+
if (useMock) {
|
|
167
|
+
logProgress(TAG, `MOCK AI provider enabled via AGHAST_MOCK_AI=${process.env.AGHAST_MOCK_AI}`);
|
|
168
|
+
return { provider: await createMockProvider(), modelName: MOCK_MODEL_NAME };
|
|
169
|
+
}
|
|
170
|
+
const provider = createProviderByName(aiProviderName);
|
|
171
|
+
await provider.initialize({
|
|
172
|
+
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
173
|
+
model: modelOverride,
|
|
174
|
+
});
|
|
175
|
+
const modelName = provider.getModelName?.() ?? DEFAULT_AI_MODEL;
|
|
176
|
+
return { provider, modelName };
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Validate that the config directory has the required structure.
|
|
180
|
+
* Returns early with a clear error message if anything is missing.
|
|
181
|
+
*/
|
|
182
|
+
async function validateConfigDir(configDir) {
|
|
183
|
+
// Check checks-config.json exists
|
|
184
|
+
const registryPath = resolve(configDir, 'checks-config.json');
|
|
185
|
+
try {
|
|
186
|
+
await stat(registryPath);
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
console.error(formatError(ERROR_CODES.E2002, `Config directory is missing checks-config.json: ${registryPath}`));
|
|
190
|
+
console.error(` Use 'aghast new-check --config-dir ${configDir}' to bootstrap a config directory.`);
|
|
191
|
+
process.exit(1);
|
|
192
|
+
}
|
|
193
|
+
// Check checks/ directory exists
|
|
194
|
+
const checksPath = resolve(configDir, 'checks');
|
|
195
|
+
try {
|
|
196
|
+
const checksStat = await stat(checksPath);
|
|
197
|
+
if (!checksStat.isDirectory()) {
|
|
198
|
+
console.error(formatError(ERROR_CODES.E2002, `${checksPath} exists but is not a directory`));
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
console.error(formatError(ERROR_CODES.E2002, `Config directory is missing checks/ folder: ${checksPath}`));
|
|
204
|
+
console.error(` Use 'aghast new-check --config-dir ${configDir}' to add checks.`);
|
|
205
|
+
process.exit(1);
|
|
206
|
+
}
|
|
207
|
+
// Check that checks/ has at least one subfolder
|
|
208
|
+
const entries = await readdir(checksPath);
|
|
209
|
+
if (entries.length === 0) {
|
|
210
|
+
console.error(formatError(ERROR_CODES.E2003, `No checks found in ${checksPath}`));
|
|
211
|
+
console.error(` Use 'aghast new-check --config-dir ${configDir}' to add checks.`);
|
|
212
|
+
process.exit(1);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
export async function runScan(args) {
|
|
216
|
+
const globalTimer = createTimer();
|
|
217
|
+
const parsed = parseArgs(args);
|
|
218
|
+
// --config-dir is required (CLI flag > AGHAST_CONFIG_DIR env var)
|
|
219
|
+
const rawConfigDir = parsed.configDir || process.env.AGHAST_CONFIG_DIR;
|
|
220
|
+
if (!rawConfigDir) {
|
|
221
|
+
console.error(formatError(ERROR_CODES.E2001, "--config-dir is required (or set AGHAST_CONFIG_DIR). Use 'aghast new-check --config-dir <path>' to create a config directory."));
|
|
222
|
+
process.exit(1);
|
|
223
|
+
}
|
|
224
|
+
const configDir = resolve(rawConfigDir);
|
|
225
|
+
// Validate config directory structure
|
|
226
|
+
await validateConfigDir(configDir);
|
|
227
|
+
// Load runtime configuration
|
|
228
|
+
let runtimeConfig;
|
|
229
|
+
try {
|
|
230
|
+
runtimeConfig = await loadRuntimeConfig(configDir, parsed.runtimeConfigPath);
|
|
231
|
+
}
|
|
232
|
+
catch (err) {
|
|
233
|
+
console.error(formatError(ERROR_CODES.E2005, err instanceof Error ? err.message : String(err)));
|
|
234
|
+
process.exit(1);
|
|
235
|
+
}
|
|
236
|
+
// Set log level: --debug flag or AGHAST_DEBUG env var enables debug
|
|
237
|
+
const debug = parsed.debug || process.env.AGHAST_DEBUG === 'true';
|
|
238
|
+
setLogLevel(debug ? 'debug' : 'info');
|
|
239
|
+
// Validate repository path exists and is a directory
|
|
240
|
+
try {
|
|
241
|
+
const repoStat = await stat(parsed.repositoryPath);
|
|
242
|
+
if (!repoStat.isDirectory()) {
|
|
243
|
+
console.error(formatError(ERROR_CODES.E4001, `Repository path is not a directory: ${parsed.repositoryPath}`));
|
|
244
|
+
process.exit(1);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
catch (err) {
|
|
248
|
+
if (err instanceof Error && 'code' in err && err.code === 'ENOENT') {
|
|
249
|
+
console.error(formatError(ERROR_CODES.E4001, `Repository path does not exist: ${parsed.repositoryPath}`));
|
|
250
|
+
process.exit(1);
|
|
251
|
+
}
|
|
252
|
+
throw err;
|
|
253
|
+
}
|
|
254
|
+
// Resolve output format: CLI > runtime config > default
|
|
255
|
+
const resolvedOutputFormat = parsed.outputFormat ?? runtimeConfig.reporting?.outputFormat ?? 'json';
|
|
256
|
+
// Resolve formatter early — fail fast on unknown format
|
|
257
|
+
const formatter = getFormatter(resolvedOutputFormat);
|
|
258
|
+
// Treat AGHAST_MOCK_AI=false (or empty) as disabled; any other truthy value enables mock mode
|
|
259
|
+
const mockAiEnv = process.env.AGHAST_MOCK_AI;
|
|
260
|
+
const useMock = !!(mockAiEnv && mockAiEnv !== 'false');
|
|
261
|
+
// ─── Load and filter checks BEFORE AI validation ───
|
|
262
|
+
// Checks always live in <config-dir>/checks/
|
|
263
|
+
const checksDirs = [resolve(configDir, 'checks')];
|
|
264
|
+
// Resolve generic prompt: CLI > env > runtime config > default (handled in buildPrompt)
|
|
265
|
+
const genericPrompt = parsed.genericPrompt ?? process.env.AGHAST_GENERIC_PROMPT ?? runtimeConfig.genericPrompt;
|
|
266
|
+
logDebug(TAG, `Config dir: ${configDir}, checks dir: ${checksDirs[0]}`);
|
|
267
|
+
// Two-layer config loading
|
|
268
|
+
const registry = await loadCheckRegistry(configDir);
|
|
269
|
+
const checkFolders = await discoverCheckFolders(checksDirs);
|
|
270
|
+
if (checkFolders.size === 0) {
|
|
271
|
+
console.error(formatError(ERROR_CODES.E2003, `No valid checks found in ${checksDirs[0]}. Each check needs a <id>/<id>.json file.`));
|
|
272
|
+
process.exit(1);
|
|
273
|
+
}
|
|
274
|
+
const allChecks = await resolveChecks(registry, checkFolders);
|
|
275
|
+
// Analyze repository to get remote URL for check filtering
|
|
276
|
+
const repoAnalysis = await analyzeRepository(parsed.repositoryPath);
|
|
277
|
+
const repoUrl = repoAnalysis.repository.remoteUrl ?? parsed.repositoryPath;
|
|
278
|
+
const matchingChecks = filterChecksForRepository(allChecks, repoUrl);
|
|
279
|
+
logProgress(TAG, `Found ${matchingChecks.length} matching checks (of ${allChecks.length} total)`);
|
|
280
|
+
if (matchingChecks.length === 0) {
|
|
281
|
+
logProgress(TAG, 'No matching checks found for this repository');
|
|
282
|
+
}
|
|
283
|
+
// Validate and load check details
|
|
284
|
+
const checksWithDetails = [];
|
|
285
|
+
for (const check of matchingChecks) {
|
|
286
|
+
// instructionsFile is already absolute from resolveChecks — validate against ''
|
|
287
|
+
const validation = await validateCheck(check, '');
|
|
288
|
+
if (!validation.valid) {
|
|
289
|
+
logProgress(TAG, `Skipping invalid check "${check.id}": ${validation.errors.join(', ')}`);
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
// checkTarget rules already resolved by resolveChecks — no additional path resolution needed
|
|
293
|
+
// semgrep-only checks have no instructions markdown — use synthetic details
|
|
294
|
+
if (check.checkTarget?.type === 'semgrep-only') {
|
|
295
|
+
checksWithDetails.push({
|
|
296
|
+
check,
|
|
297
|
+
details: { id: check.id, name: check.name, overview: '', content: '' },
|
|
298
|
+
});
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
const details = await loadCheckDetails(check, '');
|
|
302
|
+
checksWithDetails.push({ check, details });
|
|
303
|
+
}
|
|
304
|
+
// ─── Determine which prerequisites are needed ───
|
|
305
|
+
const needsAI = checksWithDetails.some(c => c.check.checkTarget?.type !== 'semgrep-only');
|
|
306
|
+
const needsSemgrep = checksWithDetails.some(c => c.check.checkTarget?.type === 'semgrep' || c.check.checkTarget?.type === 'semgrep-only');
|
|
307
|
+
// ─── Conditional AI provider setup ───
|
|
308
|
+
const aiProviderName = parsed.aiProvider ?? runtimeConfig.aiProvider?.name ?? DEFAULT_PROVIDER_NAME;
|
|
309
|
+
if (needsAI && !useMock) {
|
|
310
|
+
// Validate AI provider name before checking credentials (config errors before auth errors)
|
|
311
|
+
if (!getProviderNames().includes(aiProviderName)) {
|
|
312
|
+
console.error(formatError(ERROR_CODES.E3002, `Unknown AI provider "${aiProviderName}". Supported providers: ${getProviderNames().join(', ')}`));
|
|
313
|
+
process.exit(1);
|
|
314
|
+
}
|
|
315
|
+
// Validate ANTHROPIC_API_KEY (not needed when using mock or local Claude)
|
|
316
|
+
if (!process.env.ANTHROPIC_API_KEY && process.env.AGHAST_LOCAL_CLAUDE !== 'true') {
|
|
317
|
+
console.error(formatError(ERROR_CODES.E3001, 'ANTHROPIC_API_KEY environment variable is required (or set AGHAST_LOCAL_CLAUDE=true)'));
|
|
318
|
+
process.exit(1);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
// Resolve model precedence: CLI --model > env AGHAST_AI_MODEL > runtime config > default
|
|
322
|
+
const modelOverride = parsed.model ?? process.env.AGHAST_AI_MODEL ?? runtimeConfig.aiProvider?.model;
|
|
323
|
+
let provider;
|
|
324
|
+
let modelName;
|
|
325
|
+
if (needsAI) {
|
|
326
|
+
({ provider, modelName } = await createProvider(useMock, aiProviderName, modelOverride));
|
|
327
|
+
if (debug) {
|
|
328
|
+
provider.enableDebug?.();
|
|
329
|
+
}
|
|
330
|
+
logProgress(TAG, `Using model: ${modelName}`);
|
|
331
|
+
}
|
|
332
|
+
// ─── Conditional Semgrep verification ───
|
|
333
|
+
if (needsSemgrep && !process.env.AGHAST_MOCK_SEMGREP) {
|
|
334
|
+
try {
|
|
335
|
+
await verifySemgrepInstalled();
|
|
336
|
+
}
|
|
337
|
+
catch (err) {
|
|
338
|
+
console.error(formatError(ERROR_CODES.E5001, err instanceof Error ? err.message : String(err)));
|
|
339
|
+
process.exit(1);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
const results = await runMultiScan({
|
|
343
|
+
repositoryPath: parsed.repositoryPath,
|
|
344
|
+
checks: checksWithDetails,
|
|
345
|
+
aiProvider: provider,
|
|
346
|
+
aiModelName: needsAI ? modelName : undefined,
|
|
347
|
+
repositoryInfo: repoAnalysis.repository,
|
|
348
|
+
aiProviderName: needsAI ? (useMock ? 'mock' : aiProviderName) : undefined,
|
|
349
|
+
configDir,
|
|
350
|
+
genericPrompt,
|
|
351
|
+
});
|
|
352
|
+
// Resolve output path: --output flag > runtime config dir > default
|
|
353
|
+
let outputPath;
|
|
354
|
+
if (parsed.outputPath) {
|
|
355
|
+
outputPath = parsed.outputPath;
|
|
356
|
+
}
|
|
357
|
+
else if (runtimeConfig.reporting?.outputDirectory) {
|
|
358
|
+
const dir = resolve(runtimeConfig.reporting.outputDirectory);
|
|
359
|
+
outputPath = resolve(dir, 'security_checks_results' + formatter.fileExtension);
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
outputPath = resolve(parsed.repositoryPath, 'security_checks_results' + formatter.fileExtension);
|
|
363
|
+
}
|
|
364
|
+
await mkdir(dirname(outputPath), { recursive: true });
|
|
365
|
+
await writeFile(outputPath, formatter.format(results), 'utf-8');
|
|
366
|
+
// Summary output
|
|
367
|
+
const statusIcon = results.summary.failedChecks > 0
|
|
368
|
+
? 'FAIL'
|
|
369
|
+
: results.summary.flaggedChecks > 0
|
|
370
|
+
? 'FLAG'
|
|
371
|
+
: results.summary.errorChecks > 0
|
|
372
|
+
? 'ERROR'
|
|
373
|
+
: 'PASS';
|
|
374
|
+
console.log('');
|
|
375
|
+
console.log('='.repeat(60));
|
|
376
|
+
console.log(`AGHAST Scan Complete: ${colorStatus(statusIcon)}`);
|
|
377
|
+
console.log('='.repeat(60));
|
|
378
|
+
console.log(` Total checks: ${results.summary.totalChecks}`);
|
|
379
|
+
console.log(` Passed: ${results.summary.passedChecks}`);
|
|
380
|
+
console.log(` Failed: ${results.summary.failedChecks}`);
|
|
381
|
+
console.log(` Flagged: ${results.summary.flaggedChecks}`);
|
|
382
|
+
console.log(` Errors: ${results.summary.errorChecks}`);
|
|
383
|
+
console.log(` Total issues: ${results.summary.totalIssues}`);
|
|
384
|
+
if (results.tokenUsage) {
|
|
385
|
+
console.log(` Tokens: ${results.tokenUsage.totalTokens.toLocaleString()} (in: ${results.tokenUsage.inputTokens.toLocaleString()}, out: ${results.tokenUsage.outputTokens.toLocaleString()})`);
|
|
386
|
+
}
|
|
387
|
+
console.log(` Duration: ${globalTimer.elapsedStr()}`);
|
|
388
|
+
console.log(` Results: ${outputPath}`);
|
|
389
|
+
console.log('='.repeat(60));
|
|
390
|
+
// Exit code based on --fail-on-check-failure flag or runtime config (spec Section 9.3)
|
|
391
|
+
const failOnCheckFailure = parsed.failOnCheckFailure || runtimeConfig.failOnCheckFailure === true;
|
|
392
|
+
const shouldFail = failOnCheckFailure && (results.summary.failedChecks > 0 || results.summary.errorChecks > 0);
|
|
393
|
+
process.exit(shouldFail ? 1 : 0);
|
|
394
|
+
}
|
|
395
|
+
// Auto-run when executed directly (pnpm scan / tsx src/index.ts), but not when imported by cli.ts.
|
|
396
|
+
if (!process.env._AGHAST_CLI) {
|
|
397
|
+
runScan(process.argv.slice(2)).catch((err) => {
|
|
398
|
+
const require = createRequire(import.meta.url);
|
|
399
|
+
const pkg = require('../package.json');
|
|
400
|
+
console.error('');
|
|
401
|
+
console.error(formatFatalError(err instanceof Error ? err.message : String(err), pkg.version));
|
|
402
|
+
logDebug(TAG, 'Error details', err);
|
|
403
|
+
process.exit(1);
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type LogLevel = 'silent' | 'info' | 'debug';
|
|
2
|
+
export declare function getLogLevel(): LogLevel;
|
|
3
|
+
/**
|
|
4
|
+
* Programmatically set the log level (avoids env var race conditions with --debug flag).
|
|
5
|
+
*/
|
|
6
|
+
export declare function setLogLevel(level: LogLevel): void;
|
|
7
|
+
/**
|
|
8
|
+
* Log a progress/activity message at info level.
|
|
9
|
+
*/
|
|
10
|
+
export declare function logProgress(tag: string, message: string, details?: Record<string, unknown>): void;
|
|
11
|
+
/**
|
|
12
|
+
* Create a timer for measuring elapsed time.
|
|
13
|
+
*/
|
|
14
|
+
export declare function createTimer(): {
|
|
15
|
+
elapsed: () => number;
|
|
16
|
+
elapsedStr: () => string;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Log debug information (single line, compact).
|
|
20
|
+
*/
|
|
21
|
+
export declare function logDebug(tag: string, message: string, data?: unknown): void;
|
|
22
|
+
/**
|
|
23
|
+
* Log debug information without truncation (for full prompts and responses).
|
|
24
|
+
*/
|
|
25
|
+
export declare function logDebugFull(tag: string, message: string, data?: string): void;
|
|
26
|
+
//# sourceMappingURL=logging.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../src/logging.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAUnD,wBAAgB,WAAW,IAAI,QAAQ,CAItC;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAEjD;AAMD;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAMjG;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI;IAAE,OAAO,EAAE,MAAM,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,MAAM,CAAA;CAAE,CAWjF;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAW3E;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAS9E"}
|