tryassay 0.31.0 → 0.33.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.
Files changed (165) hide show
  1. package/dist/cli.js +55 -0
  2. package/dist/cli.js.map +1 -1
  3. package/dist/commands/assess.js +73 -0
  4. package/dist/commands/assess.js.map +1 -1
  5. package/dist/commands/bounty-chain.d.ts +1 -0
  6. package/dist/commands/bounty-chain.js +34 -0
  7. package/dist/commands/bounty-chain.js.map +1 -0
  8. package/dist/commands/bounty-check.d.ts +10 -0
  9. package/dist/commands/bounty-check.js +104 -0
  10. package/dist/commands/bounty-check.js.map +1 -0
  11. package/dist/commands/bounty-discover.d.ts +6 -0
  12. package/dist/commands/bounty-discover.js +45 -0
  13. package/dist/commands/bounty-discover.js.map +1 -0
  14. package/dist/commands/bounty-scan.d.ts +7 -0
  15. package/dist/commands/bounty-scan.js +312 -0
  16. package/dist/commands/bounty-scan.js.map +1 -0
  17. package/dist/commands/bounty-watch.d.ts +9 -0
  18. package/dist/commands/bounty-watch.js +210 -0
  19. package/dist/commands/bounty-watch.js.map +1 -0
  20. package/dist/commands/hunt.d.ts +11 -0
  21. package/dist/commands/hunt.js +216 -0
  22. package/dist/commands/hunt.js.map +1 -0
  23. package/dist/hunt/__tests__/deep-dive.test.d.ts +1 -0
  24. package/dist/hunt/__tests__/deep-dive.test.js +102 -0
  25. package/dist/hunt/__tests__/deep-dive.test.js.map +1 -0
  26. package/dist/hunt/__tests__/discovery.test.d.ts +1 -0
  27. package/dist/hunt/__tests__/discovery.test.js +55 -0
  28. package/dist/hunt/__tests__/discovery.test.js.map +1 -0
  29. package/dist/hunt/__tests__/e2e.test.d.ts +1 -0
  30. package/dist/hunt/__tests__/e2e.test.js +261 -0
  31. package/dist/hunt/__tests__/e2e.test.js.map +1 -0
  32. package/dist/hunt/__tests__/matcher.test.d.ts +1 -0
  33. package/dist/hunt/__tests__/matcher.test.js +63 -0
  34. package/dist/hunt/__tests__/matcher.test.js.map +1 -0
  35. package/dist/hunt/__tests__/orchestrator.test.d.ts +1 -0
  36. package/dist/hunt/__tests__/orchestrator.test.js +73 -0
  37. package/dist/hunt/__tests__/orchestrator.test.js.map +1 -0
  38. package/dist/hunt/__tests__/parse-utils.test.d.ts +1 -0
  39. package/dist/hunt/__tests__/parse-utils.test.js +28 -0
  40. package/dist/hunt/__tests__/parse-utils.test.js.map +1 -0
  41. package/dist/hunt/__tests__/state.test.d.ts +1 -0
  42. package/dist/hunt/__tests__/state.test.js +49 -0
  43. package/dist/hunt/__tests__/state.test.js.map +1 -0
  44. package/dist/hunt/__tests__/templates.test.d.ts +1 -0
  45. package/dist/hunt/__tests__/templates.test.js +32 -0
  46. package/dist/hunt/__tests__/templates.test.js.map +1 -0
  47. package/dist/hunt/__tests__/triage.test.d.ts +1 -0
  48. package/dist/hunt/__tests__/triage.test.js +91 -0
  49. package/dist/hunt/__tests__/triage.test.js.map +1 -0
  50. package/dist/hunt/__tests__/types.test.d.ts +1 -0
  51. package/dist/hunt/__tests__/types.test.js +65 -0
  52. package/dist/hunt/__tests__/types.test.js.map +1 -0
  53. package/dist/hunt/deep-dive.d.ts +8 -0
  54. package/dist/hunt/deep-dive.js +86 -0
  55. package/dist/hunt/deep-dive.js.map +1 -0
  56. package/dist/hunt/discovery.d.ts +15 -0
  57. package/dist/hunt/discovery.js +116 -0
  58. package/dist/hunt/discovery.js.map +1 -0
  59. package/dist/hunt/matcher.d.ts +8 -0
  60. package/dist/hunt/matcher.js +27 -0
  61. package/dist/hunt/matcher.js.map +1 -0
  62. package/dist/hunt/orchestrator.d.ts +27 -0
  63. package/dist/hunt/orchestrator.js +91 -0
  64. package/dist/hunt/orchestrator.js.map +1 -0
  65. package/dist/hunt/parse-utils.d.ts +2 -0
  66. package/dist/hunt/parse-utils.js +17 -0
  67. package/dist/hunt/parse-utils.js.map +1 -0
  68. package/dist/hunt/state.d.ts +5 -0
  69. package/dist/hunt/state.js +35 -0
  70. package/dist/hunt/state.js.map +1 -0
  71. package/dist/hunt/templates/auth-bypass.d.ts +2 -0
  72. package/dist/hunt/templates/auth-bypass.js +80 -0
  73. package/dist/hunt/templates/auth-bypass.js.map +1 -0
  74. package/dist/hunt/templates/cors-misconfig.d.ts +2 -0
  75. package/dist/hunt/templates/cors-misconfig.js +88 -0
  76. package/dist/hunt/templates/cors-misconfig.js.map +1 -0
  77. package/dist/hunt/templates/csrf-bypass.d.ts +2 -0
  78. package/dist/hunt/templates/csrf-bypass.js +65 -0
  79. package/dist/hunt/templates/csrf-bypass.js.map +1 -0
  80. package/dist/hunt/templates/index.d.ts +3 -0
  81. package/dist/hunt/templates/index.js +29 -0
  82. package/dist/hunt/templates/index.js.map +1 -0
  83. package/dist/hunt/templates/injection.d.ts +2 -0
  84. package/dist/hunt/templates/injection.js +103 -0
  85. package/dist/hunt/templates/injection.js.map +1 -0
  86. package/dist/hunt/templates/open-redirect.d.ts +2 -0
  87. package/dist/hunt/templates/open-redirect.js +93 -0
  88. package/dist/hunt/templates/open-redirect.js.map +1 -0
  89. package/dist/hunt/templates/path-traversal.d.ts +2 -0
  90. package/dist/hunt/templates/path-traversal.js +94 -0
  91. package/dist/hunt/templates/path-traversal.js.map +1 -0
  92. package/dist/hunt/templates/prototype-pollution.d.ts +2 -0
  93. package/dist/hunt/templates/prototype-pollution.js +108 -0
  94. package/dist/hunt/templates/prototype-pollution.js.map +1 -0
  95. package/dist/hunt/templates/ssrf.d.ts +2 -0
  96. package/dist/hunt/templates/ssrf.js +75 -0
  97. package/dist/hunt/templates/ssrf.js.map +1 -0
  98. package/dist/hunt/templates/timing-attack.d.ts +2 -0
  99. package/dist/hunt/templates/timing-attack.js +108 -0
  100. package/dist/hunt/templates/timing-attack.js.map +1 -0
  101. package/dist/hunt/templates/weak-random.d.ts +2 -0
  102. package/dist/hunt/templates/weak-random.js +73 -0
  103. package/dist/hunt/templates/weak-random.js.map +1 -0
  104. package/dist/hunt/triage.d.ts +8 -0
  105. package/dist/hunt/triage.js +78 -0
  106. package/dist/hunt/triage.js.map +1 -0
  107. package/dist/lib/__tests__/bounty-scan.test.d.ts +1 -0
  108. package/dist/lib/__tests__/bounty-scan.test.js +15 -0
  109. package/dist/lib/__tests__/bounty-scan.test.js.map +1 -0
  110. package/dist/lib/__tests__/chain-analyzer.test.d.ts +1 -0
  111. package/dist/lib/__tests__/chain-analyzer.test.js +47 -0
  112. package/dist/lib/__tests__/chain-analyzer.test.js.map +1 -0
  113. package/dist/lib/__tests__/change-classifier.test.d.ts +1 -0
  114. package/dist/lib/__tests__/change-classifier.test.js +55 -0
  115. package/dist/lib/__tests__/change-classifier.test.js.map +1 -0
  116. package/dist/lib/__tests__/finding-dedup.test.d.ts +1 -0
  117. package/dist/lib/__tests__/finding-dedup.test.js +30 -0
  118. package/dist/lib/__tests__/finding-dedup.test.js.map +1 -0
  119. package/dist/lib/__tests__/learned-rules.test.js +25 -0
  120. package/dist/lib/__tests__/learned-rules.test.js.map +1 -1
  121. package/dist/lib/__tests__/novelty-checker.test.d.ts +1 -0
  122. package/dist/lib/__tests__/novelty-checker.test.js +57 -0
  123. package/dist/lib/__tests__/novelty-checker.test.js.map +1 -0
  124. package/dist/lib/__tests__/program-registry.test.d.ts +1 -0
  125. package/dist/lib/__tests__/program-registry.test.js +40 -0
  126. package/dist/lib/__tests__/program-registry.test.js.map +1 -0
  127. package/dist/lib/__tests__/retry.test.d.ts +1 -0
  128. package/dist/lib/__tests__/retry.test.js +23 -0
  129. package/dist/lib/__tests__/retry.test.js.map +1 -0
  130. package/dist/lib/__tests__/watchlist.test.d.ts +1 -0
  131. package/dist/lib/__tests__/watchlist.test.js +88 -0
  132. package/dist/lib/__tests__/watchlist.test.js.map +1 -0
  133. package/dist/lib/chain-analyzer.d.ts +25 -0
  134. package/dist/lib/chain-analyzer.js +105 -0
  135. package/dist/lib/chain-analyzer.js.map +1 -0
  136. package/dist/lib/change-classifier.d.ts +3 -0
  137. package/dist/lib/change-classifier.js +97 -0
  138. package/dist/lib/change-classifier.js.map +1 -0
  139. package/dist/lib/finding-dedup.d.ts +2 -0
  140. package/dist/lib/finding-dedup.js +9 -0
  141. package/dist/lib/finding-dedup.js.map +1 -0
  142. package/dist/lib/issue-reporter.d.ts +13 -0
  143. package/dist/lib/issue-reporter.js +51 -0
  144. package/dist/lib/issue-reporter.js.map +1 -0
  145. package/dist/lib/novelty-checker.d.ts +60 -0
  146. package/dist/lib/novelty-checker.js +223 -0
  147. package/dist/lib/novelty-checker.js.map +1 -0
  148. package/dist/lib/program-registry.d.ts +12 -0
  149. package/dist/lib/program-registry.js +18 -0
  150. package/dist/lib/program-registry.js.map +1 -0
  151. package/dist/lib/retry.d.ts +5 -0
  152. package/dist/lib/retry.js +19 -0
  153. package/dist/lib/retry.js.map +1 -0
  154. package/dist/lib/watchlist.d.ts +23 -0
  155. package/dist/lib/watchlist.js +31 -0
  156. package/dist/lib/watchlist.js.map +1 -0
  157. package/dist/runtime/safe-executor.js +1 -1
  158. package/dist/runtime/safe-executor.js.map +1 -1
  159. package/dist/runtime/types.d.ts +1 -1
  160. package/dist/sdk/forward-verify.d.ts +2 -2
  161. package/dist/sdk/forward-verify.js +31 -2
  162. package/dist/sdk/forward-verify.js.map +1 -1
  163. package/dist/sdk/types.d.ts +8 -0
  164. package/dist/types.d.ts +45 -0
  165. 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,9 @@
1
+ export interface BountyWatchOptions {
2
+ add?: string;
3
+ remove?: string;
4
+ list?: boolean;
5
+ dryRun?: boolean;
6
+ watchlist?: string;
7
+ stateFile?: string;
8
+ }
9
+ export declare function bountyWatchCommand(options: BountyWatchOptions): Promise<void>;
@@ -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 {};