@sikkuumiii/defuse 0.0.0-stage → 0.5.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 (236) hide show
  1. package/LICENSE +235 -0
  2. package/README.md +561 -2
  3. package/dist/src/cli.d.ts +20 -0
  4. package/dist/src/cli.js +619 -0
  5. package/dist/src/cli.js.map +1 -0
  6. package/dist/src/core/analyze.d.ts +178 -0
  7. package/dist/src/core/analyze.js +834 -0
  8. package/dist/src/core/analyze.js.map +1 -0
  9. package/dist/src/core/coverage.d.ts +87 -0
  10. package/dist/src/core/coverage.js +181 -0
  11. package/dist/src/core/coverage.js.map +1 -0
  12. package/dist/src/core/finding.d.ts +196 -0
  13. package/dist/src/core/finding.js +178 -0
  14. package/dist/src/core/finding.js.map +1 -0
  15. package/dist/src/core/licence.d.ts +50 -0
  16. package/dist/src/core/licence.js +56 -0
  17. package/dist/src/core/licence.js.map +1 -0
  18. package/dist/src/core/paths.d.ts +21 -0
  19. package/dist/src/core/paths.js +58 -0
  20. package/dist/src/core/paths.js.map +1 -0
  21. package/dist/src/core/score.d.ts +137 -0
  22. package/dist/src/core/score.js +232 -0
  23. package/dist/src/core/score.js.map +1 -0
  24. package/dist/src/dast/targets.d.ts +30 -0
  25. package/dist/src/dast/targets.js +79 -0
  26. package/dist/src/dast/targets.js.map +1 -0
  27. package/dist/src/dast/zap.d.ts +42 -0
  28. package/dist/src/dast/zap.js +184 -0
  29. package/dist/src/dast/zap.js.map +1 -0
  30. package/dist/src/engine/scan.d.ts +80 -0
  31. package/dist/src/engine/scan.js +129 -0
  32. package/dist/src/engine/scan.js.map +1 -0
  33. package/dist/src/engine/shapes.d.ts +47 -0
  34. package/dist/src/engine/shapes.js +328 -0
  35. package/dist/src/engine/shapes.js.map +1 -0
  36. package/dist/src/engine/walk.d.ts +60 -0
  37. package/dist/src/engine/walk.js +156 -0
  38. package/dist/src/engine/walk.js.map +1 -0
  39. package/dist/src/parse/astDump.d.ts +31 -0
  40. package/dist/src/parse/astDump.js +66 -0
  41. package/dist/src/parse/astDump.js.map +1 -0
  42. package/dist/src/parse/languages.d.ts +70 -0
  43. package/dist/src/parse/languages.js +174 -0
  44. package/dist/src/parse/languages.js.map +1 -0
  45. package/dist/src/parse/location.d.ts +17 -0
  46. package/dist/src/parse/location.js +38 -0
  47. package/dist/src/parse/location.js.map +1 -0
  48. package/dist/src/parse/node-grammars.d.ts +12 -0
  49. package/dist/src/parse/node-grammars.js +35 -0
  50. package/dist/src/parse/node-grammars.js.map +1 -0
  51. package/dist/src/parse/parser.d.ts +126 -0
  52. package/dist/src/parse/parser.js +202 -0
  53. package/dist/src/parse/parser.js.map +1 -0
  54. package/dist/src/parse/tree-store.d.ts +139 -0
  55. package/dist/src/parse/tree-store.js +236 -0
  56. package/dist/src/parse/tree-store.js.map +1 -0
  57. package/dist/src/platform/dependency-rule.d.ts +27 -0
  58. package/dist/src/platform/dependency-rule.js +21 -0
  59. package/dist/src/platform/dependency-rule.js.map +1 -0
  60. package/dist/src/platform/deps.d.ts +86 -0
  61. package/dist/src/platform/deps.js +304 -0
  62. package/dist/src/platform/deps.js.map +1 -0
  63. package/dist/src/platform/php-facts.d.ts +49 -0
  64. package/dist/src/platform/php-facts.js +67 -0
  65. package/dist/src/platform/php-facts.js.map +1 -0
  66. package/dist/src/platform/runtime-version.d.ts +78 -0
  67. package/dist/src/platform/runtime-version.js +573 -0
  68. package/dist/src/platform/runtime-version.js.map +1 -0
  69. package/dist/src/report/colors.d.ts +50 -0
  70. package/dist/src/report/colors.js +97 -0
  71. package/dist/src/report/colors.js.map +1 -0
  72. package/dist/src/report/coverage-table.d.ts +90 -0
  73. package/dist/src/report/coverage-table.js +291 -0
  74. package/dist/src/report/coverage-table.js.map +1 -0
  75. package/dist/src/report/html-report.d.ts +66 -0
  76. package/dist/src/report/html-report.js +489 -0
  77. package/dist/src/report/html-report.js.map +1 -0
  78. package/dist/src/report/human.d.ts +44 -0
  79. package/dist/src/report/human.js +575 -0
  80. package/dist/src/report/human.js.map +1 -0
  81. package/dist/src/report/json.d.ts +24 -0
  82. package/dist/src/report/json.js +178 -0
  83. package/dist/src/report/json.js.map +1 -0
  84. package/dist/src/report/mark.d.ts +17 -0
  85. package/dist/src/report/mark.js +39 -0
  86. package/dist/src/report/mark.js.map +1 -0
  87. package/dist/src/report/pricing.d.ts +33 -0
  88. package/dist/src/report/pricing.js +343 -0
  89. package/dist/src/report/pricing.js.map +1 -0
  90. package/dist/src/report/sarif.d.ts +39 -0
  91. package/dist/src/report/sarif.js +219 -0
  92. package/dist/src/report/sarif.js.map +1 -0
  93. package/dist/src/report/site.d.ts +87 -0
  94. package/dist/src/report/site.js +742 -0
  95. package/dist/src/report/site.js.map +1 -0
  96. package/dist/src/rules/code-injection.d.ts +47 -0
  97. package/dist/src/rules/code-injection.js +326 -0
  98. package/dist/src/rules/code-injection.js.map +1 -0
  99. package/dist/src/rules/command-injection.d.ts +30 -0
  100. package/dist/src/rules/command-injection.js +286 -0
  101. package/dist/src/rules/command-injection.js.map +1 -0
  102. package/dist/src/rules/contract.d.ts +198 -0
  103. package/dist/src/rules/contract.js +39 -0
  104. package/dist/src/rules/contract.js.map +1 -0
  105. package/dist/src/rules/format-string.d.ts +46 -0
  106. package/dist/src/rules/format-string.js +146 -0
  107. package/dist/src/rules/format-string.js.map +1 -0
  108. package/dist/src/rules/hardcoded-secret.d.ts +38 -0
  109. package/dist/src/rules/hardcoded-secret.js +440 -0
  110. package/dist/src/rules/hardcoded-secret.js.map +1 -0
  111. package/dist/src/rules/lib/guards.d.ts +168 -0
  112. package/dist/src/rules/lib/guards.js +1179 -0
  113. package/dist/src/rules/lib/guards.js.map +1 -0
  114. package/dist/src/rules/lib/html-safety.d.ts +75 -0
  115. package/dist/src/rules/lib/html-safety.js +755 -0
  116. package/dist/src/rules/lib/html-safety.js.map +1 -0
  117. package/dist/src/rules/lib/local-build.d.ts +59 -0
  118. package/dist/src/rules/lib/local-build.js +320 -0
  119. package/dist/src/rules/lib/local-build.js.map +1 -0
  120. package/dist/src/rules/lib/strings.d.ts +208 -0
  121. package/dist/src/rules/lib/strings.js +1970 -0
  122. package/dist/src/rules/lib/strings.js.map +1 -0
  123. package/dist/src/rules/path-traversal.d.ts +33 -0
  124. package/dist/src/rules/path-traversal.js +96 -0
  125. package/dist/src/rules/path-traversal.js.map +1 -0
  126. package/dist/src/rules/registry.d.ts +19 -0
  127. package/dist/src/rules/registry.js +77 -0
  128. package/dist/src/rules/registry.js.map +1 -0
  129. package/dist/src/rules/sql-injection.d.ts +36 -0
  130. package/dist/src/rules/sql-injection.js +299 -0
  131. package/dist/src/rules/sql-injection.js.map +1 -0
  132. package/dist/src/rules/ssrf.d.ts +39 -0
  133. package/dist/src/rules/ssrf.js +111 -0
  134. package/dist/src/rules/ssrf.js.map +1 -0
  135. package/dist/src/rules/unbounded-copy.d.ts +37 -0
  136. package/dist/src/rules/unbounded-copy.js +147 -0
  137. package/dist/src/rules/unbounded-copy.js.map +1 -0
  138. package/dist/src/rules/unsafe-deserialization.d.ts +43 -0
  139. package/dist/src/rules/unsafe-deserialization.js +276 -0
  140. package/dist/src/rules/unsafe-deserialization.js.map +1 -0
  141. package/dist/src/rules/weak-hash.d.ts +37 -0
  142. package/dist/src/rules/weak-hash.js +197 -0
  143. package/dist/src/rules/weak-hash.js.map +1 -0
  144. package/dist/src/rules/xss.d.ts +38 -0
  145. package/dist/src/rules/xss.js +527 -0
  146. package/dist/src/rules/xss.js.map +1 -0
  147. package/dist/src/taint/content-type.d.ts +19 -0
  148. package/dist/src/taint/content-type.js +20 -0
  149. package/dist/src/taint/content-type.js.map +1 -0
  150. package/dist/src/taint/dictionaries.d.ts +23 -0
  151. package/dist/src/taint/dictionaries.js +1778 -0
  152. package/dist/src/taint/dictionaries.js.map +1 -0
  153. package/dist/src/taint/fold.d.ts +59 -0
  154. package/dist/src/taint/fold.js +1177 -0
  155. package/dist/src/taint/fold.js.map +1 -0
  156. package/dist/src/taint/java-scope.d.ts +61 -0
  157. package/dist/src/taint/java-scope.js +212 -0
  158. package/dist/src/taint/java-scope.js.map +1 -0
  159. package/dist/src/taint/local-map.d.ts +79 -0
  160. package/dist/src/taint/local-map.js +603 -0
  161. package/dist/src/taint/local-map.js.map +1 -0
  162. package/dist/src/taint/project.d.ts +172 -0
  163. package/dist/src/taint/project.js +617 -0
  164. package/dist/src/taint/project.js.map +1 -0
  165. package/dist/src/taint/tracer.d.ts +265 -0
  166. package/dist/src/taint/tracer.js +3817 -0
  167. package/dist/src/taint/tracer.js.map +1 -0
  168. package/dist/src/taint/types.d.ts +484 -0
  169. package/dist/src/taint/types.js +47 -0
  170. package/dist/src/taint/types.js.map +1 -0
  171. package/dist/src/taint/visibility.d.ts +25 -0
  172. package/dist/src/taint/visibility.js +96 -0
  173. package/dist/src/taint/visibility.js.map +1 -0
  174. package/docs/examples/defuse.json +20 -0
  175. package/docs/examples/dvwa-urls.json +14 -0
  176. package/docs/examples/github-code-scanning.yml +54 -0
  177. package/docs/examples/tiny.js +4 -0
  178. package/package.json +73 -4
  179. package/src/cli.ts +747 -0
  180. package/src/core/analyze.ts +1072 -0
  181. package/src/core/coverage.ts +269 -0
  182. package/src/core/finding.ts +311 -0
  183. package/src/core/licence.ts +61 -0
  184. package/src/core/paths.ts +59 -0
  185. package/src/core/score.ts +353 -0
  186. package/src/dast/targets.ts +121 -0
  187. package/src/dast/zap.ts +246 -0
  188. package/src/engine/scan.ts +200 -0
  189. package/src/engine/shapes.ts +348 -0
  190. package/src/engine/walk.ts +196 -0
  191. package/src/parse/astDump.ts +85 -0
  192. package/src/parse/languages.ts +232 -0
  193. package/src/parse/location.ts +44 -0
  194. package/src/parse/node-grammars.ts +41 -0
  195. package/src/parse/parser.ts +262 -0
  196. package/src/parse/tree-store.ts +301 -0
  197. package/src/platform/dependency-rule.ts +33 -0
  198. package/src/platform/deps.ts +374 -0
  199. package/src/platform/php-facts.ts +85 -0
  200. package/src/platform/runtime-version.ts +710 -0
  201. package/src/report/colors.ts +107 -0
  202. package/src/report/coverage-table.ts +359 -0
  203. package/src/report/html-report.ts +601 -0
  204. package/src/report/human.ts +811 -0
  205. package/src/report/json.ts +189 -0
  206. package/src/report/mark.ts +47 -0
  207. package/src/report/pricing.ts +374 -0
  208. package/src/report/sarif.ts +235 -0
  209. package/src/report/site.ts +760 -0
  210. package/src/rules/code-injection.ts +346 -0
  211. package/src/rules/command-injection.ts +296 -0
  212. package/src/rules/contract.ts +220 -0
  213. package/src/rules/format-string.ts +158 -0
  214. package/src/rules/hardcoded-secret.ts +485 -0
  215. package/src/rules/lib/guards.ts +1235 -0
  216. package/src/rules/lib/html-safety.ts +793 -0
  217. package/src/rules/lib/local-build.ts +329 -0
  218. package/src/rules/lib/strings.ts +2034 -0
  219. package/src/rules/path-traversal.ts +101 -0
  220. package/src/rules/registry.ts +90 -0
  221. package/src/rules/sql-injection.ts +311 -0
  222. package/src/rules/ssrf.ts +118 -0
  223. package/src/rules/unbounded-copy.ts +162 -0
  224. package/src/rules/unsafe-deserialization.ts +291 -0
  225. package/src/rules/weak-hash.ts +226 -0
  226. package/src/rules/xss.ts +572 -0
  227. package/src/taint/content-type.ts +20 -0
  228. package/src/taint/dictionaries.ts +1855 -0
  229. package/src/taint/fold.ts +1206 -0
  230. package/src/taint/java-scope.ts +200 -0
  231. package/src/taint/local-map.ts +594 -0
  232. package/src/taint/project.ts +774 -0
  233. package/src/taint/tracer.ts +4298 -0
  234. package/src/taint/types.ts +511 -0
  235. package/src/taint/visibility.ts +100 -0
  236. package/tsconfig.json +61 -0
