tryassay 0.33.1 → 0.34.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 (126) hide show
  1. package/dist/cli.js +20 -0
  2. package/dist/cli.js.map +1 -1
  3. package/dist/commands/hunt.d.ts +2 -0
  4. package/dist/commands/hunt.js +58 -7
  5. package/dist/commands/hunt.js.map +1 -1
  6. package/dist/commands/mcp.d.ts +14 -0
  7. package/dist/commands/mcp.js +18 -0
  8. package/dist/commands/mcp.js.map +1 -0
  9. package/dist/commands/watch.d.ts +19 -0
  10. package/dist/commands/watch.js +158 -0
  11. package/dist/commands/watch.js.map +1 -0
  12. package/dist/hunt/__tests__/finding-to-template.test.d.ts +1 -0
  13. package/dist/hunt/__tests__/finding-to-template.test.js +213 -0
  14. package/dist/hunt/__tests__/finding-to-template.test.js.map +1 -0
  15. package/dist/hunt/__tests__/parse-utils.test.js +28 -1
  16. package/dist/hunt/__tests__/parse-utils.test.js.map +1 -1
  17. package/dist/hunt/__tests__/taint-analysis.test.d.ts +1 -0
  18. package/dist/hunt/__tests__/taint-analysis.test.js +556 -0
  19. package/dist/hunt/__tests__/taint-analysis.test.js.map +1 -0
  20. package/dist/hunt/__tests__/templates.test.js +2 -2
  21. package/dist/hunt/__tests__/templates.test.js.map +1 -1
  22. package/dist/hunt/deep-dive.d.ts +2 -2
  23. package/dist/hunt/deep-dive.js +4 -4
  24. package/dist/hunt/deep-dive.js.map +1 -1
  25. package/dist/hunt/discovery.js +2 -2
  26. package/dist/hunt/discovery.js.map +1 -1
  27. package/dist/hunt/finding-to-template.d.ts +47 -0
  28. package/dist/hunt/finding-to-template.js +288 -0
  29. package/dist/hunt/finding-to-template.js.map +1 -0
  30. package/dist/hunt/orchestrator.d.ts +3 -0
  31. package/dist/hunt/orchestrator.js +20 -5
  32. package/dist/hunt/orchestrator.js.map +1 -1
  33. package/dist/hunt/taint-analysis.d.ts +49 -0
  34. package/dist/hunt/taint-analysis.js +429 -0
  35. package/dist/hunt/taint-analysis.js.map +1 -0
  36. package/dist/hunt/templates/csv-injection.d.ts +2 -0
  37. package/dist/hunt/templates/csv-injection.js +148 -0
  38. package/dist/hunt/templates/csv-injection.js.map +1 -0
  39. package/dist/hunt/templates/django-misconfig.d.ts +2 -0
  40. package/dist/hunt/templates/django-misconfig.js +172 -0
  41. package/dist/hunt/templates/django-misconfig.js.map +1 -0
  42. package/dist/hunt/templates/express-misconfig.d.ts +2 -0
  43. package/dist/hunt/templates/express-misconfig.js +156 -0
  44. package/dist/hunt/templates/express-misconfig.js.map +1 -0
  45. package/dist/hunt/templates/file-upload.d.ts +2 -0
  46. package/dist/hunt/templates/file-upload.js +131 -0
  47. package/dist/hunt/templates/file-upload.js.map +1 -0
  48. package/dist/hunt/templates/graphql-abuse.d.ts +2 -0
  49. package/dist/hunt/templates/graphql-abuse.js +161 -0
  50. package/dist/hunt/templates/graphql-abuse.js.map +1 -0
  51. package/dist/hunt/templates/hardcoded-credentials.d.ts +2 -0
  52. package/dist/hunt/templates/hardcoded-credentials.js +109 -0
  53. package/dist/hunt/templates/hardcoded-credentials.js.map +1 -0
  54. package/dist/hunt/templates/idor.d.ts +2 -0
  55. package/dist/hunt/templates/idor.js +102 -0
  56. package/dist/hunt/templates/idor.js.map +1 -0
  57. package/dist/hunt/templates/index.d.ts +2 -2
  58. package/dist/hunt/templates/index.js +38 -5
  59. package/dist/hunt/templates/index.js.map +1 -1
  60. package/dist/hunt/templates/insecure-deserialization.d.ts +2 -0
  61. package/dist/hunt/templates/insecure-deserialization.js +131 -0
  62. package/dist/hunt/templates/insecure-deserialization.js.map +1 -0
  63. package/dist/hunt/templates/mass-assignment.d.ts +2 -0
  64. package/dist/hunt/templates/mass-assignment.js +101 -0
  65. package/dist/hunt/templates/mass-assignment.js.map +1 -0
  66. package/dist/hunt/templates/nextjs-misconfig.d.ts +2 -0
  67. package/dist/hunt/templates/nextjs-misconfig.js +127 -0
  68. package/dist/hunt/templates/nextjs-misconfig.js.map +1 -0
  69. package/dist/hunt/templates/postmessage.d.ts +2 -0
  70. package/dist/hunt/templates/postmessage.js +180 -0
  71. package/dist/hunt/templates/postmessage.js.map +1 -0
  72. package/dist/hunt/templates/race-condition.d.ts +2 -0
  73. package/dist/hunt/templates/race-condition.js +138 -0
  74. package/dist/hunt/templates/race-condition.js.map +1 -0
  75. package/dist/hunt/templates/spring-misconfig.d.ts +2 -0
  76. package/dist/hunt/templates/spring-misconfig.js +177 -0
  77. package/dist/hunt/templates/spring-misconfig.js.map +1 -0
  78. package/dist/hunt/templates/xxe.d.ts +2 -0
  79. package/dist/hunt/templates/xxe.js +187 -0
  80. package/dist/hunt/templates/xxe.js.map +1 -0
  81. package/dist/hunt/triage.d.ts +2 -2
  82. package/dist/hunt/triage.js +4 -4
  83. package/dist/hunt/triage.js.map +1 -1
  84. package/dist/realtime/__tests__/catch-real-bugs.test.d.ts +9 -0
  85. package/dist/realtime/__tests__/catch-real-bugs.test.js +205 -0
  86. package/dist/realtime/__tests__/catch-real-bugs.test.js.map +1 -0
  87. package/dist/realtime/__tests__/code-buffer.test.d.ts +1 -0
  88. package/dist/realtime/__tests__/code-buffer.test.js +202 -0
  89. package/dist/realtime/__tests__/code-buffer.test.js.map +1 -0
  90. package/dist/realtime/__tests__/correction-injector.test.d.ts +1 -0
  91. package/dist/realtime/__tests__/correction-injector.test.js +168 -0
  92. package/dist/realtime/__tests__/correction-injector.test.js.map +1 -0
  93. package/dist/realtime/__tests__/stream-interceptor.test.d.ts +1 -0
  94. package/dist/realtime/__tests__/stream-interceptor.test.js +193 -0
  95. package/dist/realtime/__tests__/stream-interceptor.test.js.map +1 -0
  96. package/dist/realtime/__tests__/streaming-checks.test.d.ts +1 -0
  97. package/dist/realtime/__tests__/streaming-checks.test.js +479 -0
  98. package/dist/realtime/__tests__/streaming-checks.test.js.map +1 -0
  99. package/dist/realtime/__tests__/streaming-verifier.test.d.ts +1 -0
  100. package/dist/realtime/__tests__/streaming-verifier.test.js +157 -0
  101. package/dist/realtime/__tests__/streaming-verifier.test.js.map +1 -0
  102. package/dist/realtime/code-buffer.d.ts +52 -0
  103. package/dist/realtime/code-buffer.js +276 -0
  104. package/dist/realtime/code-buffer.js.map +1 -0
  105. package/dist/realtime/correction-injector.d.ts +56 -0
  106. package/dist/realtime/correction-injector.js +96 -0
  107. package/dist/realtime/correction-injector.js.map +1 -0
  108. package/dist/realtime/index.d.ts +14 -0
  109. package/dist/realtime/index.js +11 -0
  110. package/dist/realtime/index.js.map +1 -0
  111. package/dist/realtime/mcp-server.d.ts +14 -0
  112. package/dist/realtime/mcp-server.js +200 -0
  113. package/dist/realtime/mcp-server.js.map +1 -0
  114. package/dist/realtime/stream-interceptor.d.ts +65 -0
  115. package/dist/realtime/stream-interceptor.js +174 -0
  116. package/dist/realtime/stream-interceptor.js.map +1 -0
  117. package/dist/realtime/streaming-checks.d.ts +55 -0
  118. package/dist/realtime/streaming-checks.js +452 -0
  119. package/dist/realtime/streaming-checks.js.map +1 -0
  120. package/dist/realtime/streaming-verifier.d.ts +57 -0
  121. package/dist/realtime/streaming-verifier.js +134 -0
  122. package/dist/realtime/streaming-verifier.js.map +1 -0
  123. package/dist/realtime/types.d.ts +99 -0
  124. package/dist/realtime/types.js +8 -0
  125. package/dist/realtime/types.js.map +1 -0
  126. package/package.json +2 -1
