@trust-assurance-protocol/owaspscan 1.0.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 (221) hide show
  1. package/dist/analysis/ast-analyzer.d.ts +13 -0
  2. package/dist/analysis/ast-analyzer.d.ts.map +1 -0
  3. package/dist/analysis/ast-analyzer.js +58 -0
  4. package/dist/analysis/ast-analyzer.js.map +1 -0
  5. package/dist/analysis/llm-verifier.d.ts +17 -0
  6. package/dist/analysis/llm-verifier.d.ts.map +1 -0
  7. package/dist/analysis/llm-verifier.js +152 -0
  8. package/dist/analysis/llm-verifier.js.map +1 -0
  9. package/dist/analysis/result-cache.d.ts +20 -0
  10. package/dist/analysis/result-cache.d.ts.map +1 -0
  11. package/dist/analysis/result-cache.js +70 -0
  12. package/dist/analysis/result-cache.js.map +1 -0
  13. package/dist/analysis/sinks.d.ts +12 -0
  14. package/dist/analysis/sinks.d.ts.map +1 -0
  15. package/dist/analysis/sinks.js +142 -0
  16. package/dist/analysis/sinks.js.map +1 -0
  17. package/dist/analysis/sources.d.ts +8 -0
  18. package/dist/analysis/sources.d.ts.map +1 -0
  19. package/dist/analysis/sources.js +114 -0
  20. package/dist/analysis/sources.js.map +1 -0
  21. package/dist/analysis/taint-engine.d.ts +5 -0
  22. package/dist/analysis/taint-engine.d.ts.map +1 -0
  23. package/dist/analysis/taint-engine.js +187 -0
  24. package/dist/analysis/taint-engine.js.map +1 -0
  25. package/dist/cli/index.d.ts +3 -0
  26. package/dist/cli/index.d.ts.map +1 -0
  27. package/dist/cli/index.js +227 -0
  28. package/dist/cli/index.js.map +1 -0
  29. package/dist/config/loader.d.ts +10 -0
  30. package/dist/config/loader.d.ts.map +1 -0
  31. package/dist/config/loader.js +81 -0
  32. package/dist/config/loader.js.map +1 -0
  33. package/dist/config/schema.d.ts +23 -0
  34. package/dist/config/schema.d.ts.map +1 -0
  35. package/dist/config/schema.js +17 -0
  36. package/dist/config/schema.js.map +1 -0
  37. package/dist/mcp/server.d.ts +2 -0
  38. package/dist/mcp/server.d.ts.map +1 -0
  39. package/dist/mcp/server.js +250 -0
  40. package/dist/mcp/server.js.map +1 -0
  41. package/dist/parsers/ast-parser.d.ts +38 -0
  42. package/dist/parsers/ast-parser.d.ts.map +1 -0
  43. package/dist/parsers/ast-parser.js +88 -0
  44. package/dist/parsers/ast-parser.js.map +1 -0
  45. package/dist/parsers/ast-queries.d.ts +63 -0
  46. package/dist/parsers/ast-queries.d.ts.map +1 -0
  47. package/dist/parsers/ast-queries.js +580 -0
  48. package/dist/parsers/ast-queries.js.map +1 -0
  49. package/dist/reporter/console.d.ts +8 -0
  50. package/dist/reporter/console.d.ts.map +1 -0
  51. package/dist/reporter/console.js +143 -0
  52. package/dist/reporter/console.js.map +1 -0
  53. package/dist/reporter/json.d.ts +3 -0
  54. package/dist/reporter/json.d.ts.map +1 -0
  55. package/dist/reporter/json.js +7 -0
  56. package/dist/reporter/json.js.map +1 -0
  57. package/dist/reporter/llm.d.ts +3 -0
  58. package/dist/reporter/llm.d.ts.map +1 -0
  59. package/dist/reporter/llm.js +66 -0
  60. package/dist/reporter/llm.js.map +1 -0
  61. package/dist/reporter/sarif.d.ts +3 -0
  62. package/dist/reporter/sarif.d.ts.map +1 -0
  63. package/dist/reporter/sarif.js +110 -0
  64. package/dist/reporter/sarif.js.map +1 -0
  65. package/dist/rules/owasp-a01/idor.d.ts +3 -0
  66. package/dist/rules/owasp-a01/idor.d.ts.map +1 -0
  67. package/dist/rules/owasp-a01/idor.js +48 -0
  68. package/dist/rules/owasp-a01/idor.js.map +1 -0
  69. package/dist/rules/owasp-a01/missing-auth-middleware.d.ts +3 -0
  70. package/dist/rules/owasp-a01/missing-auth-middleware.d.ts.map +1 -0
  71. package/dist/rules/owasp-a01/missing-auth-middleware.js +41 -0
  72. package/dist/rules/owasp-a01/missing-auth-middleware.js.map +1 -0
  73. package/dist/rules/owasp-a01/path-traversal.d.ts +3 -0
  74. package/dist/rules/owasp-a01/path-traversal.d.ts.map +1 -0
  75. package/dist/rules/owasp-a01/path-traversal.js +73 -0
  76. package/dist/rules/owasp-a01/path-traversal.js.map +1 -0
  77. package/dist/rules/owasp-a02/hardcoded-secrets.d.ts +3 -0
  78. package/dist/rules/owasp-a02/hardcoded-secrets.d.ts.map +1 -0
  79. package/dist/rules/owasp-a02/hardcoded-secrets.js +97 -0
  80. package/dist/rules/owasp-a02/hardcoded-secrets.js.map +1 -0
  81. package/dist/rules/owasp-a02/insecure-tls.d.ts +3 -0
  82. package/dist/rules/owasp-a02/insecure-tls.d.ts.map +1 -0
  83. package/dist/rules/owasp-a02/insecure-tls.js +75 -0
  84. package/dist/rules/owasp-a02/insecure-tls.js.map +1 -0
  85. package/dist/rules/owasp-a02/weak-hash.d.ts +3 -0
  86. package/dist/rules/owasp-a02/weak-hash.d.ts.map +1 -0
  87. package/dist/rules/owasp-a02/weak-hash.js +73 -0
  88. package/dist/rules/owasp-a02/weak-hash.js.map +1 -0
  89. package/dist/rules/owasp-a02/weak-random.d.ts +3 -0
  90. package/dist/rules/owasp-a02/weak-random.d.ts.map +1 -0
  91. package/dist/rules/owasp-a02/weak-random.js +70 -0
  92. package/dist/rules/owasp-a02/weak-random.js.map +1 -0
  93. package/dist/rules/owasp-a03/command-injection.d.ts +3 -0
  94. package/dist/rules/owasp-a03/command-injection.d.ts.map +1 -0
  95. package/dist/rules/owasp-a03/command-injection.js +79 -0
  96. package/dist/rules/owasp-a03/command-injection.js.map +1 -0
  97. package/dist/rules/owasp-a03/ldap-injection.d.ts +3 -0
  98. package/dist/rules/owasp-a03/ldap-injection.d.ts.map +1 -0
  99. package/dist/rules/owasp-a03/ldap-injection.js +56 -0
  100. package/dist/rules/owasp-a03/ldap-injection.js.map +1 -0
  101. package/dist/rules/owasp-a03/nosql-injection.d.ts +3 -0
  102. package/dist/rules/owasp-a03/nosql-injection.d.ts.map +1 -0
  103. package/dist/rules/owasp-a03/nosql-injection.js +61 -0
  104. package/dist/rules/owasp-a03/nosql-injection.js.map +1 -0
  105. package/dist/rules/owasp-a03/sql-injection.d.ts +3 -0
  106. package/dist/rules/owasp-a03/sql-injection.d.ts.map +1 -0
  107. package/dist/rules/owasp-a03/sql-injection.js +88 -0
  108. package/dist/rules/owasp-a03/sql-injection.js.map +1 -0
  109. package/dist/rules/owasp-a03/template-injection.d.ts +3 -0
  110. package/dist/rules/owasp-a03/template-injection.d.ts.map +1 -0
  111. package/dist/rules/owasp-a03/template-injection.js +64 -0
  112. package/dist/rules/owasp-a03/template-injection.js.map +1 -0
  113. package/dist/rules/owasp-a03/xss.d.ts +3 -0
  114. package/dist/rules/owasp-a03/xss.d.ts.map +1 -0
  115. package/dist/rules/owasp-a03/xss.js +74 -0
  116. package/dist/rules/owasp-a03/xss.js.map +1 -0
  117. package/dist/rules/owasp-a04/mass-assignment.d.ts +3 -0
  118. package/dist/rules/owasp-a04/mass-assignment.d.ts.map +1 -0
  119. package/dist/rules/owasp-a04/mass-assignment.js +63 -0
  120. package/dist/rules/owasp-a04/mass-assignment.js.map +1 -0
  121. package/dist/rules/owasp-a04/missing-rate-limit.d.ts +3 -0
  122. package/dist/rules/owasp-a04/missing-rate-limit.d.ts.map +1 -0
  123. package/dist/rules/owasp-a04/missing-rate-limit.js +48 -0
  124. package/dist/rules/owasp-a04/missing-rate-limit.js.map +1 -0
  125. package/dist/rules/owasp-a05/cors-wildcard.d.ts +3 -0
  126. package/dist/rules/owasp-a05/cors-wildcard.d.ts.map +1 -0
  127. package/dist/rules/owasp-a05/cors-wildcard.js +79 -0
  128. package/dist/rules/owasp-a05/cors-wildcard.js.map +1 -0
  129. package/dist/rules/owasp-a05/debug-mode.d.ts +3 -0
  130. package/dist/rules/owasp-a05/debug-mode.d.ts.map +1 -0
  131. package/dist/rules/owasp-a05/debug-mode.js +73 -0
  132. package/dist/rules/owasp-a05/debug-mode.js.map +1 -0
  133. package/dist/rules/owasp-a05/default-credentials.d.ts +3 -0
  134. package/dist/rules/owasp-a05/default-credentials.d.ts.map +1 -0
  135. package/dist/rules/owasp-a05/default-credentials.js +52 -0
  136. package/dist/rules/owasp-a05/default-credentials.js.map +1 -0
  137. package/dist/rules/owasp-a05/error-disclosure.d.ts +3 -0
  138. package/dist/rules/owasp-a05/error-disclosure.d.ts.map +1 -0
  139. package/dist/rules/owasp-a05/error-disclosure.js +70 -0
  140. package/dist/rules/owasp-a05/error-disclosure.js.map +1 -0
  141. package/dist/rules/owasp-a06/outdated-packages.d.ts +3 -0
  142. package/dist/rules/owasp-a06/outdated-packages.d.ts.map +1 -0
  143. package/dist/rules/owasp-a06/outdated-packages.js +75 -0
  144. package/dist/rules/owasp-a06/outdated-packages.js.map +1 -0
  145. package/dist/rules/owasp-a07/insecure-cookies.d.ts +3 -0
  146. package/dist/rules/owasp-a07/insecure-cookies.d.ts.map +1 -0
  147. package/dist/rules/owasp-a07/insecure-cookies.js +64 -0
  148. package/dist/rules/owasp-a07/insecure-cookies.js.map +1 -0
  149. package/dist/rules/owasp-a07/jwt-none-alg.d.ts +3 -0
  150. package/dist/rules/owasp-a07/jwt-none-alg.d.ts.map +1 -0
  151. package/dist/rules/owasp-a07/jwt-none-alg.js +81 -0
  152. package/dist/rules/owasp-a07/jwt-none-alg.js.map +1 -0
  153. package/dist/rules/owasp-a07/no-password-hashing.d.ts +3 -0
  154. package/dist/rules/owasp-a07/no-password-hashing.d.ts.map +1 -0
  155. package/dist/rules/owasp-a07/no-password-hashing.js +70 -0
  156. package/dist/rules/owasp-a07/no-password-hashing.js.map +1 -0
  157. package/dist/rules/owasp-a07/weak-session.d.ts +3 -0
  158. package/dist/rules/owasp-a07/weak-session.d.ts.map +1 -0
  159. package/dist/rules/owasp-a07/weak-session.js +64 -0
  160. package/dist/rules/owasp-a07/weak-session.js.map +1 -0
  161. package/dist/rules/owasp-a08/unsafe-deserialization.d.ts +3 -0
  162. package/dist/rules/owasp-a08/unsafe-deserialization.d.ts.map +1 -0
  163. package/dist/rules/owasp-a08/unsafe-deserialization.js +78 -0
  164. package/dist/rules/owasp-a08/unsafe-deserialization.js.map +1 -0
  165. package/dist/rules/owasp-a08/unsafe-eval.d.ts +3 -0
  166. package/dist/rules/owasp-a08/unsafe-eval.d.ts.map +1 -0
  167. package/dist/rules/owasp-a08/unsafe-eval.js +73 -0
  168. package/dist/rules/owasp-a08/unsafe-eval.js.map +1 -0
  169. package/dist/rules/owasp-a09/log-sensitive-data.d.ts +3 -0
  170. package/dist/rules/owasp-a09/log-sensitive-data.d.ts.map +1 -0
  171. package/dist/rules/owasp-a09/log-sensitive-data.js +73 -0
  172. package/dist/rules/owasp-a09/log-sensitive-data.js.map +1 -0
  173. package/dist/rules/owasp-a09/missing-error-handling.d.ts +3 -0
  174. package/dist/rules/owasp-a09/missing-error-handling.d.ts.map +1 -0
  175. package/dist/rules/owasp-a09/missing-error-handling.js +84 -0
  176. package/dist/rules/owasp-a09/missing-error-handling.js.map +1 -0
  177. package/dist/rules/owasp-a10/open-redirect.d.ts +3 -0
  178. package/dist/rules/owasp-a10/open-redirect.d.ts.map +1 -0
  179. package/dist/rules/owasp-a10/open-redirect.js +67 -0
  180. package/dist/rules/owasp-a10/open-redirect.js.map +1 -0
  181. package/dist/rules/owasp-a10/unvalidated-fetch.d.ts +3 -0
  182. package/dist/rules/owasp-a10/unvalidated-fetch.d.ts.map +1 -0
  183. package/dist/rules/owasp-a10/unvalidated-fetch.js +85 -0
  184. package/dist/rules/owasp-a10/unvalidated-fetch.js.map +1 -0
  185. package/dist/rules/registry.d.ts +20 -0
  186. package/dist/rules/registry.d.ts.map +1 -0
  187. package/dist/rules/registry.js +142 -0
  188. package/dist/rules/registry.js.map +1 -0
  189. package/dist/scanner/engine.d.ts +21 -0
  190. package/dist/scanner/engine.d.ts.map +1 -0
  191. package/dist/scanner/engine.js +260 -0
  192. package/dist/scanner/engine.js.map +1 -0
  193. package/dist/scanner/file-walker.d.ts +7 -0
  194. package/dist/scanner/file-walker.d.ts.map +1 -0
  195. package/dist/scanner/file-walker.js +81 -0
  196. package/dist/scanner/file-walker.js.map +1 -0
  197. package/dist/scanner/language-detect.d.ts +5 -0
  198. package/dist/scanner/language-detect.d.ts.map +1 -0
  199. package/dist/scanner/language-detect.js +91 -0
  200. package/dist/scanner/language-detect.js.map +1 -0
  201. package/dist/scanner/sca-scanner.d.ts +38 -0
  202. package/dist/scanner/sca-scanner.d.ts.map +1 -0
  203. package/dist/scanner/sca-scanner.js +223 -0
  204. package/dist/scanner/sca-scanner.js.map +1 -0
  205. package/dist/types/index.d.ts +114 -0
  206. package/dist/types/index.d.ts.map +1 -0
  207. package/dist/types/index.js +25 -0
  208. package/dist/types/index.js.map +1 -0
  209. package/dist/utils/pattern-matcher.d.ts +4 -0
  210. package/dist/utils/pattern-matcher.d.ts.map +1 -0
  211. package/dist/utils/pattern-matcher.js +72 -0
  212. package/dist/utils/pattern-matcher.js.map +1 -0
  213. package/dist/utils/scoring.d.ts +8 -0
  214. package/dist/utils/scoring.d.ts.map +1 -0
  215. package/dist/utils/scoring.js +76 -0
  216. package/dist/utils/scoring.js.map +1 -0
  217. package/dist/utils/suppression.d.ts +3 -0
  218. package/dist/utils/suppression.d.ts.map +1 -0
  219. package/dist/utils/suppression.js +33 -0
  220. package/dist/utils/suppression.js.map +1 -0
  221. package/package.json +94 -0