@@ -0,0 +1,172 @@
1
+ /**
2
+ * THE PROJECT INDEX (cross-file resolution)
3
+ * ==========================================
4
+ *
5
+ * Up to now the tracer could follow a value anywhere inside one file and no
6
+ * further. `helper(dirty)` where `helper` lives in `./helpers.js` was the end of
7
+ * the road, and on real code that is where most of the road is: applications put
8
+ * their database access in `db.js`, their escaping in `util/html.py`, their
9
+ * command runners in `Shell.java`.
10
+ *
11
+ * This module answers one question: **"file F calls a function named N - which
12
+ * file, if any, is that?"**
13
+ *
14
+ * THE RULE IT PLAYS BY: answer only when the answer is unambiguous.
15
+ *
16
+ * If two imported modules both define `sanitize`, we say nothing and record
17
+ * that we declined. Picking one at random would let the tool print a
18
+ * step-by-step "proof" through a function that never runs - which is worse than
19
+ * printing nothing, because it looks like evidence. The count of declined
20
+ * resolutions is reported in every scan.
21
+ *
22
+ * HOW IMPORTS ARE FOUND, per language:
23
+ *
24
+ * JS/TS `import x from './a'` and `require('./a')`, resolved relative to the
25
+ * importing file, trying the usual extensions and `/index`.
26
+ * Python `from .a import x`, `from pkg.a import x`, `import pkg.a` - resolved
27
+ * against the files actually present in the scan.
28
+ * Java `import com.x.Bar;` resolves to a file named `Bar.java`, PLUS every
29
+ * file in the same directory, because Java classes in the same
30
+ * package see each other with no import at all.
31
+ * Go every file in the same directory, because that is one package. Go
32
+ * imports name packages rather than files, and resolving those needs
33
+ * module metadata we do not read.
34
+ *
35
+ * WHAT IT DOES NOT DO, stated here and in the scan report:
36
+ * - It does not check that the function is actually EXPORTED. A module-private
37
+ * helper with the same name as an exported one could be entered.
38
+ * - It does not follow re-exports (`export * from './a'`).
39
+ * - It does not resolve node_modules, third-party packages, or aliases from
40
+ * tsconfig `paths` / webpack config.
41
+ * - Dynamic imports and computed requires are invisible.
42
+ */
43
+ import type { Node } from 'web-tree-sitter';
44
+ import type { LanguageId } from '../parse/languages.js';
45
+ import { type TreeStore } from '../parse/tree-store.js';
46
+ import { type CrossFileResolver } from './tracer.js';
47
+ /**
48
+ * A function recorded as COORDINATES rather than as a syntax node.
49
+ *
50
+ * This is the change that lets the memory ceiling go away. The index used to
51
+ * hold a live Node for every function body in the project, and a Node keeps its
52
+ * whole tree alive - so indexing the project pinned every tree in it, whether
53
+ * or not anything ever traced into them. Holding two integers and a string
54
+ * instead lets the trees be freed, at the cost of parsing a file again on the
55
+ * rare occasion the tracer actually descends into it.
56
+ *
57
+ * bodyType is recorded alongside the offsets because a byte range alone is not
58
+ * always unique: a node can share its exact extent with its parent. The type is
59
+ * what tells them apart, and a lookup that cannot match both is refused.
60
+ */
61
+ export interface IndexedFunction {
62
+ readonly name: string;
63
+ readonly params: readonly string[];
64
+ /** The argument range the function accepts - see LocalFunction.minArgs. */
65
+ readonly minArgs?: number | undefined;
66
+ readonly maxArgs?: number | undefined;
67
+ readonly bodyStart: number;
68
+ readonly bodyEnd: number;
69
+ readonly bodyType: string;
70
+ }
71
+ /**
72
+ * What buildProjectIndex needs from each file. Everything here is extracted
73
+ * while the file's tree is hot during the first pass, so the index itself never
74
+ * touches a tree and never holds one.
75
+ */
76
+ export interface IndexedFileInput {
77
+ readonly path: string;
78
+ readonly language: LanguageId;
79
+ readonly functions: ReadonlyMap<string, IndexedFunction>;
80
+ /** Raw module specifiers, already read out of the tree. */
81
+ readonly importSpecifiers: readonly string[];
82
+ /** Java only - see javaTypeFacts(). */
83
+ readonly javaTypes?: JavaTypeFacts | undefined;
84
+ }
85
+ /**
86
+ * What a Java file says about the types it declares and names, read from the
87
+ * top level of its tree in the first pass. staticMethod() below needs these to
88
+ * answer "which class does `Utils` mean here?" without holding the tree.
89
+ */
90
+ export interface JavaTypeFacts {
91
+ /** From `package a.b;` - the empty string for the unnamed package. */
92
+ readonly packageName: string;
93
+ /** Top-level type declarations of every kind - class, interface, enum, record, annotation. */
94
+ readonly types: readonly {
95
+ readonly name: string;
96
+ readonly kind: string;
97
+ }[];
98
+ /** `import a.b.C;` as `a.b.C`. Not `import a.b.*;`, not `import static`. */
99
+ readonly singleTypeImports: readonly string[];
100
+ /** The last name of each `import static a.b.C.m;` - a member that is then in scope by that name. */
101
+ readonly staticImports: readonly string[];
102
+ /** Whether any `import static a.b.C.*;` brings in members nobody here can list. */
103
+ readonly staticOnDemand: boolean;
104
+ /** Every type declared anywhere in the file, nested ones included. */
105
+ readonly allTypeNames: readonly string[];
106
+ }
107
+ export declare function javaTypeFacts(root: Node): JavaTypeFacts;
108
+ /** Turn a file's functions into coordinates, using the tracer's own definition. */
109
+ export declare function indexFunctions(root: Node, language: LanguageId): Map<string, IndexedFunction>;
110
+ export interface ProjectIndexStats {
111
+ readonly filesIndexed: number;
112
+ readonly functionsIndexed: number;
113
+ readonly importEdges: number;
114
+ /**
115
+ * Import statements we READ but could not point at a file in this scan.
116
+ *
117
+ * Counted because it is the difference between "this code imports nothing"
118
+ * and "this code imports 117 things and you gave me none of them". A beginner
119
+ * scanned juice-shop's server.ts on its own, got zero findings, and concluded
120
+ * the tool was broken. It was not: server.ts is a wiring file whose 117
121
+ * imports all pointed outside the scan, so every trace stopped at the first
122
+ * module boundary. The same repository's routes/ directory produces seven
123
+ * findings, two of them flow-verified.
124
+ *
125
+ * The report had the evidence - importEdges was 0 - and never said what it
126
+ * meant. An undeclared blind spot is exactly what this project refuses to
127
+ * ship, so it is declared now.
128
+ */
129
+ readonly importsUnresolved: number;
130
+ /** Times a cross-file call WAS followed. */
131
+ readonly resolved: number;
132
+ /** Times several files defined the name and we refused to choose. */
133
+ readonly ambiguous: number;
134
+ /**
135
+ * Times a function was found in the index but could not be located again in
136
+ * the re-parsed tree, and the resolution was declined rather than guessed.
137
+ *
138
+ * This should be zero forever: the parse is deterministic, so a node recorded
139
+ * at bytes 400-980 as a `block` is a `block` at bytes 400-980 every time the
140
+ * same file is parsed with the same grammar. It is counted anyway, because
141
+ * "should be impossible" is how a tool ends up tracing into the wrong
142
+ * function and printing a confident proof of it.
143
+ */
144
+ readonly relocationsFailed: number;
145
+ }
146
+ export interface ProjectIndex extends CrossFileResolver {
147
+ readonly stats: () => ProjectIndexStats;
148
+ /**
149
+ * The one static method `receiver.method(...)` can run, from a Java file -
150
+ * or null whenever that is in any doubt. See the note in the body.
151
+ */
152
+ readonly staticMethod: (fromPath: string, receiver: string, method: string,
153
+ /** Simple names of the types the call sits inside inherit from - see strings.ts. */
154
+ supertypes?: readonly string[],
155
+ /** The caller created the object with `new X(...)`, so an instance method is exact too. */
156
+ allowInstance?: boolean) => {
157
+ readonly path: string;
158
+ readonly method: Node;
159
+ } | null;
160
+ /** Is a Java type of this simple name - top-level or nested - declared anywhere in the scan? */
161
+ readonly javaTypeInScan: (simpleName: string) => boolean;
162
+ }
163
+ /** The raw module specifiers this file mentions, e.g. "./db", "app.helpers". */
164
+ export declare function importSpecifiers(root: Node, language: LanguageId): string[];
165
+ /**
166
+ * @param files one record per scanned file, with functions and import
167
+ * specifiers ALREADY extracted from its tree.
168
+ * @param store where trees come from. Only touched when a resolution actually
169
+ * succeeds, which on real projects is a small fraction of files -
170
+ * the index itself is built without a single tree in hand.
171
+ */
172
+ export declare function buildProjectIndex(files: readonly IndexedFileInput[], store: TreeStore): ProjectIndex;