@@ -0,0 +1,479 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { getFormalChecks, loadLearnedChecks, compileCheckSet, runChecks, _deriveContextKeywords, _extractRegexLiterals, } from '../streaming-checks.js';
3
+ // ── Helpers ─────────────────────────────────────────────────────
4
+ function makeUnit(text, language = 'typescript') {
5
+ return {
6
+ text,
7
+ kind: 'statement',
8
+ startOffset: 0,
9
+ endOffset: text.length,
10
+ language,
11
+ };
12
+ }
13
+ function findingIds(unit, checkSet) {
14
+ return runChecks(unit, checkSet)
15
+ .filter(e => e.verdict === 'FAIL')
16
+ .map(e => e.checkId);
17
+ }
18
+ // ── getFormalChecks ─────────────────────────────────────────────
19
+ describe('getFormalChecks', () => {
20
+ it('returns a non-empty array of StreamingCheck objects', () => {
21
+ const checks = getFormalChecks();
22
+ expect(checks.length).toBeGreaterThan(0);
23
+ for (const check of checks) {
24
+ expect(check.id).toBeTruthy();
25
+ expect(check.name).toBeTruthy();
26
+ expect(check.pattern).toBeInstanceOf(RegExp);
27
+ expect(['FAIL', 'PASS']).toContain(check.verdict);
28
+ expect(['critical', 'high', 'medium', 'low']).toContain(check.severity);
29
+ expect(check.source).toBe('formal');
30
+ }
31
+ });
32
+ it('returns the same array reference on repeated calls (no re-creation)', () => {
33
+ const a = getFormalChecks();
34
+ const b = getFormalChecks();
35
+ expect(a).toBe(b);
36
+ });
37
+ });
38
+ // ── SQL Injection Detection ─────────────────────────────────────
39
+ describe('SQL injection detection', () => {
40
+ const checkSet = compileCheckSet('typescript');
41
+ it('detects string concatenation in SQL queries', () => {
42
+ const unit = makeUnit('const q = "SELECT * FROM users WHERE id = " + id');
43
+ const ids = findingIds(unit, checkSet);
44
+ expect(ids).toContain('sql_concat_injection');
45
+ });
46
+ it('detects template literal interpolation in SQL queries', () => {
47
+ const unit = makeUnit('const q = `SELECT * FROM users WHERE id = ${userId}`');
48
+ const ids = findingIds(unit, checkSet);
49
+ expect(ids).toContain('sql_template_injection');
50
+ });
51
+ it('does NOT flag parameterized queries', () => {
52
+ const unit = makeUnit('db.query("SELECT * FROM users WHERE id = $1", [id])');
53
+ const ids = findingIds(unit, checkSet);
54
+ expect(ids).not.toContain('sql_concat_injection');
55
+ expect(ids).not.toContain('sql_template_injection');
56
+ });
57
+ });
58
+ // ── Missing Error Handling ──────────────────────────────────────
59
+ describe('missing error handling', () => {
60
+ const checkSet = compileCheckSet('typescript');
61
+ it('detects fetch().then() without .catch()', () => {
62
+ const unit = makeUnit('fetch(url).then(r => r.json())');
63
+ const ids = findingIds(unit, checkSet);
64
+ expect(ids).toContain('unhandled_promise');
65
+ });
66
+ it('does NOT flag fetch().then().catch()', () => {
67
+ const unit = makeUnit('fetch(url).then(r => r.json()).catch(e => console.error(e))');
68
+ const ids = findingIds(unit, checkSet);
69
+ expect(ids).not.toContain('unhandled_promise');
70
+ });
71
+ });
72
+ // ── Hardcoded Secrets ───────────────────────────────────────────
73
+ describe('hardcoded secret detection', () => {
74
+ const checkSet = compileCheckSet('typescript');
75
+ it('detects hardcoded API key', () => {
76
+ const unit = makeUnit('const API_KEY = "sk-abc123456789abcdef"');
77
+ const ids = findingIds(unit, checkSet);
78
+ expect(ids).toContain('hardcoded_secret');
79
+ });
80
+ it('detects hardcoded GitHub token', () => {
81
+ const unit = makeUnit('const token = "ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"');
82
+ const ids = findingIds(unit, checkSet);
83
+ expect(ids).toContain('hardcoded_secret');
84
+ });
85
+ it('does NOT flag environment variable usage', () => {
86
+ const unit = makeUnit('const apiKey = process.env.API_KEY');
87
+ const ids = findingIds(unit, checkSet);
88
+ expect(ids).not.toContain('hardcoded_secret');
89
+ });
90
+ });
91
+ // ── Eval Usage ──────────────────────────────────────────────────
92
+ describe('eval detection', () => {
93
+ const checkSet = compileCheckSet('typescript');
94
+ it('detects eval(userInput)', () => {
95
+ const unit = makeUnit('eval(userInput)');
96
+ const ids = findingIds(unit, checkSet);
97
+ expect(ids).toContain('unsafe_eval');
98
+ });
99
+ it('detects new Function() usage', () => {
100
+ const unit = makeUnit('const fn = new Function("return " + code)');
101
+ const ids = findingIds(unit, checkSet);
102
+ expect(ids).toContain('unsafe_function_constructor');
103
+ });
104
+ });
105
+ // ── Insecure Randomness ─────────────────────────────────────────
106
+ describe('insecure randomness detection', () => {
107
+ const checkSet = compileCheckSet('typescript');
108
+ it('detects Math.random() for token generation', () => {
109
+ const unit = makeUnit('const token = Math.random().toString(36)');
110
+ const ids = findingIds(unit, checkSet);
111
+ expect(ids).toContain('insecure_random_token');
112
+ });
113
+ it('detects Math.random() in security context', () => {
114
+ const unit = makeUnit('const sessionToken = "sess_" + Math.random()');
115
+ const ids = findingIds(unit, checkSet);
116
+ expect(ids).toContain('insecure_random');
117
+ });
118
+ });
119
+ // ── Path Traversal ──────────────────────────────────────────────
120
+ describe('path traversal detection', () => {
121
+ const checkSet = compileCheckSet('typescript');
122
+ it('detects readFile with req.params', () => {
123
+ const unit = makeUnit('fs.readFileSync(req.params.path)');
124
+ const ids = findingIds(unit, checkSet);
125
+ expect(ids).toContain('path_traversal');
126
+ });
127
+ it('does NOT flag readFile with a constant path', () => {
128
+ const unit = makeUnit('fs.readFileSync("./config.json")');
129
+ const ids = findingIds(unit, checkSet);
130
+ expect(ids).not.toContain('path_traversal');
131
+ });
132
+ });
133
+ // ── Command Injection ───────────────────────────────────────────
134
+ describe('command injection detection', () => {
135
+ const checkSet = compileCheckSet('typescript');
136
+ it('detects exec with string concatenation', () => {
137
+ const unit = makeUnit('exec("rm " + filename)');
138
+ const ids = findingIds(unit, checkSet);
139
+ expect(ids).toContain('command_injection');
140
+ });
141
+ it('detects exec with template literal interpolation', () => {
142
+ const unit = makeUnit('exec(`ls ${dir}`)');
143
+ const ids = findingIds(unit, checkSet);
144
+ expect(ids).toContain('command_injection');
145
+ });
146
+ it('does NOT flag execFile with argument array', () => {
147
+ const unit = makeUnit('execFile("ls", ["-la", dir])');
148
+ const ids = findingIds(unit, checkSet);
149
+ expect(ids).not.toContain('command_injection');
150
+ });
151
+ });
152
+ // ── Language Filtering ──────────────────────────────────────────
153
+ describe('compileCheckSet language filtering', () => {
154
+ it('filters TypeScript checks out of Python check set', () => {
155
+ const tsSet = compileCheckSet('typescript');
156
+ const pySet = compileCheckSet('python');
157
+ // JS-only checks like unhandled_promise should not be in Python set
158
+ const pyIds = pySet.checks.map(c => c.id);
159
+ expect(pyIds).not.toContain('unhandled_promise');
160
+ expect(pyIds).not.toContain('unsafe_eval');
161
+ // But cross-language checks like path_traversal should be in both
162
+ const tsIds = tsSet.checks.map(c => c.id);
163
+ expect(tsIds).toContain('path_traversal');
164
+ expect(pyIds).toContain('path_traversal');
165
+ });
166
+ it('includes all-language checks for any language', () => {
167
+ const goSet = compileCheckSet('go');
168
+ const goIds = goSet.checks.map(c => c.id);
169
+ // hardcoded_secret has empty languages array (applies to all)
170
+ expect(goIds).toContain('hardcoded_secret');
171
+ });
172
+ it('tracks compileTimeMs', () => {
173
+ const set = compileCheckSet('typescript');
174
+ expect(set.compileTimeMs).toBeGreaterThanOrEqual(0);
175
+ expect(set.language).toBe('typescript');
176
+ });
177
+ });
178
+ // ── Learned Rules Loading ───────────────────────────────────────
179
+ describe('loadLearnedChecks', () => {
180
+ it('returns empty array for non-existent catalog', () => {
181
+ const checks = loadLearnedChecks('/nonexistent/path/rules.json');
182
+ expect(checks).toEqual([]);
183
+ });
184
+ });
185
+ // ── Performance Benchmark ───────────────────────────────────────
186
+ describe('performance', () => {
187
+ it('runs full check set against a 50-line function in <10ms', () => {
188
+ const checkSet = compileCheckSet('typescript');
189
+ // Generate a realistic 50-line function
190
+ const lines = [
191
+ 'async function processUserData(req: Request, res: Response) {',
192
+ ' const userId = req.params.id;',
193
+ ' const db = getDatabase();',
194
+ ' ',
195
+ ' try {',
196
+ ' const user = await db.query("SELECT * FROM users WHERE id = $1", [userId]);',
197
+ ' if (!user) {',
198
+ ' return res.status(404).json({ error: "User not found" });',
199
+ ' }',
200
+ ' ',
201
+ ' const profile = await db.query("SELECT * FROM profiles WHERE user_id = $1", [userId]);',
202
+ ' const settings = await db.query("SELECT * FROM settings WHERE user_id = $1", [userId]);',
203
+ ' ',
204
+ ' const name = user.name ?? "Anonymous";',
205
+ ' const email = user.email ?? "";',
206
+ ' const avatar = user.avatar ?? "/default-avatar.png";',
207
+ ' ',
208
+ ' if (typeof name !== "string" || name.length === 0) {',
209
+ ' throw new TypeError("Invalid name");',
210
+ ' }',
211
+ ' ',
212
+ ' const result = {',
213
+ ' id: userId,',
214
+ ' name,',
215
+ ' email,',
216
+ ' avatar,',
217
+ ' profile: profile ?? {},',
218
+ ' settings: settings ?? {},',
219
+ ' lastLogin: user.lastLogin?.toISOString() ?? null,',
220
+ ' isAdmin: user.role === "admin",',
221
+ ' permissions: user.permissions ?? [],',
222
+ ' };',
223
+ ' ',
224
+ ' const cache = getCache();',
225
+ ' await cache.set(`user:${userId}`, JSON.stringify(result), { ex: 3600 });',
226
+ ' ',
227
+ ' logger.info("User data fetched", { userId });',
228
+ ' ',
229
+ ' return res.json(result);',
230
+ ' } catch (error) {',
231
+ ' logger.error("Failed to fetch user data", { userId, error });',
232
+ ' return res.status(500).json({ error: "Internal server error" });',
233
+ ' }',
234
+ '}',
235
+ '',
236
+ 'function validateEmail(email: string): boolean {',
237
+ ' const regex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;',
238
+ ' return regex.test(email);',
239
+ '}',
240
+ '',
241
+ 'function sanitizePath(input: string): string {',
242
+ ' return path.resolve(path.join(BASE_DIR, path.basename(input)));',
243
+ '}',
244
+ ];
245
+ const unit = makeUnit(lines.join('\n'));
246
+ // Warm up
247
+ runChecks(unit, checkSet);
248
+ // Measure
249
+ const iterations = 100;
250
+ const start = performance.now();
251
+ for (let i = 0; i < iterations; i++) {
252
+ runChecks(unit, checkSet);
253
+ }
254
+ const elapsed = performance.now() - start;
255
+ const avgMs = elapsed / iterations;
256
+ expect(avgMs).toBeLessThan(10);
257
+ });
258
+ });
259
+ // ── runChecks event structure ───────────────────────────────────
260
+ describe('runChecks event structure', () => {
261
+ it('returns well-formed VerificationEvent objects', () => {
262
+ const checkSet = compileCheckSet('typescript');
263
+ const unit = makeUnit('eval(userInput)');
264
+ const events = runChecks(unit, checkSet);
265
+ const evalEvent = events.find(e => e.checkId === 'unsafe_eval');
266
+ expect(evalEvent).toBeDefined();
267
+ expect(evalEvent.type).toBe('finding');
268
+ expect(evalEvent.verdict).toBe('FAIL');
269
+ expect(evalEvent.codeUnit).toBe(unit);
270
+ expect(evalEvent.severity).toBe('critical');
271
+ expect(evalEvent.evidence).toContain('eval');
272
+ expect(evalEvent.latencyMs).toBeGreaterThanOrEqual(0);
273
+ expect(evalEvent.suggestion).toBeTruthy();
274
+ });
275
+ it('returns empty array for clean code', () => {
276
+ const checkSet = compileCheckSet('typescript');
277
+ const unit = makeUnit('const x = 1 + 2;');
278
+ const events = runChecks(unit, checkSet);
279
+ expect(events).toEqual([]);
280
+ });
281
+ });
282
+ // ── Context Keywords Filtering ────────────────────────────────────
283
+ describe('contextKeywords filtering', () => {
284
+ function makeCheckWithKeywords(id, keywords, patternStr = /eval\(/) {
285
+ return {
286
+ id,
287
+ name: `Test check ${id}`,
288
+ languages: [],
289
+ pattern: patternStr,
290
+ verdict: 'FAIL',
291
+ severity: 'high',
292
+ evidenceTemplate: 'Found: $0',
293
+ source: 'learned',
294
+ contextKeywords: keywords,
295
+ };
296
+ }
297
+ it('skips check when contextKeywords are set but none match the code', () => {
298
+ const canvasCheck = makeCheckWithKeywords('canvas_check', ['canvas', 'drawImage', 'getContext'], /drawImage/);
299
+ const checkSet = {
300
+ checks: [canvasCheck],
301
+ language: 'typescript',
302
+ compileTimeMs: 0,
303
+ };
304
+ // SQL code should NOT trigger a canvas rule
305
+ const unit = makeUnit('const result = db.query("SELECT * FROM users")');
306
+ const events = runChecks(unit, checkSet);
307
+ expect(events).toEqual([]);
308
+ });
309
+ it('runs check when at least one contextKeyword matches', () => {
310
+ const canvasCheck = makeCheckWithKeywords('canvas_check', ['canvas', 'drawImage', 'getContext'], /drawImage/);
311
+ const checkSet = {
312
+ checks: [canvasCheck],
313
+ language: 'typescript',
314
+ compileTimeMs: 0,
315
+ };
316
+ // Canvas code SHOULD trigger a canvas rule
317
+ const unit = makeUnit('ctx.drawImage(img, 0, 0)');
318
+ const events = runChecks(unit, checkSet);
319
+ expect(events.length).toBe(1);
320
+ expect(events[0].checkId).toBe('canvas_check');
321
+ });
322
+ it('runs check when contextKeywords is undefined (no filtering)', () => {
323
+ const noKeywordsCheck = makeCheckWithKeywords('general_check', undefined, /eval\(/);
324
+ const checkSet = {
325
+ checks: [noKeywordsCheck],
326
+ language: 'typescript',
327
+ compileTimeMs: 0,
328
+ };
329
+ const unit = makeUnit('eval(code)');
330
+ const events = runChecks(unit, checkSet);
331
+ expect(events.length).toBe(1);
332
+ });
333
+ it('runs check when contextKeywords is empty array (no filtering)', () => {
334
+ const emptyKeywordsCheck = makeCheckWithKeywords('empty_kw_check', [], /eval\(/);
335
+ const checkSet = {
336
+ checks: [emptyKeywordsCheck],
337
+ language: 'typescript',
338
+ compileTimeMs: 0,
339
+ };
340
+ const unit = makeUnit('eval(code)');
341
+ const events = runChecks(unit, checkSet);
342
+ expect(events.length).toBe(1);
343
+ });
344
+ it('keyword matching is case-insensitive', () => {
345
+ const check = makeCheckWithKeywords('react_check', ['React', 'useState'], /useState/);
346
+ const checkSet = {
347
+ checks: [check],
348
+ language: 'typescript',
349
+ compileTimeMs: 0,
350
+ };
351
+ // Lowercase 'react' should match keyword 'React'
352
+ const unit = makeUnit('import react from "react"; useState(0)');
353
+ const events = runChecks(unit, checkSet);
354
+ expect(events.length).toBe(1);
355
+ });
356
+ it('React rules do NOT fire on SQL database code', () => {
357
+ const reactMemoCheck = makeCheckWithKeywords('react_memo', ['React', 'useState', 'useEffect', 'useRef', 'useCallback', 'useMemo', 'jsx', 'tsx', 'import react', 'from \'react', 'from "react'], /React\.memo/);
358
+ const checkSet = {
359
+ checks: [reactMemoCheck],
360
+ language: 'typescript',
361
+ compileTimeMs: 0,
362
+ };
363
+ const unit = makeUnit('const result = await db.query("SELECT * FROM users WHERE id = $1", [userId])');
364
+ const events = runChecks(unit, checkSet);
365
+ expect(events).toEqual([]);
366
+ });
367
+ it('OpenAPI rules do NOT fire on plain Express routes', () => {
368
+ const openApiCheck = makeCheckWithKeywords('openapi_decorator', ['@Api', '@Controller', '@Get(', '@Post(', '@Put(', '@Delete(', '@Patch(', 'swagger', 'openapi', '@nestjs'], /@ApiParam/);
369
+ const checkSet = {
370
+ checks: [openApiCheck],
371
+ language: 'typescript',
372
+ compileTimeMs: 0,
373
+ };
374
+ const unit = makeUnit('app.get("/users/:id", (req, res) => res.json({}))');
375
+ const events = runChecks(unit, checkSet);
376
+ expect(events).toEqual([]);
377
+ });
378
+ it('formal checks (no contextKeywords) still fire on all code', () => {
379
+ // Formal checks should be unaffected by this change
380
+ const checkSet = compileCheckSet('typescript');
381
+ const unit = makeUnit('eval(userInput)');
382
+ const ids = findingIds(unit, checkSet);
383
+ expect(ids).toContain('unsafe_eval');
384
+ });
385
+ });
386
+ // ── deriveContextKeywords ─────────────────────────────────────────
387
+ describe('deriveContextKeywords', () => {
388
+ function makeFakeRule(overrides) {
389
+ return {
390
+ id: 'test_rule',
391
+ pattern: {
392
+ id: 'tp_001',
393
+ description: overrides.description ?? 'test rule',
394
+ kind: 'regex',
395
+ languages: ['typescript'],
396
+ regexPattern: overrides.pattern?.regexPattern ?? 'test',
397
+ fileGlob: '**/*.ts',
398
+ matchBehavior: 'presence_is_bad',
399
+ claimCategory: overrides.category ?? 'general',
400
+ severity: 'high',
401
+ evidenceTemplate: 'Found: {match}',
402
+ },
403
+ status: 'promoted',
404
+ createdAt: '2026-01-01',
405
+ updatedAt: '2026-01-01',
406
+ fireCount: 0,
407
+ truePositiveCount: 0,
408
+ falsePositiveCount: 0,
409
+ sourceFindings: [],
410
+ fixDescription: overrides.fixDescription,
411
+ ...overrides,
412
+ };
413
+ }
414
+ it('assigns React keywords for React-related rules', () => {
415
+ const rule = makeFakeRule({ description: 'React component missing memoization' });
416
+ const keywords = _deriveContextKeywords(rule);
417
+ expect(keywords).toBeDefined();
418
+ expect(keywords.some(kw => kw.toLowerCase().includes('react'))).toBe(true);
419
+ });
420
+ it('assigns OpenAPI keywords for decorator-related rules', () => {
421
+ const rule = makeFakeRule({ description: 'Missing @ApiParam decorator on NestJS controller' });
422
+ const keywords = _deriveContextKeywords(rule);
423
+ expect(keywords).toBeDefined();
424
+ expect(keywords.some(kw => kw.includes('@Api') || kw.includes('@Controller'))).toBe(true);
425
+ });
426
+ it('assigns canvas keywords for canvas-related rules', () => {
427
+ const rule = makeFakeRule({ description: 'Canvas drawImage without error handling' });
428
+ const keywords = _deriveContextKeywords(rule);
429
+ expect(keywords).toBeDefined();
430
+ expect(keywords.some(kw => kw.toLowerCase().includes('canvas') || kw.includes('drawImage'))).toBe(true);
431
+ });
432
+ it('falls back to regex literals for unrecognized rules', () => {
433
+ const rule = makeFakeRule({
434
+ description: 'some obscure check',
435
+ category: 'misc',
436
+ });
437
+ // Override the pattern with something that has extractable literals
438
+ rule.pattern.regexPattern = 'handleCustomEvent\\(.*\\)';
439
+ const keywords = _deriveContextKeywords(rule);
440
+ expect(keywords).toBeDefined();
441
+ expect(keywords).toContain('handleCustomEvent');
442
+ });
443
+ it('returns undefined when no keywords can be derived', () => {
444
+ const rule = makeFakeRule({
445
+ description: 'bad code',
446
+ category: 'misc',
447
+ });
448
+ rule.pattern.regexPattern = '.*';
449
+ const keywords = _deriveContextKeywords(rule);
450
+ expect(keywords).toBeUndefined();
451
+ });
452
+ });
453
+ // ── extractRegexLiterals ──────────────────────────────────────────
454
+ describe('extractRegexLiterals', () => {
455
+ it('extracts alphanumeric identifiers of 4+ chars', () => {
456
+ const literals = _extractRegexLiterals('drawImage\\(.*canvas\\.getContext');
457
+ expect(literals).toContain('drawImage');
458
+ expect(literals).toContain('canvas');
459
+ expect(literals).toContain('getContext');
460
+ });
461
+ it('filters out common noise words', () => {
462
+ const literals = _extractRegexLiterals('true|false|null|undefined|customHandler');
463
+ expect(literals).not.toContain('true');
464
+ expect(literals).not.toContain('false');
465
+ expect(literals).not.toContain('null');
466
+ expect(literals).not.toContain('undefined');
467
+ expect(literals).toContain('customHandler');
468
+ });
469
+ it('returns empty for short/no literals', () => {
470
+ const literals = _extractRegexLiterals('^[a-z]+$');
471
+ expect(literals).toEqual([]);
472
+ });
473
+ it('limits to 10 literals max', () => {
474
+ const longPattern = Array.from({ length: 20 }, (_, i) => `identifier${i}`).join('|');
475
+ const literals = _extractRegexLiterals(longPattern);
476
+ expect(literals.length).toBeLessThanOrEqual(10);
477
+ });
478
+ });
479
+ //# sourceMappingURL=streaming-checks.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaming-checks.test.js","sourceRoot":"","sources":["../../../src/realtime/__tests__/streaming-checks.test.ts"],"names":[],"mappings":"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"}