@@ -0,0 +1,142 @@
1
+ // ============================================================
2
+ // Rule Registry — central loader for all security rules
3
+ // Supports plugin rules via registerRules()
4
+ // ============================================================
5
+ // OWASP A01 — Broken Access Control
6
+ import { MissingAuthMiddleware } from './owasp-a01/missing-auth-middleware.js';
7
+ import { PathTraversal } from './owasp-a01/path-traversal.js';
8
+ import { InsecureDirectObjectRef } from './owasp-a01/idor.js';
9
+ // OWASP A02 — Cryptographic Failures
10
+ import { WeakHash } from './owasp-a02/weak-hash.js';
11
+ import { HardcodedSecrets } from './owasp-a02/hardcoded-secrets.js';
12
+ import { WeakRandom } from './owasp-a02/weak-random.js';
13
+ import { InsecureTLS } from './owasp-a02/insecure-tls.js';
14
+ // OWASP A03 — Injection
15
+ import { SqlInjection } from './owasp-a03/sql-injection.js';
16
+ import { CommandInjection } from './owasp-a03/command-injection.js';
17
+ import { NoSqlInjection } from './owasp-a03/nosql-injection.js';
18
+ import { XssReflected } from './owasp-a03/xss.js';
19
+ import { TemplateInjection } from './owasp-a03/template-injection.js';
20
+ import { LdapInjection } from './owasp-a03/ldap-injection.js';
21
+ // OWASP A04 — Insecure Design
22
+ import { MissingRateLimit } from './owasp-a04/missing-rate-limit.js';
23
+ import { MassAssignment } from './owasp-a04/mass-assignment.js';
24
+ // OWASP A05 — Security Misconfiguration
25
+ import { DebugMode } from './owasp-a05/debug-mode.js';
26
+ import { CorsWildcard } from './owasp-a05/cors-wildcard.js';
27
+ import { ErrorDisclosure } from './owasp-a05/error-disclosure.js';
28
+ import { DefaultCredentials } from './owasp-a05/default-credentials.js';
29
+ // OWASP A06 — Vulnerable & Outdated Components
30
+ import { OutdatedPackages } from './owasp-a06/outdated-packages.js';
31
+ // OWASP A07 — Identification & Authentication Failures
32
+ import { JwtNoneAlgorithm } from './owasp-a07/jwt-none-alg.js';
33
+ import { NoPasswordHashing } from './owasp-a07/no-password-hashing.js';
34
+ import { WeakSessionConfig } from './owasp-a07/weak-session.js';
35
+ import { InsecureCookies } from './owasp-a07/insecure-cookies.js';
36
+ // OWASP A08 — Software & Data Integrity Failures
37
+ import { UnsafeEval } from './owasp-a08/unsafe-eval.js';
38
+ import { UnsafeDeserialization } from './owasp-a08/unsafe-deserialization.js';
39
+ // OWASP A09 — Security Logging & Monitoring Failures
40
+ import { LogSensitiveData } from './owasp-a09/log-sensitive-data.js';
41
+ import { MissingErrorHandling } from './owasp-a09/missing-error-handling.js';
42
+ // OWASP A10 — Server-Side Request Forgery
43
+ import { UnvalidatedFetch } from './owasp-a10/unvalidated-fetch.js';
44
+ import { OpenRedirect } from './owasp-a10/open-redirect.js';
45
+ // Core OWASP Top 10 rules (public/open-source)
46
+ const CORE_RULES = [
47
+ // A01 — Broken Access Control
48
+ MissingAuthMiddleware,
49
+ PathTraversal,
50
+ InsecureDirectObjectRef,
51
+ // A02 — Cryptographic Failures
52
+ HardcodedSecrets,
53
+ WeakHash,
54
+ WeakRandom,
55
+ InsecureTLS,
56
+ // A03 — Injection
57
+ SqlInjection,
58
+ CommandInjection,
59
+ NoSqlInjection,
60
+ XssReflected,
61
+ TemplateInjection,
62
+ LdapInjection,
63
+ // A04 — Insecure Design
64
+ MissingRateLimit,
65
+ MassAssignment,
66
+ // A05 — Security Misconfiguration
67
+ DebugMode,
68
+ CorsWildcard,
69
+ ErrorDisclosure,
70
+ DefaultCredentials,
71
+ // A06 — Vulnerable Components
72
+ OutdatedPackages,
73
+ // A07 — Auth Failures
74
+ JwtNoneAlgorithm,
75
+ NoPasswordHashing,
76
+ WeakSessionConfig,
77
+ InsecureCookies,
78
+ // A08 — Data Integrity
79
+ UnsafeEval,
80
+ UnsafeDeserialization,
81
+ // A09 — Logging Failures
82
+ LogSensitiveData,
83
+ MissingErrorHandling,
84
+ // A10 — SSRF
85
+ UnvalidatedFetch,
86
+ OpenRedirect,
87
+ ];
88
+ export class RuleRegistry {
89
+ rules;
90
+ _proRulesLoaded = false;
91
+ constructor(rules = CORE_RULES) {
92
+ this.rules = new Map();
93
+ for (const rule of rules) {
94
+ this.rules.set(rule.id, rule);
95
+ }
96
+ }
97
+ /** Register additional rules (e.g., from @owaspscan/rules-pro) */
98
+ registerRules(rules) {
99
+ for (const rule of rules) {
100
+ this.rules.set(rule.id, rule);
101
+ }
102
+ this._proRulesLoaded = true;
103
+ }
104
+ get proRulesLoaded() {
105
+ return this._proRulesLoaded;
106
+ }
107
+ get coreRuleCount() {
108
+ return CORE_RULES.length;
109
+ }
110
+ getAll() {
111
+ return Array.from(this.rules.values());
112
+ }
113
+ getById(id) {
114
+ return this.rules.get(id);
115
+ }
116
+ getByCategory(category) {
117
+ return this.getAll().filter((r) => r.owasp === category);
118
+ }
119
+ getByLanguage(language) {
120
+ return this.getAll().filter((r) => r.languages.includes('all') || r.languages.includes(language));
121
+ }
122
+ filterByCategories(categoryPrefixes) {
123
+ return this.getAll().filter((rule) => {
124
+ // e.g., 'A01' matches 'A01:2021', 'LLM01' matches 'LLM01:2025'
125
+ return categoryPrefixes.some((prefix) => rule.owasp.startsWith(prefix.toUpperCase()));
126
+ });
127
+ }
128
+ size() {
129
+ return this.rules.size;
130
+ }
131
+ }
132
+ /** Create a fresh registry, optionally with extra rules */
133
+ export function createRegistry(extraRules) {
134
+ const reg = new RuleRegistry();
135
+ if (extraRules) {
136
+ reg.registerRules(extraRules);
137
+ }
138
+ return reg;
139
+ }
140
+ // Singleton instance
141
+ export const registry = new RuleRegistry();
142
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/rules/registry.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,wDAAwD;AACxD,4CAA4C;AAC5C,+DAA+D;AAI/D,oCAAoC;AACpC,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,qCAAqC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAE1D,wBAAwB;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAE9D,8BAA8B;AAC9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEhE,wCAAwC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAExE,+CAA+C;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEpE,uDAAuD;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAElE,iDAAiD;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAE9E,qDAAqD;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAE7E,0CAA0C;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5D,+CAA+C;AAC/C,MAAM,UAAU,GAAW;IACzB,8BAA8B;IAC9B,qBAAqB;IACrB,aAAa;IACb,uBAAuB;IAEvB,+BAA+B;IAC/B,gBAAgB;IAChB,QAAQ;IACR,UAAU;IACV,WAAW;IAEX,kBAAkB;IAClB,YAAY;IACZ,gBAAgB;IAChB,cAAc;IACd,YAAY;IACZ,iBAAiB;IACjB,aAAa;IAEb,wBAAwB;IACxB,gBAAgB;IAChB,cAAc;IAEd,kCAAkC;IAClC,SAAS;IACT,YAAY;IACZ,eAAe;IACf,kBAAkB;IAElB,8BAA8B;IAC9B,gBAAgB;IAEhB,sBAAsB;IACtB,gBAAgB;IAChB,iBAAiB;IACjB,iBAAiB;IACjB,eAAe;IAEf,uBAAuB;IACvB,UAAU;IACV,qBAAqB;IAErB,yBAAyB;IACzB,gBAAgB;IAChB,oBAAoB;IAEpB,aAAa;IACb,gBAAgB;IAChB,YAAY;CACb,CAAC;AAEF,MAAM,OAAO,YAAY;IACf,KAAK,CAAoB;IACzB,eAAe,GAAG,KAAK,CAAC;IAEhC,YAAY,QAAgB,UAAU;QACpC,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,EAAE,CAAC;QACvB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,kEAAkE;IAClE,aAAa,CAAC,KAAa;QACzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAChC,CAAC;QACD,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;IAC9B,CAAC;IAED,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,eAAe,CAAC;IAC9B,CAAC;IAED,IAAI,aAAa;QACf,OAAO,UAAU,CAAC,MAAM,CAAC;IAC3B,CAAC;IAED,MAAM;QACJ,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,CAAC,EAAU;QAChB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5B,CAAC;IAED,aAAa,CAAC,QAAuB;QACnC,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC;IAC3D,CAAC;IAED,aAAa,CAAC,QAA2B;QACvC,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,MAAM,CACzB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CACrE,CAAC;IACJ,CAAC;IAED,kBAAkB,CAAC,gBAA0B;QAC3C,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;YACnC,+DAA+D;YAC/D,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CACtC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAC5C,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;CACF;AAED,2DAA2D;AAC3D,MAAM,UAAU,cAAc,CAAC,UAAmB;IAChD,MAAM,GAAG,GAAG,IAAI,YAAY,EAAE,CAAC;IAC/B,IAAI,UAAU,EAAE,CAAC;QACf,GAAG,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,qBAAqB;AACrB,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,YAAY,EAAE,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { Rule, FileResult, ScanResult, SupportedLanguage, ScanOptions, FailOnLevel } from '../types/index.js';
2
+ import type { TaintMap } from '../analysis/ast-analyzer.js';
3
+ import { sortFindings } from '../utils/scoring.js';
4
+ import { registry } from '../rules/registry.js';
5
+ export interface EngineOptions {
6
+ rules?: string[];
7
+ exclude?: string[];
8
+ recursive: boolean;
9
+ failOn: FailOnLevel;
10
+ verbose: boolean;
11
+ maxFindings?: number;
12
+ sca?: boolean;
13
+ }
14
+ export declare function scanFile(filePath: string, rules: Rule[], crossFileSources?: TaintMap): Promise<FileResult>;
15
+ export declare function scanDirectory(targetPath: string, options: EngineOptions, onProgress?: (current: number, total: number, filePath: string) => void): Promise<ScanResult>;
16
+ export declare function scanCode(code: string, language: SupportedLanguage, filename?: string, ruleCategories?: string[]): Promise<ScanResult>;
17
+ export declare function buildScanOptions(partial: Partial<ScanOptions> & {
18
+ target: string;
19
+ }): EngineOptions;
20
+ export { registry, sortFindings };
21
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/scanner/engine.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,IAAI,EAEJ,UAAU,EACV,UAAU,EACV,iBAAiB,EACjB,WAAW,EACX,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAG3B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAM5D,OAAO,EAAmB,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEpE,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAiBhD,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,WAAW,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,wBAAsB,QAAQ,CAC5B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,IAAI,EAAE,EACb,gBAAgB,CAAC,EAAE,QAAQ,GAC1B,OAAO,CAAC,UAAU,CAAC,CAuFrB;AAED,wBAAsB,aAAa,CACjC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,aAAa,EACtB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,GACtE,OAAO,CAAC,UAAU,CAAC,CA6FrB;AAED,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,iBAAiB,EAC3B,QAAQ,SAAa,EACrB,cAAc,CAAC,EAAE,MAAM,EAAE,GACxB,OAAO,CAAC,UAAU,CAAC,CA6ErB;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,aAAa,CASlG;AAED,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC"}
@@ -0,0 +1,260 @@
1
+ // ============================================================
2
+ // Scan Engine — orchestrates file walking, rule application, reporting
3
+ // ============================================================
4
+ import { analyzeTaint } from '../analysis/taint-engine.js';
5
+ import { analyzeAST } from '../analysis/ast-analyzer.js';
6
+ import { parseCode } from '../parsers/ast-parser.js';
7
+ import { collectExportedTaintSources } from '../parsers/ast-queries.js';
8
+ import { detectLanguage, languageMatches } from './language-detect.js';
9
+ import { walkFiles, readFileSafe } from './file-walker.js';
10
+ import { applyPatterns } from '../utils/pattern-matcher.js';
11
+ import { buildScanResult, sortFindings } from '../utils/scoring.js';
12
+ import { runSCA } from './sca-scanner.js';
13
+ import { registry } from '../rules/registry.js';
14
+ // Auto-discover and load @trust-assurance-protocol/rules-pro if installed
15
+ let _proDiscoveryDone = false;
16
+ async function loadProRules() {
17
+ if (_proDiscoveryDone)
18
+ return;
19
+ _proDiscoveryDone = true;
20
+ try {
21
+ // @ts-ignore — @trust-assurance-protocol/rules-pro is an optional dependency, may not be installed
22
+ const mod = await import('@trust-assurance-protocol/rules-pro');
23
+ if (mod.proRules && Array.isArray(mod.proRules)) {
24
+ registry.registerRules(mod.proRules);
25
+ }
26
+ }
27
+ catch {
28
+ // @trust-assurance-protocol/rules-pro not installed — run with core rules only
29
+ }
30
+ }
31
+ export async function scanFile(filePath, rules, crossFileSources) {
32
+ const startTime = Date.now();
33
+ const content = readFileSafe(filePath);
34
+ if (content === null) {
35
+ return {
36
+ filePath,
37
+ language: 'all',
38
+ findings: [],
39
+ linesScanned: 0,
40
+ rulesApplied: 0,
41
+ scanDurationMs: 0,
42
+ };
43
+ }
44
+ const lines = content.split('\n');
45
+ const firstLine = lines[0] ?? '';
46
+ const language = detectLanguage(filePath, firstLine) ?? 'all';
47
+ const applicableRules = rules.filter((rule) => languageMatches(rule.languages, language));
48
+ const findings = [];
49
+ // --- Tier 2: AST analysis (runs first — highest structural confidence) ---
50
+ if (language === 'javascript' || language === 'typescript' || language === 'python') {
51
+ const astFindings = analyzeAST(content, language, filePath, rules, crossFileSources);
52
+ findings.push(...astFindings);
53
+ }
54
+ // --- Tier 1: Regex (covers languages without AST + rules not covered by AST) ---
55
+ for (const rule of applicableRules) {
56
+ const matches = applyPatterns(content, rule.patterns);
57
+ for (const match of matches) {
58
+ // Skip if AST already found this rule at this line (AST is higher quality)
59
+ const isDupe = findings.some((f) => f.ruleId === rule.id && Math.abs(f.line - match.line) <= 2);
60
+ if (isDupe)
61
+ continue;
62
+ findings.push({
63
+ ruleId: rule.id,
64
+ ruleName: rule.name,
65
+ owasp: rule.owasp,
66
+ cwe: rule.cwe,
67
+ severity: rule.severity,
68
+ filePath,
69
+ line: match.line,
70
+ column: match.column,
71
+ snippet: match.snippet,
72
+ message: `${rule.name} — ${rule.description.slice(0, 150)}`,
73
+ fix: rule.fix,
74
+ references: rule.references,
75
+ confidence: 'MEDIUM',
76
+ analysisMethod: 'regex',
77
+ });
78
+ }
79
+ }
80
+ // --- Tier 3: Regex taint (fallback for languages without AST support) ---
81
+ // For JS/TS/Python the AST already handles both direct and indirect taint detection.
82
+ // Regex taint runs only for other languages (Go, Java, PHP, etc.).
83
+ if (language !== 'javascript' && language !== 'typescript' && language !== 'python') {
84
+ const taintFindings = analyzeTaint(content, language, filePath, rules);
85
+ for (const tf of taintFindings) {
86
+ const isDupe = findings.some((f) => f.ruleId === tf.ruleId && Math.abs(f.line - tf.line) <= 2);
87
+ if (!isDupe) {
88
+ findings.push(tf);
89
+ }
90
+ }
91
+ }
92
+ // Sort findings by line number
93
+ findings.sort((a, b) => a.line - b.line);
94
+ return {
95
+ filePath,
96
+ language: language,
97
+ findings,
98
+ linesScanned: lines.length,
99
+ rulesApplied: applicableRules.length,
100
+ scanDurationMs: Date.now() - startTime,
101
+ };
102
+ }
103
+ export async function scanDirectory(targetPath, options, onProgress) {
104
+ await loadProRules();
105
+ const startTime = Date.now();
106
+ // Determine which rules to apply
107
+ let rules;
108
+ if (options.rules && options.rules.length > 0) {
109
+ rules = registry.filterByCategories(options.rules);
110
+ }
111
+ else {
112
+ rules = registry.getAll();
113
+ }
114
+ // Discover all files
115
+ const files = await walkFiles(targetPath, {
116
+ recursive: options.recursive,
117
+ exclude: options.exclude,
118
+ });
119
+ if (options.verbose) {
120
+ process.stderr.write(`Found ${files.length} files to scan with ${rules.length} rules\n`);
121
+ }
122
+ // --- Cross-file taint pre-pass (JS/TS only) ---
123
+ // Collect exported functions that return tainted values so downstream files
124
+ // can treat calls to those functions as taint sources.
125
+ const crossFileSources = new Map();
126
+ for (const filePath of files) {
127
+ const ext = filePath.split('.').pop() ?? '';
128
+ if (ext !== 'js' && ext !== 'ts' && ext !== 'jsx' && ext !== 'tsx' && ext !== 'mjs' && ext !== 'cjs')
129
+ continue;
130
+ const content = readFileSafe(filePath);
131
+ if (!content)
132
+ continue;
133
+ const firstLine = content.split('\n')[0] ?? '';
134
+ const lang = detectLanguage(filePath, firstLine);
135
+ if (lang !== 'javascript' && lang !== 'typescript')
136
+ continue;
137
+ const tree = parseCode(content, lang);
138
+ if (!tree)
139
+ continue;
140
+ const exported = collectExportedTaintSources(tree.rootNode, lang);
141
+ for (const [k, v] of exported) {
142
+ crossFileSources.set(k, v);
143
+ }
144
+ }
145
+ if (options.verbose && crossFileSources.size > 0) {
146
+ process.stderr.write(`Cross-file taint sources found: ${crossFileSources.size}\n`);
147
+ }
148
+ // Scan each file
149
+ const fileResults = [];
150
+ let totalFindings = 0;
151
+ for (let i = 0; i < files.length; i++) {
152
+ const filePath = files[i];
153
+ if (onProgress) {
154
+ onProgress(i + 1, files.length, filePath);
155
+ }
156
+ const result = await scanFile(filePath, rules, crossFileSources);
157
+ fileResults.push(result);
158
+ totalFindings += result.findings.length;
159
+ // Early exit if maxFindings exceeded
160
+ if (options.maxFindings && totalFindings >= options.maxFindings) {
161
+ if (options.verbose) {
162
+ process.stderr.write(`Max findings limit (${options.maxFindings}) reached. Stopping.\n`);
163
+ }
164
+ break;
165
+ }
166
+ }
167
+ // SCA dependency scanning (opt-in)
168
+ if (options.sca) {
169
+ const scaFindings = await runSCA(targetPath);
170
+ if (scaFindings.length > 0) {
171
+ // Attach SCA findings to a synthetic "manifest" file result
172
+ const manifestResult = {
173
+ filePath: targetPath,
174
+ language: 'all',
175
+ findings: scaFindings,
176
+ linesScanned: 0,
177
+ rulesApplied: 1,
178
+ scanDurationMs: 0,
179
+ };
180
+ fileResults.push(manifestResult);
181
+ }
182
+ }
183
+ return buildScanResult(targetPath, fileResults, Date.now() - startTime, options.failOn);
184
+ }
185
+ export async function scanCode(code, language, filename = '<inline>', ruleCategories) {
186
+ await loadProRules();
187
+ const startTime = Date.now();
188
+ let rules;
189
+ if (ruleCategories && ruleCategories.length > 0) {
190
+ rules = registry.filterByCategories(ruleCategories);
191
+ }
192
+ else {
193
+ rules = registry.getAll();
194
+ }
195
+ const applicableRules = rules.filter((rule) => languageMatches(rule.languages, language));
196
+ const lines = code.split('\n');
197
+ const findings = [];
198
+ // --- Tier 2: AST (runs first — highest structural confidence) ---
199
+ if (language === 'javascript' || language === 'typescript' || language === 'python') {
200
+ const astFindings = analyzeAST(code, language, filename, applicableRules);
201
+ findings.push(...astFindings);
202
+ }
203
+ // --- Tier 1: Regex (fallback for rules not covered by AST) ---
204
+ for (const rule of applicableRules) {
205
+ const matches = applyPatterns(code, rule.patterns);
206
+ for (const match of matches) {
207
+ const isDupe = findings.some((f) => f.ruleId === rule.id && Math.abs(f.line - match.line) <= 2);
208
+ if (isDupe)
209
+ continue;
210
+ findings.push({
211
+ ruleId: rule.id,
212
+ ruleName: rule.name,
213
+ owasp: rule.owasp,
214
+ cwe: rule.cwe,
215
+ severity: rule.severity,
216
+ filePath: filename,
217
+ line: match.line,
218
+ column: match.column,
219
+ snippet: match.snippet,
220
+ message: `${rule.name} — ${rule.description.slice(0, 150)}`,
221
+ fix: rule.fix,
222
+ references: rule.references,
223
+ confidence: 'MEDIUM',
224
+ analysisMethod: 'regex',
225
+ });
226
+ }
227
+ }
228
+ // --- Tier 3: Regex taint (fallback for non-AST languages only) ---
229
+ if (language !== 'javascript' && language !== 'typescript' && language !== 'python') {
230
+ const taintFindings = analyzeTaint(code, language, filename, applicableRules);
231
+ for (const tf of taintFindings) {
232
+ const isDupe = findings.some((f) => f.ruleId === tf.ruleId && Math.abs(f.line - tf.line) <= 2);
233
+ if (!isDupe) {
234
+ findings.push(tf);
235
+ }
236
+ }
237
+ }
238
+ findings.sort((a, b) => a.line - b.line);
239
+ const fileResult = {
240
+ filePath: filename,
241
+ language,
242
+ findings,
243
+ linesScanned: lines.length,
244
+ rulesApplied: applicableRules.length,
245
+ scanDurationMs: Date.now() - startTime,
246
+ };
247
+ return buildScanResult(filename, [fileResult], Date.now() - startTime, 'never');
248
+ }
249
+ export function buildScanOptions(partial) {
250
+ return {
251
+ rules: partial.rules,
252
+ exclude: partial.exclude,
253
+ recursive: partial.recursive ?? true,
254
+ failOn: partial.failOn ?? 'never',
255
+ verbose: partial.verbose ?? false,
256
+ maxFindings: partial.maxFindings,
257
+ };
258
+ }
259
+ export { registry, sortFindings };
260
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/scanner/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface WalkOptions {
2
+ recursive: boolean;
3
+ exclude?: string[] | undefined;
4
+ }
5
+ export declare function walkFiles(targetPath: string, options: WalkOptions): Promise<string[]>;
6
+ export declare function readFileSafe(filePath: string): string | null;
7
+ //# sourceMappingURL=file-walker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-walker.d.ts","sourceRoot":"","sources":["../../src/scanner/file-walker.ts"],"names":[],"mappings":"AAmCA,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;CAChC;AAgBD,wBAAsB,SAAS,CAC7B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,MAAM,EAAE,CAAC,CAyCnB;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM5D"}
@@ -0,0 +1,81 @@
1
+ // ============================================================
2
+ // File Walker — discovers scannable files respecting .gitignore
3
+ // ============================================================
4
+ import fs from 'fs';
5
+ import path from 'path';
6
+ import { createRequire } from 'module';
7
+ import { glob } from 'glob';
8
+ import { isSupportedFile } from './language-detect.js';
9
+ const require = createRequire(import.meta.url);
10
+ // ignore is a CJS-only package — use createRequire for ESM compatibility
11
+ const ignoreLib = require('ignore');
12
+ const ALWAYS_IGNORED = [
13
+ 'node_modules/**',
14
+ 'dist/**',
15
+ 'build/**',
16
+ '.git/**',
17
+ 'coverage/**',
18
+ '**/*.min.js',
19
+ '**/*.bundle.js',
20
+ '**/*.map',
21
+ '**/__pycache__/**',
22
+ '**/*.pyc',
23
+ '**/.venv/**',
24
+ '**/venv/**',
25
+ '**/.tox/**',
26
+ '**/vendor/**',
27
+ '**/.cache/**',
28
+ ];
29
+ function loadGitignore(dir) {
30
+ const ig = ignoreLib();
31
+ const gitignorePath = path.join(dir, '.gitignore');
32
+ if (fs.existsSync(gitignorePath)) {
33
+ const content = fs.readFileSync(gitignorePath, 'utf8');
34
+ ig.add(content);
35
+ }
36
+ return ig;
37
+ }
38
+ export async function walkFiles(targetPath, options) {
39
+ const stat = fs.statSync(targetPath);
40
+ // Single file — validate and return
41
+ if (stat.isFile()) {
42
+ if (isSupportedFile(targetPath)) {
43
+ return [path.resolve(targetPath)];
44
+ }
45
+ return [];
46
+ }
47
+ if (!stat.isDirectory()) {
48
+ throw new Error(`Target path is not a file or directory: ${targetPath}`);
49
+ }
50
+ const baseDir = path.resolve(targetPath);
51
+ const pattern = options.recursive ? '**/*' : '*';
52
+ const ignorePatterns = [
53
+ ...ALWAYS_IGNORED,
54
+ ...(options.exclude ?? []),
55
+ ];
56
+ const gitignore = loadGitignore(baseDir);
57
+ const allFiles = await glob(pattern, {
58
+ cwd: baseDir,
59
+ ignore: ignorePatterns,
60
+ nodir: true,
61
+ absolute: false,
62
+ dot: false,
63
+ });
64
+ const filteredFiles = allFiles.filter((relPath) => {
65
+ // Apply .gitignore rules
66
+ if (gitignore.ignores(relPath))
67
+ return false;
68
+ const absPath = path.join(baseDir, relPath);
69
+ return isSupportedFile(absPath);
70
+ });
71
+ return filteredFiles.map((relPath) => path.join(baseDir, relPath));
72
+ }
73
+ export function readFileSafe(filePath) {
74
+ try {
75
+ return fs.readFileSync(filePath, 'utf8');
76
+ }
77
+ catch {
78
+ return null;
79
+ }
80
+ }
81
+ //# sourceMappingURL=file-walker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-walker.js","sourceRoot":"","sources":["../../src/scanner/file-walker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { SupportedLanguage } from '../types/index.js';
2
+ export declare function detectLanguage(filePath: string, firstLine?: string): SupportedLanguage | null;
3
+ export declare function isSupportedFile(filePath: string, firstLine?: string): boolean;
4
+ export declare function languageMatches(ruleLangs: SupportedLanguage[], fileLang: SupportedLanguage): boolean;
5
+ //# sourceMappingURL=language-detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"language-detect.d.ts","sourceRoot":"","sources":["../../src/scanner/language-detect.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AA+D3D,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,GACjB,iBAAiB,GAAG,IAAI,CAsB1B;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAE7E;AAGD,wBAAgB,eAAe,CAC7B,SAAS,EAAE,iBAAiB,EAAE,EAC9B,QAAQ,EAAE,iBAAiB,GAC1B,OAAO,CAOT"}
@@ -0,0 +1,91 @@
1
+ // ============================================================
2
+ // Language Detection — maps file extensions to SupportedLanguage
3
+ // ============================================================
4
+ import path from 'path';
5
+ const EXTENSION_MAP = {
6
+ // JavaScript / TypeScript
7
+ '.js': 'javascript',
8
+ '.mjs': 'javascript',
9
+ '.cjs': 'javascript',
10
+ '.jsx': 'javascript',
11
+ '.ts': 'typescript',
12
+ '.tsx': 'typescript',
13
+ '.mts': 'typescript',
14
+ '.cts': 'typescript',
15
+ // Python
16
+ '.py': 'python',
17
+ '.pyw': 'python',
18
+ '.pyi': 'python',
19
+ // Java
20
+ '.java': 'java',
21
+ // Go
22
+ '.go': 'go',
23
+ // PHP
24
+ '.php': 'php',
25
+ '.php3': 'php',
26
+ '.php4': 'php',
27
+ '.php5': 'php',
28
+ '.phtml': 'php',
29
+ // Ruby
30
+ '.rb': 'ruby',
31
+ '.rake': 'ruby',
32
+ '.gemspec': 'ruby',
33
+ // C#
34
+ '.cs': 'csharp',
35
+ // C / C++
36
+ '.c': 'cpp',
37
+ '.cc': 'cpp',
38
+ '.cpp': 'cpp',
39
+ '.cxx': 'cpp',
40
+ '.h': 'cpp',
41
+ '.hpp': 'cpp',
42
+ // Rust
43
+ '.rs': 'rust',
44
+ };
45
+ const SHEBANG_MAP = {
46
+ 'node': 'javascript',
47
+ 'nodejs': 'javascript',
48
+ 'ts-node': 'typescript',
49
+ 'tsx': 'typescript',
50
+ 'python': 'python',
51
+ 'python3': 'python',
52
+ 'python2': 'python',
53
+ 'ruby': 'ruby',
54
+ 'php': 'php',
55
+ };
56
+ export function detectLanguage(filePath, firstLine) {
57
+ const ext = path.extname(filePath).toLowerCase();
58
+ // Extension-based detection (fast path)
59
+ if (ext in EXTENSION_MAP) {
60
+ return EXTENSION_MAP[ext];
61
+ }
62
+ // Shebang-based detection for extensionless files
63
+ if (firstLine?.startsWith('#!')) {
64
+ const parts = firstLine.split(/\s+/);
65
+ const interpreter = path.basename(parts[0].replace('#!', ''));
66
+ if (interpreter in SHEBANG_MAP) {
67
+ return SHEBANG_MAP[interpreter];
68
+ }
69
+ // Handle /usr/bin/env python style shebangs
70
+ if (parts[1] && path.basename(parts[1]) in SHEBANG_MAP) {
71
+ return SHEBANG_MAP[path.basename(parts[1])];
72
+ }
73
+ }
74
+ return null;
75
+ }
76
+ export function isSupportedFile(filePath, firstLine) {
77
+ return detectLanguage(filePath, firstLine) !== null;
78
+ }
79
+ // Languages where JS/TS patterns also apply (superset check)
80
+ export function languageMatches(ruleLangs, fileLang) {
81
+ if (ruleLangs.includes('all'))
82
+ return true;
83
+ if (ruleLangs.includes(fileLang))
84
+ return true;
85
+ // TypeScript is a superset of JavaScript — JS rules apply to TS files
86
+ if (fileLang === 'typescript' && ruleLangs.includes('javascript'))
87
+ return true;
88
+ // JSX/TSX handled by javascript/typescript rules
89
+ return false;
90
+ }
91
+ //# sourceMappingURL=language-detect.js.map