tryassay 0.32.0 → 0.33.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/dist/cli.js +55 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/assess.js +73 -0
- package/dist/commands/assess.js.map +1 -1
- package/dist/commands/bounty-chain.d.ts +1 -0
- package/dist/commands/bounty-chain.js +34 -0
- package/dist/commands/bounty-chain.js.map +1 -0
- package/dist/commands/bounty-check.d.ts +10 -0
- package/dist/commands/bounty-check.js +104 -0
- package/dist/commands/bounty-check.js.map +1 -0
- package/dist/commands/bounty-discover.d.ts +6 -0
- package/dist/commands/bounty-discover.js +45 -0
- package/dist/commands/bounty-discover.js.map +1 -0
- package/dist/commands/bounty-scan.d.ts +7 -0
- package/dist/commands/bounty-scan.js +312 -0
- package/dist/commands/bounty-scan.js.map +1 -0
- package/dist/commands/bounty-watch.d.ts +9 -0
- package/dist/commands/bounty-watch.js +210 -0
- package/dist/commands/bounty-watch.js.map +1 -0
- package/dist/commands/hunt.d.ts +11 -0
- package/dist/commands/hunt.js +216 -0
- package/dist/commands/hunt.js.map +1 -0
- package/dist/hunt/__tests__/deep-dive.test.d.ts +1 -0
- package/dist/hunt/__tests__/deep-dive.test.js +102 -0
- package/dist/hunt/__tests__/deep-dive.test.js.map +1 -0
- package/dist/hunt/__tests__/discovery.test.d.ts +1 -0
- package/dist/hunt/__tests__/discovery.test.js +55 -0
- package/dist/hunt/__tests__/discovery.test.js.map +1 -0
- package/dist/hunt/__tests__/e2e.test.d.ts +1 -0
- package/dist/hunt/__tests__/e2e.test.js +261 -0
- package/dist/hunt/__tests__/e2e.test.js.map +1 -0
- package/dist/hunt/__tests__/matcher.test.d.ts +1 -0
- package/dist/hunt/__tests__/matcher.test.js +63 -0
- package/dist/hunt/__tests__/matcher.test.js.map +1 -0
- package/dist/hunt/__tests__/orchestrator.test.d.ts +1 -0
- package/dist/hunt/__tests__/orchestrator.test.js +73 -0
- package/dist/hunt/__tests__/orchestrator.test.js.map +1 -0
- package/dist/hunt/__tests__/parse-utils.test.d.ts +1 -0
- package/dist/hunt/__tests__/parse-utils.test.js +28 -0
- package/dist/hunt/__tests__/parse-utils.test.js.map +1 -0
- package/dist/hunt/__tests__/state.test.d.ts +1 -0
- package/dist/hunt/__tests__/state.test.js +49 -0
- package/dist/hunt/__tests__/state.test.js.map +1 -0
- package/dist/hunt/__tests__/templates.test.d.ts +1 -0
- package/dist/hunt/__tests__/templates.test.js +32 -0
- package/dist/hunt/__tests__/templates.test.js.map +1 -0
- package/dist/hunt/__tests__/triage.test.d.ts +1 -0
- package/dist/hunt/__tests__/triage.test.js +91 -0
- package/dist/hunt/__tests__/triage.test.js.map +1 -0
- package/dist/hunt/__tests__/types.test.d.ts +1 -0
- package/dist/hunt/__tests__/types.test.js +65 -0
- package/dist/hunt/__tests__/types.test.js.map +1 -0
- package/dist/hunt/deep-dive.d.ts +8 -0
- package/dist/hunt/deep-dive.js +86 -0
- package/dist/hunt/deep-dive.js.map +1 -0
- package/dist/hunt/discovery.d.ts +15 -0
- package/dist/hunt/discovery.js +116 -0
- package/dist/hunt/discovery.js.map +1 -0
- package/dist/hunt/matcher.d.ts +8 -0
- package/dist/hunt/matcher.js +27 -0
- package/dist/hunt/matcher.js.map +1 -0
- package/dist/hunt/orchestrator.d.ts +27 -0
- package/dist/hunt/orchestrator.js +91 -0
- package/dist/hunt/orchestrator.js.map +1 -0
- package/dist/hunt/parse-utils.d.ts +8 -0
- package/dist/hunt/parse-utils.js +44 -0
- package/dist/hunt/parse-utils.js.map +1 -0
- package/dist/hunt/state.d.ts +5 -0
- package/dist/hunt/state.js +35 -0
- package/dist/hunt/state.js.map +1 -0
- package/dist/hunt/templates/auth-bypass.d.ts +2 -0
- package/dist/hunt/templates/auth-bypass.js +80 -0
- package/dist/hunt/templates/auth-bypass.js.map +1 -0
- package/dist/hunt/templates/cors-misconfig.d.ts +2 -0
- package/dist/hunt/templates/cors-misconfig.js +88 -0
- package/dist/hunt/templates/cors-misconfig.js.map +1 -0
- package/dist/hunt/templates/csrf-bypass.d.ts +2 -0
- package/dist/hunt/templates/csrf-bypass.js +65 -0
- package/dist/hunt/templates/csrf-bypass.js.map +1 -0
- package/dist/hunt/templates/index.d.ts +3 -0
- package/dist/hunt/templates/index.js +29 -0
- package/dist/hunt/templates/index.js.map +1 -0
- package/dist/hunt/templates/injection.d.ts +2 -0
- package/dist/hunt/templates/injection.js +103 -0
- package/dist/hunt/templates/injection.js.map +1 -0
- package/dist/hunt/templates/open-redirect.d.ts +2 -0
- package/dist/hunt/templates/open-redirect.js +93 -0
- package/dist/hunt/templates/open-redirect.js.map +1 -0
- package/dist/hunt/templates/path-traversal.d.ts +2 -0
- package/dist/hunt/templates/path-traversal.js +94 -0
- package/dist/hunt/templates/path-traversal.js.map +1 -0
- package/dist/hunt/templates/prototype-pollution.d.ts +2 -0
- package/dist/hunt/templates/prototype-pollution.js +108 -0
- package/dist/hunt/templates/prototype-pollution.js.map +1 -0
- package/dist/hunt/templates/ssrf.d.ts +2 -0
- package/dist/hunt/templates/ssrf.js +75 -0
- package/dist/hunt/templates/ssrf.js.map +1 -0
- package/dist/hunt/templates/timing-attack.d.ts +2 -0
- package/dist/hunt/templates/timing-attack.js +108 -0
- package/dist/hunt/templates/timing-attack.js.map +1 -0
- package/dist/hunt/templates/weak-random.d.ts +2 -0
- package/dist/hunt/templates/weak-random.js +73 -0
- package/dist/hunt/templates/weak-random.js.map +1 -0
- package/dist/hunt/triage.d.ts +8 -0
- package/dist/hunt/triage.js +78 -0
- package/dist/hunt/triage.js.map +1 -0
- package/dist/lib/__tests__/bounty-scan.test.d.ts +1 -0
- package/dist/lib/__tests__/bounty-scan.test.js +15 -0
- package/dist/lib/__tests__/bounty-scan.test.js.map +1 -0
- package/dist/lib/__tests__/chain-analyzer.test.d.ts +1 -0
- package/dist/lib/__tests__/chain-analyzer.test.js +47 -0
- package/dist/lib/__tests__/chain-analyzer.test.js.map +1 -0
- package/dist/lib/__tests__/finding-dedup.test.d.ts +1 -0
- package/dist/lib/__tests__/finding-dedup.test.js +30 -0
- package/dist/lib/__tests__/finding-dedup.test.js.map +1 -0
- package/dist/lib/__tests__/learned-rules.test.js +25 -0
- package/dist/lib/__tests__/learned-rules.test.js.map +1 -1
- package/dist/lib/__tests__/novelty-checker.test.d.ts +1 -0
- package/dist/lib/__tests__/novelty-checker.test.js +57 -0
- package/dist/lib/__tests__/novelty-checker.test.js.map +1 -0
- package/dist/lib/__tests__/program-registry.test.d.ts +1 -0
- package/dist/lib/__tests__/program-registry.test.js +40 -0
- package/dist/lib/__tests__/program-registry.test.js.map +1 -0
- package/dist/lib/__tests__/retry.test.d.ts +1 -0
- package/dist/lib/__tests__/retry.test.js +23 -0
- package/dist/lib/__tests__/retry.test.js.map +1 -0
- package/dist/lib/__tests__/watchlist.test.d.ts +1 -0
- package/dist/lib/__tests__/watchlist.test.js +88 -0
- package/dist/lib/__tests__/watchlist.test.js.map +1 -0
- package/dist/lib/chain-analyzer.d.ts +25 -0
- package/dist/lib/chain-analyzer.js +105 -0
- package/dist/lib/chain-analyzer.js.map +1 -0
- package/dist/lib/finding-dedup.d.ts +2 -0
- package/dist/lib/finding-dedup.js +9 -0
- package/dist/lib/finding-dedup.js.map +1 -0
- package/dist/lib/issue-reporter.d.ts +13 -0
- package/dist/lib/issue-reporter.js +51 -0
- package/dist/lib/issue-reporter.js.map +1 -0
- package/dist/lib/novelty-checker.d.ts +60 -0
- package/dist/lib/novelty-checker.js +223 -0
- package/dist/lib/novelty-checker.js.map +1 -0
- package/dist/lib/program-registry.d.ts +12 -0
- package/dist/lib/program-registry.js +18 -0
- package/dist/lib/program-registry.js.map +1 -0
- package/dist/lib/retry.d.ts +5 -0
- package/dist/lib/retry.js +19 -0
- package/dist/lib/retry.js.map +1 -0
- package/dist/lib/watchlist.d.ts +23 -0
- package/dist/lib/watchlist.js +31 -0
- package/dist/lib/watchlist.js.map +1 -0
- package/dist/runtime/safe-executor.js +1 -1
- package/dist/runtime/safe-executor.js.map +1 -1
- package/dist/runtime/types.d.ts +1 -1
- package/dist/sdk/forward-verify.js +1 -1
- package/dist/sdk/forward-verify.js.map +1 -1
- package/dist/types.d.ts +45 -0
- package/package.json +1 -1
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import { resolve, basename, extname, relative, join } from 'node:path';
|
|
2
|
+
import { readFile, stat, writeFile, mkdir, readdir } from 'node:fs/promises';
|
|
3
|
+
import { safeExecSync } from '../runtime/safe-executor.js';
|
|
4
|
+
import { forwardVerify, ScanSession } from '../sdk/forward-verify.js';
|
|
5
|
+
import { getLearnedRulesSummary } from '../lib/learned-rules/index.js';
|
|
6
|
+
import { checkNoveltyLocal } from '../lib/novelty-checker.js';
|
|
7
|
+
// ── Security-critical file patterns ──────────────────────────
|
|
8
|
+
const SECURITY_GLOBS = [
|
|
9
|
+
'**/auth*', '**/csrf*', '**/cors*', '**/session*', '**/proxy*',
|
|
10
|
+
'**/cookie*', '**/sanitiz*', '**/validat*', '**/encrypt*', '**/decrypt*',
|
|
11
|
+
'**/token*', '**/password*', '**/secret*', '**/permission*',
|
|
12
|
+
'**/access-control*', '**/rate-limit*', '**/xss*', '**/injection*',
|
|
13
|
+
'**/ssrf*', '**/redirect*', '**/origin*', '**/header*', '**/middleware*',
|
|
14
|
+
'**/security*', '**/firewall*', '**/block*', '**/allow*', '**/deny*',
|
|
15
|
+
'**/private*', '**/image-optim*',
|
|
16
|
+
];
|
|
17
|
+
// ── Security keyword matchers (derived from SECURITY_GLOBS basenames) ──
|
|
18
|
+
const SECURITY_KEYWORDS = SECURITY_GLOBS.map(g => {
|
|
19
|
+
const base = g.split('/').pop() ?? '';
|
|
20
|
+
return base.replace(/^\*+/, '').replace(/\*+$/, '').toLowerCase();
|
|
21
|
+
}).filter(k => k.length > 0);
|
|
22
|
+
const IGNORED_DIRS = new Set([
|
|
23
|
+
'node_modules', '.git', 'dist', 'build', 'vendor',
|
|
24
|
+
'fixtures', 'examples', 'docs', '__tests__',
|
|
25
|
+
]);
|
|
26
|
+
const SUPPORTED_EXTENSIONS = new Set([
|
|
27
|
+
'.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs',
|
|
28
|
+
'.py', '.go', '.rs', '.java',
|
|
29
|
+
]);
|
|
30
|
+
// ── Helpers ──────────────────────────────────────────────────
|
|
31
|
+
function isGitUrl(input) {
|
|
32
|
+
return input.startsWith('https://github.com/') ||
|
|
33
|
+
input.startsWith('git@') ||
|
|
34
|
+
input.startsWith('https://gitlab.com/');
|
|
35
|
+
}
|
|
36
|
+
function detectLanguage(filePath) {
|
|
37
|
+
const ext = extname(filePath).toLowerCase();
|
|
38
|
+
const map = {
|
|
39
|
+
'.ts': 'typescript', '.tsx': 'typescript',
|
|
40
|
+
'.js': 'javascript', '.jsx': 'javascript',
|
|
41
|
+
'.mjs': 'javascript', '.cjs': 'javascript',
|
|
42
|
+
'.py': 'python', '.go': 'go', '.rs': 'rust', '.java': 'java',
|
|
43
|
+
};
|
|
44
|
+
return map[ext] ?? 'unknown';
|
|
45
|
+
}
|
|
46
|
+
// ── File Discovery (recursive readdir, Node 20 compatible) ───
|
|
47
|
+
async function discoverSecurityFiles(targetPath) {
|
|
48
|
+
const found = [];
|
|
49
|
+
async function walk(dir) {
|
|
50
|
+
let entries;
|
|
51
|
+
try {
|
|
52
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
for (const entry of entries) {
|
|
58
|
+
if (entry.isDirectory()) {
|
|
59
|
+
if (!IGNORED_DIRS.has(entry.name)) {
|
|
60
|
+
await walk(join(dir, entry.name));
|
|
61
|
+
}
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (!entry.isFile())
|
|
65
|
+
continue;
|
|
66
|
+
const ext = extname(entry.name).toLowerCase();
|
|
67
|
+
if (!SUPPORTED_EXTENSIONS.has(ext))
|
|
68
|
+
continue;
|
|
69
|
+
// Skip test/spec/declaration files
|
|
70
|
+
if (entry.name.includes('.test.') || entry.name.includes('.spec.') ||
|
|
71
|
+
entry.name.endsWith('.d.ts') || entry.name.endsWith('.min.js') ||
|
|
72
|
+
entry.name.endsWith('.map'))
|
|
73
|
+
continue;
|
|
74
|
+
// Check if filename matches any security keyword
|
|
75
|
+
const nameLower = entry.name.toLowerCase();
|
|
76
|
+
const matches = SECURITY_KEYWORDS.some(kw => nameLower.includes(kw));
|
|
77
|
+
if (matches) {
|
|
78
|
+
found.push(relative(targetPath, join(dir, entry.name)));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
await walk(targetPath);
|
|
83
|
+
return found.sort();
|
|
84
|
+
}
|
|
85
|
+
// ── Size Filter ──────────────────────────────────────────────
|
|
86
|
+
async function filterBySize(targetPath, files, maxLines = 500) {
|
|
87
|
+
const result = [];
|
|
88
|
+
for (const file of files) {
|
|
89
|
+
try {
|
|
90
|
+
const content = await readFile(resolve(targetPath, file), 'utf-8');
|
|
91
|
+
const lines = content.split('\n').length;
|
|
92
|
+
if (lines <= maxLines) {
|
|
93
|
+
result.push(file);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
// Unreadable files are skipped
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
export async function bountyScanCommand(target, options) {
|
|
103
|
+
const scanStart = Date.now();
|
|
104
|
+
const maxLines = parseInt(options.maxLines ?? '500', 10);
|
|
105
|
+
const maxFiles = parseInt(options.maxFiles ?? '50', 10);
|
|
106
|
+
console.log('\n╔══════════════════════════════════════════╗');
|
|
107
|
+
console.log('║ Assay Bounty Scanner ║');
|
|
108
|
+
console.log('╚══════════════════════════════════════════╝\n');
|
|
109
|
+
// Resolve target
|
|
110
|
+
let targetPath;
|
|
111
|
+
let repoName;
|
|
112
|
+
if (isGitUrl(target) && !options.noclone) {
|
|
113
|
+
repoName = target.split('/').pop()?.replace('.git', '') ?? 'repo';
|
|
114
|
+
targetPath = resolve(`/tmp/assay-bounty-${repoName}-${Date.now()}`);
|
|
115
|
+
console.log(`Cloning ${target}...`);
|
|
116
|
+
const result = safeExecSync('git', ['clone', '--shallow-since=90 days ago', target, targetPath]);
|
|
117
|
+
if (result.exitCode !== 0) {
|
|
118
|
+
console.error(`Clone failed: ${result.stderr}`);
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
targetPath = resolve(target);
|
|
124
|
+
repoName = basename(targetPath);
|
|
125
|
+
try {
|
|
126
|
+
const info = await stat(targetPath);
|
|
127
|
+
if (!info.isDirectory()) {
|
|
128
|
+
console.error(`Not a directory: ${targetPath}`);
|
|
129
|
+
process.exit(1);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
console.error(`Path not found: ${targetPath}`);
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
console.log(`Target: ${repoName} (${targetPath})\n`);
|
|
138
|
+
// Step 1: Discover security-critical files
|
|
139
|
+
console.log('[1/4] Discovering security-critical files...');
|
|
140
|
+
const allSecurityFiles = await discoverSecurityFiles(targetPath);
|
|
141
|
+
console.log(` Found ${allSecurityFiles.length} security-related files`);
|
|
142
|
+
// Step 2: Filter by size (Assay works best on 50-500 line files)
|
|
143
|
+
console.log(`[2/4] Filtering to ≤${maxLines} lines...`);
|
|
144
|
+
let files = await filterBySize(targetPath, allSecurityFiles, maxLines);
|
|
145
|
+
if (files.length > maxFiles) {
|
|
146
|
+
console.log(` Capping at ${maxFiles} files (use --max-files to increase)`);
|
|
147
|
+
files = files.slice(0, maxFiles);
|
|
148
|
+
}
|
|
149
|
+
console.log(` ${files.length} files to scan\n`);
|
|
150
|
+
if (files.length === 0) {
|
|
151
|
+
console.log('No security-critical files found within size limit.');
|
|
152
|
+
console.log('Try: --max-lines 1000 or check the target directory.');
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
// List files
|
|
156
|
+
for (const file of files) {
|
|
157
|
+
console.log(` · ${file}`);
|
|
158
|
+
}
|
|
159
|
+
console.log('');
|
|
160
|
+
// Step 3: Scan each file
|
|
161
|
+
console.log('[3/4] Scanning files...');
|
|
162
|
+
const session = new ScanSession();
|
|
163
|
+
const findings = [];
|
|
164
|
+
let totalClaims = 0;
|
|
165
|
+
let totalInputTokens = 0;
|
|
166
|
+
let totalOutputTokens = 0;
|
|
167
|
+
let filesScanned = 0;
|
|
168
|
+
let filesErrored = 0;
|
|
169
|
+
for (const file of files) {
|
|
170
|
+
const filePath = resolve(targetPath, file);
|
|
171
|
+
const language = detectLanguage(file);
|
|
172
|
+
if (language === 'unknown') {
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
let code;
|
|
176
|
+
try {
|
|
177
|
+
code = await readFile(filePath, 'utf-8');
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
filesErrored++;
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
process.stdout.write(` Scanning ${file}...`);
|
|
184
|
+
try {
|
|
185
|
+
const { result, inputTokens, outputTokens } = await forwardVerify(code, language, `Security audit of ${file} in ${repoName}. Focus on: CSRF, SSRF, injection, auth bypass, input validation, origin validation, cookie security, session management.`, session);
|
|
186
|
+
totalClaims += result.total;
|
|
187
|
+
totalInputTokens += inputTokens;
|
|
188
|
+
totalOutputTokens += outputTokens;
|
|
189
|
+
// Build a claim lookup map for joining metadata
|
|
190
|
+
const claimMap = new Map(result.claims.map(c => [c.id, c]));
|
|
191
|
+
// Collect FAIL and PARTIAL findings
|
|
192
|
+
for (const v of result.verifications) {
|
|
193
|
+
if (v.verdict === 'FAIL' || v.verdict === 'PARTIAL') {
|
|
194
|
+
const meta = claimMap.get(v.claimId);
|
|
195
|
+
const claimText = meta?.description ?? v.claimId;
|
|
196
|
+
const novelty = checkNoveltyLocal(targetPath, file, claimText);
|
|
197
|
+
findings.push({
|
|
198
|
+
file,
|
|
199
|
+
claimId: v.claimId,
|
|
200
|
+
claim: claimText,
|
|
201
|
+
verdict: v.verdict,
|
|
202
|
+
severity: meta?.severity ?? 'medium',
|
|
203
|
+
reasoning: v.reasoning,
|
|
204
|
+
evidence: file,
|
|
205
|
+
novelty: novelty.status,
|
|
206
|
+
noveltyReason: novelty.reason,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
const fails = result.verifications.filter(v => v.verdict === 'FAIL').length;
|
|
211
|
+
const partials = result.verifications.filter(v => v.verdict === 'PARTIAL').length;
|
|
212
|
+
if (fails > 0 || partials > 0) {
|
|
213
|
+
process.stdout.write(` ${result.total} claims, ${fails} FAIL, ${partials} PARTIAL\n`);
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
process.stdout.write(` ${result.total} claims, clean\n`);
|
|
217
|
+
}
|
|
218
|
+
filesScanned++;
|
|
219
|
+
}
|
|
220
|
+
catch (err) {
|
|
221
|
+
process.stdout.write(` ERROR: ${err instanceof Error ? err.message : err}\n`);
|
|
222
|
+
filesErrored++;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
console.log('');
|
|
226
|
+
// Step 4: Generate report
|
|
227
|
+
console.log('[4/4] Generating bounty report...');
|
|
228
|
+
const elapsed = Math.round((Date.now() - scanStart) / 1000);
|
|
229
|
+
// Get catalog stats after learning
|
|
230
|
+
let catalogStats = { promoted: 0, total: 0 };
|
|
231
|
+
try {
|
|
232
|
+
const stats = await getLearnedRulesSummary(targetPath);
|
|
233
|
+
catalogStats = { promoted: stats.promoted, total: stats.total };
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
// Best effort
|
|
237
|
+
}
|
|
238
|
+
// Sort findings by severity
|
|
239
|
+
const severityOrder = { critical: 0, high: 1, medium: 2, low: 3 };
|
|
240
|
+
findings.sort((a, b) => (severityOrder[a.severity] ?? 3) - (severityOrder[b.severity] ?? 3));
|
|
241
|
+
// Console report
|
|
242
|
+
console.log('\n' + '='.repeat(60));
|
|
243
|
+
console.log(` BOUNTY SCAN REPORT: ${repoName}`);
|
|
244
|
+
console.log('='.repeat(60));
|
|
245
|
+
console.log(` Files scanned: ${filesScanned}`);
|
|
246
|
+
console.log(` Files errored: ${filesErrored}`);
|
|
247
|
+
console.log(` Claims checked: ${totalClaims}`);
|
|
248
|
+
console.log(` Findings: ${findings.length}`);
|
|
249
|
+
console.log(` Rules in catalog: ${catalogStats.promoted} promoted / ${catalogStats.total} total`);
|
|
250
|
+
console.log(` Tokens: ${totalInputTokens.toLocaleString()} in / ${totalOutputTokens.toLocaleString()} out`);
|
|
251
|
+
console.log(` Duration: ${elapsed}s`);
|
|
252
|
+
console.log('='.repeat(60));
|
|
253
|
+
if (findings.length === 0) {
|
|
254
|
+
console.log('\n No findings. This target looks clean.');
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
console.log('\n FINDINGS:\n');
|
|
258
|
+
for (const f of findings) {
|
|
259
|
+
const badge = f.verdict === 'FAIL' ? '🔴' : '🟡';
|
|
260
|
+
const noveltyTag = f.novelty === 'likely-novel' ? '[LIKELY NOVEL]'
|
|
261
|
+
: f.novelty === 'likely-patched' ? '[LIKELY PATCHED]'
|
|
262
|
+
: '[CHECK MANUALLY]';
|
|
263
|
+
console.log(` ${badge} [${f.severity.toUpperCase()}] ${f.file} ${noveltyTag}`);
|
|
264
|
+
console.log(` Claim: ${f.claim}`);
|
|
265
|
+
console.log(` Reasoning: ${f.reasoning}`);
|
|
266
|
+
console.log(` Evidence: ${f.evidence}`);
|
|
267
|
+
console.log(` Novelty: ${f.noveltyReason}`);
|
|
268
|
+
console.log('');
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
// Write JSON report
|
|
272
|
+
const outputDir = options.output ?? resolve(targetPath, '.assay');
|
|
273
|
+
await mkdir(outputDir, { recursive: true });
|
|
274
|
+
const reportData = {
|
|
275
|
+
repoName,
|
|
276
|
+
target,
|
|
277
|
+
scannedAt: new Date().toISOString(),
|
|
278
|
+
durationSeconds: elapsed,
|
|
279
|
+
filesScanned,
|
|
280
|
+
filesErrored,
|
|
281
|
+
totalClaims,
|
|
282
|
+
findings,
|
|
283
|
+
catalogStats,
|
|
284
|
+
tokens: { input: totalInputTokens, output: totalOutputTokens },
|
|
285
|
+
};
|
|
286
|
+
const reportPath = resolve(outputDir, 'bounty-scan.json');
|
|
287
|
+
await writeFile(reportPath, JSON.stringify(reportData, null, 2));
|
|
288
|
+
console.log(`\n Report saved: ${reportPath}`);
|
|
289
|
+
// Write markdown report for easy sharing
|
|
290
|
+
const mdLines = [
|
|
291
|
+
`# Bounty Scan: ${repoName}`,
|
|
292
|
+
``,
|
|
293
|
+
`**Scanned:** ${new Date().toISOString()}`,
|
|
294
|
+
`**Files:** ${filesScanned} scanned, ${findings.length} findings`,
|
|
295
|
+
`**Claims:** ${totalClaims} checked`,
|
|
296
|
+
``,
|
|
297
|
+
`## Findings`,
|
|
298
|
+
``,
|
|
299
|
+
`| Severity | File | Claim | Verdict | Novelty | Reasoning |`,
|
|
300
|
+
`|----------|------|-------|---------|---------|-----------|`,
|
|
301
|
+
];
|
|
302
|
+
for (const f of findings) {
|
|
303
|
+
const claim = f.claim.replace(/\|/g, '\\|');
|
|
304
|
+
const reasoning = f.reasoning.replace(/\|/g, '\\|').slice(0, 150);
|
|
305
|
+
mdLines.push(`| ${f.severity} | ${f.file} | ${claim} | ${f.verdict} | ${f.novelty} | ${reasoning} |`);
|
|
306
|
+
}
|
|
307
|
+
mdLines.push('', `## Catalog Growth`, '', `Rules: ${catalogStats.promoted} promoted / ${catalogStats.total} total`);
|
|
308
|
+
const mdPath = resolve(outputDir, 'bounty-scan.md');
|
|
309
|
+
await writeFile(mdPath, mdLines.join('\n'));
|
|
310
|
+
console.log(` Markdown report: ${mdPath}\n`);
|
|
311
|
+
}
|
|
312
|
+
//# sourceMappingURL=bounty-scan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bounty-scan.js","sourceRoot":"","sources":["../../src/commands/bounty-scan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { resolve, extname } from 'node:path';
|
|
2
|
+
import { loadWatchlist, loadScanState, saveScanState, addRepo, removeRepo, } from '../lib/watchlist.js';
|
|
3
|
+
import { hashFinding, isDuplicate } from '../lib/finding-dedup.js';
|
|
4
|
+
import { detectChains } from '../lib/chain-analyzer.js';
|
|
5
|
+
import { safeExecSync } from '../runtime/safe-executor.js';
|
|
6
|
+
import { forwardVerify, ScanSession } from '../sdk/forward-verify.js';
|
|
7
|
+
import { checkNoveltyLocal } from '../lib/novelty-checker.js';
|
|
8
|
+
import { readFile, mkdir } from 'node:fs/promises';
|
|
9
|
+
import { existsSync } from 'node:fs';
|
|
10
|
+
import { retryWithBackoff } from '../lib/retry.js';
|
|
11
|
+
import { findExistingIssue, createFindingIssue } from '../lib/issue-reporter.js';
|
|
12
|
+
const SECURITY_KEYWORDS = [
|
|
13
|
+
'auth', 'csrf', 'cors', 'session', 'proxy', 'cookie', 'sanitiz', 'validat',
|
|
14
|
+
'encrypt', 'decrypt', 'token', 'password', 'secret', 'permission',
|
|
15
|
+
'access-control', 'rate-limit', 'xss', 'injection', 'ssrf', 'redirect',
|
|
16
|
+
'origin', 'header', 'middleware', 'security', 'firewall', 'nonce',
|
|
17
|
+
];
|
|
18
|
+
const SUPPORTED_EXTENSIONS = new Set([
|
|
19
|
+
'.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.py', '.go', '.rs', '.java',
|
|
20
|
+
]);
|
|
21
|
+
// Directories that contain test fixtures, examples, and docs — deprioritize these
|
|
22
|
+
const LOW_PRIORITY_DIRS = [
|
|
23
|
+
'fixtures/', 'examples/', 'test/', 'tests/', '__tests__/', '__mocks__/',
|
|
24
|
+
'e2e/', 'spec/', 'docs/', 'templates/', 'tools/', 'scripts/', 'cookbook/',
|
|
25
|
+
];
|
|
26
|
+
function isSecurityFile(filename) {
|
|
27
|
+
const ext = extname(filename).toLowerCase();
|
|
28
|
+
if (!SUPPORTED_EXTENSIONS.has(ext))
|
|
29
|
+
return false;
|
|
30
|
+
const lower = filename.toLowerCase();
|
|
31
|
+
return SECURITY_KEYWORDS.some(kw => lower.includes(kw));
|
|
32
|
+
}
|
|
33
|
+
/** Sort security files: real source code first, fixtures/tests/examples last */
|
|
34
|
+
function prioritizeFiles(files) {
|
|
35
|
+
const isLowPriority = (f) => LOW_PRIORITY_DIRS.some(dir => f.toLowerCase().includes(dir));
|
|
36
|
+
const high = files.filter(f => !isLowPriority(f));
|
|
37
|
+
const low = files.filter(f => isLowPriority(f));
|
|
38
|
+
return [...high, ...low];
|
|
39
|
+
}
|
|
40
|
+
function getChangedFiles(repoPath, lastSha) {
|
|
41
|
+
const result = safeExecSync('git', ['-C', repoPath, 'diff', '--name-only', `${lastSha}..HEAD`]);
|
|
42
|
+
if (result.exitCode !== 0)
|
|
43
|
+
return [];
|
|
44
|
+
return result.stdout.trim().split('\n').filter(f => f.length > 0);
|
|
45
|
+
}
|
|
46
|
+
function getCurrentSha(repoPath) {
|
|
47
|
+
const result = safeExecSync('git', ['-C', repoPath, 'rev-parse', 'HEAD']);
|
|
48
|
+
return result.exitCode === 0 ? result.stdout.trim() : null;
|
|
49
|
+
}
|
|
50
|
+
export async function bountyWatchCommand(options) {
|
|
51
|
+
const watchlistPath = resolve(options.watchlist ?? 'watchlist.json');
|
|
52
|
+
const statePath = resolve(options.stateFile ?? '.assay/scan-state.json');
|
|
53
|
+
if (options.add) {
|
|
54
|
+
const repo = { url: options.add, program: 'unknown', asset: 'unknown', source: 'manual', priority: 'normal' };
|
|
55
|
+
await addRepo(watchlistPath, repo);
|
|
56
|
+
console.log(`Added ${options.add} to watchlist`);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (options.remove) {
|
|
60
|
+
await removeRepo(watchlistPath, options.remove);
|
|
61
|
+
console.log(`Removed ${options.remove} from watchlist`);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (options.list) {
|
|
65
|
+
const config = await loadWatchlist(watchlistPath);
|
|
66
|
+
const state = await loadScanState(statePath);
|
|
67
|
+
console.log('\nWatchlist:\n');
|
|
68
|
+
for (const repo of config.repos) {
|
|
69
|
+
const repoState = state.repoStates[repo.url];
|
|
70
|
+
const lastScan = repoState?.lastScanned ?? 'never';
|
|
71
|
+
const sha = repoState?.lastSha ?? 'none';
|
|
72
|
+
console.log(` ${repo.url}`);
|
|
73
|
+
console.log(` Program: ${repo.program} | Asset: ${repo.asset}`);
|
|
74
|
+
console.log(` Last scan: ${lastScan} | SHA: ${sha.slice(0, 8)}`);
|
|
75
|
+
console.log('');
|
|
76
|
+
}
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
// Default: run one scan cycle
|
|
80
|
+
console.log('\n╔══════════════════════════════════════════╗');
|
|
81
|
+
console.log('║ Assay Bounty Watcher ║');
|
|
82
|
+
console.log('╚══════════════════════════════════════════╝\n');
|
|
83
|
+
const config = await loadWatchlist(watchlistPath);
|
|
84
|
+
const state = await loadScanState(statePath);
|
|
85
|
+
await mkdir(resolve('.assay'), { recursive: true });
|
|
86
|
+
let totalFindings = 0;
|
|
87
|
+
for (const repo of config.repos) {
|
|
88
|
+
const repoName = repo.url.split('/').pop() ?? 'repo';
|
|
89
|
+
console.log(`\n── ${repoName} ──────────────────────────`);
|
|
90
|
+
const cloneDir = resolve(`/tmp/assay-watch-${repoName}`);
|
|
91
|
+
if (existsSync(cloneDir)) {
|
|
92
|
+
// Fetch latest — use --depth 1 for shallow repos, full fetch for treeless
|
|
93
|
+
const isShallow = existsSync(resolve(cloneDir, '.git', 'shallow'));
|
|
94
|
+
if (isShallow) {
|
|
95
|
+
safeExecSync('git', ['-C', cloneDir, 'fetch', '--depth', '1', 'origin']);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
safeExecSync('git', ['-C', cloneDir, 'fetch', 'origin']);
|
|
99
|
+
}
|
|
100
|
+
safeExecSync('git', ['-C', cloneDir, 'reset', '--hard', 'origin/HEAD']);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
// Try treeless clone first (fast, keeps commit graph for diffing)
|
|
104
|
+
let cloneResult = safeExecSync('git', ['clone', '--filter=blob:none', '--single-branch', repo.url, cloneDir]);
|
|
105
|
+
if (cloneResult.exitCode !== 0) {
|
|
106
|
+
// Treeless clone failed (repo too large) — fall back to shallow depth-1 clone
|
|
107
|
+
// This loses diff capability but at least gets us the current files
|
|
108
|
+
console.log(' Treeless clone failed, trying shallow clone...');
|
|
109
|
+
cloneResult = safeExecSync('git', ['clone', '--depth', '1', '--single-branch', repo.url, cloneDir]);
|
|
110
|
+
if (cloneResult.exitCode !== 0) {
|
|
111
|
+
console.log(` ERROR: Clone failed, skipping`);
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const currentSha = getCurrentSha(cloneDir);
|
|
117
|
+
if (!currentSha) {
|
|
118
|
+
console.log(' ERROR: Could not determine HEAD SHA, skipping');
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
const repoState = state.repoStates[repo.url];
|
|
122
|
+
const lastSha = repoState?.lastSha;
|
|
123
|
+
let changedFiles = [];
|
|
124
|
+
if (!lastSha || repo.priority === 'fresh') {
|
|
125
|
+
console.log(' First scan or fresh priority — scanning all security files');
|
|
126
|
+
const lsResult = safeExecSync('git', ['-C', cloneDir, 'ls-files']);
|
|
127
|
+
changedFiles = lsResult.stdout.trim().split('\n');
|
|
128
|
+
}
|
|
129
|
+
else if (lastSha === currentSha) {
|
|
130
|
+
console.log(' No new commits since last scan');
|
|
131
|
+
state.repoStates[repo.url] = { lastSha: currentSha, lastScanned: new Date().toISOString() };
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
changedFiles = getChangedFiles(cloneDir, lastSha);
|
|
136
|
+
console.log(` ${changedFiles.length} files changed since ${lastSha.slice(0, 8)}`);
|
|
137
|
+
}
|
|
138
|
+
const securityFiles = prioritizeFiles(changedFiles.filter(isSecurityFile));
|
|
139
|
+
console.log(` ${securityFiles.length} security-relevant files to scan`);
|
|
140
|
+
if (securityFiles.length === 0) {
|
|
141
|
+
state.repoStates[repo.url] = { lastSha: currentSha, lastScanned: new Date().toISOString() };
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
if (options.dryRun) {
|
|
145
|
+
console.log(' [DRY RUN] Would scan:');
|
|
146
|
+
for (const f of securityFiles) {
|
|
147
|
+
console.log(` · ${f}`);
|
|
148
|
+
}
|
|
149
|
+
state.repoStates[repo.url] = { lastSha: currentSha, lastScanned: new Date().toISOString() };
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
const session = new ScanSession();
|
|
153
|
+
const findings = [];
|
|
154
|
+
for (const file of securityFiles.slice(0, 20)) {
|
|
155
|
+
try {
|
|
156
|
+
const code = await readFile(resolve(cloneDir, file), 'utf-8');
|
|
157
|
+
if (code.split('\n').length > 500)
|
|
158
|
+
continue;
|
|
159
|
+
const ext = extname(file).toLowerCase();
|
|
160
|
+
const langMap = { '.ts': 'typescript', '.tsx': 'typescript', '.js': 'javascript', '.jsx': 'javascript', '.py': 'python', '.go': 'go', '.rs': 'rust' };
|
|
161
|
+
const language = langMap[ext];
|
|
162
|
+
if (!language)
|
|
163
|
+
continue;
|
|
164
|
+
const { result } = await retryWithBackoff(() => forwardVerify(code, language, `Security audit of ${file} in ${repoName}. Focus on CSRF, SSRF, injection, auth bypass, CORS, XSS.`, session), { maxRetries: 3, baseDelayMs: 1000 });
|
|
165
|
+
const claimMap = new Map(result.claims.map(c => [c.id, c]));
|
|
166
|
+
for (const v of result.verifications) {
|
|
167
|
+
if (v.verdict === 'FAIL' || v.verdict === 'PARTIAL') {
|
|
168
|
+
const meta = claimMap.get(v.claimId);
|
|
169
|
+
findings.push({ file, claimId: v.claimId, claim: meta?.description ?? v.claimId, verdict: v.verdict, severity: meta?.severity ?? 'medium', reasoning: v.reasoning, evidence: file });
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
catch { /* skip unreadable files */ }
|
|
174
|
+
}
|
|
175
|
+
console.log(` ${findings.length} findings`);
|
|
176
|
+
for (const f of findings) {
|
|
177
|
+
const novelty = checkNoveltyLocal(cloneDir, f.file, f.claim);
|
|
178
|
+
if (novelty.status === 'likely-patched')
|
|
179
|
+
continue;
|
|
180
|
+
const hash = hashFinding(repo.url, f.file, f.claim);
|
|
181
|
+
if (isDuplicate(hash, state.reportedFindings))
|
|
182
|
+
continue;
|
|
183
|
+
console.log(` 🔴 [${f.severity.toUpperCase()}] ${f.file}: ${f.claim.slice(0, 80)}`);
|
|
184
|
+
state.reportedFindings.push(hash);
|
|
185
|
+
totalFindings++;
|
|
186
|
+
// Create GitHub Issue if not already reported
|
|
187
|
+
const hashPrefix = hash.slice(0, 8);
|
|
188
|
+
if (!findExistingIssue(hashPrefix)) {
|
|
189
|
+
createFindingIssue({
|
|
190
|
+
repo: repo.url,
|
|
191
|
+
program: repo.program,
|
|
192
|
+
asset: repo.asset,
|
|
193
|
+
file: f.file,
|
|
194
|
+
claim: f.claim,
|
|
195
|
+
severity: f.severity,
|
|
196
|
+
reasoning: f.reasoning,
|
|
197
|
+
}, hashPrefix);
|
|
198
|
+
console.log(` → GitHub Issue created`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
const chains = detectChains(findings);
|
|
202
|
+
for (const chain of chains) {
|
|
203
|
+
console.log(` ⛓️ CHAIN ${chain.chainId}: ${chain.findingA.file} + ${chain.findingB.file} → ${chain.impact}`);
|
|
204
|
+
}
|
|
205
|
+
state.repoStates[repo.url] = { lastSha: currentSha, lastScanned: new Date().toISOString() };
|
|
206
|
+
}
|
|
207
|
+
await saveScanState(statePath, state);
|
|
208
|
+
console.log(`\nCycle complete. ${totalFindings} new finding(s). State saved.`);
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=bounty-watch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bounty-watch.js","sourceRoot":"","sources":["../../src/commands/bounty-watch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface HuntCommandOptions {
|
|
2
|
+
dive?: string;
|
|
3
|
+
auto?: boolean;
|
|
4
|
+
template?: string;
|
|
5
|
+
json?: boolean;
|
|
6
|
+
minConfidence?: 'high' | 'medium' | 'low';
|
|
7
|
+
concurrency?: string;
|
|
8
|
+
stateDir?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function huntCommand(target: string, opts: HuntCommandOptions): Promise<void>;
|
|
11
|
+
export {};
|