@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.
- package/LICENSE +235 -0
- package/README.md +561 -2
- package/dist/src/cli.d.ts +20 -0
- package/dist/src/cli.js +619 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/core/analyze.d.ts +178 -0
- package/dist/src/core/analyze.js +834 -0
- package/dist/src/core/analyze.js.map +1 -0
- package/dist/src/core/coverage.d.ts +87 -0
- package/dist/src/core/coverage.js +181 -0
- package/dist/src/core/coverage.js.map +1 -0
- package/dist/src/core/finding.d.ts +196 -0
- package/dist/src/core/finding.js +178 -0
- package/dist/src/core/finding.js.map +1 -0
- package/dist/src/core/licence.d.ts +50 -0
- package/dist/src/core/licence.js +56 -0
- package/dist/src/core/licence.js.map +1 -0
- package/dist/src/core/paths.d.ts +21 -0
- package/dist/src/core/paths.js +58 -0
- package/dist/src/core/paths.js.map +1 -0
- package/dist/src/core/score.d.ts +137 -0
- package/dist/src/core/score.js +232 -0
- package/dist/src/core/score.js.map +1 -0
- package/dist/src/dast/targets.d.ts +30 -0
- package/dist/src/dast/targets.js +79 -0
- package/dist/src/dast/targets.js.map +1 -0
- package/dist/src/dast/zap.d.ts +42 -0
- package/dist/src/dast/zap.js +184 -0
- package/dist/src/dast/zap.js.map +1 -0
- package/dist/src/engine/scan.d.ts +80 -0
- package/dist/src/engine/scan.js +129 -0
- package/dist/src/engine/scan.js.map +1 -0
- package/dist/src/engine/shapes.d.ts +47 -0
- package/dist/src/engine/shapes.js +328 -0
- package/dist/src/engine/shapes.js.map +1 -0
- package/dist/src/engine/walk.d.ts +60 -0
- package/dist/src/engine/walk.js +156 -0
- package/dist/src/engine/walk.js.map +1 -0
- package/dist/src/parse/astDump.d.ts +31 -0
- package/dist/src/parse/astDump.js +66 -0
- package/dist/src/parse/astDump.js.map +1 -0
- package/dist/src/parse/languages.d.ts +70 -0
- package/dist/src/parse/languages.js +174 -0
- package/dist/src/parse/languages.js.map +1 -0
- package/dist/src/parse/location.d.ts +17 -0
- package/dist/src/parse/location.js +38 -0
- package/dist/src/parse/location.js.map +1 -0
- package/dist/src/parse/node-grammars.d.ts +12 -0
- package/dist/src/parse/node-grammars.js +35 -0
- package/dist/src/parse/node-grammars.js.map +1 -0
- package/dist/src/parse/parser.d.ts +126 -0
- package/dist/src/parse/parser.js +202 -0
- package/dist/src/parse/parser.js.map +1 -0
- package/dist/src/parse/tree-store.d.ts +139 -0
- package/dist/src/parse/tree-store.js +236 -0
- package/dist/src/parse/tree-store.js.map +1 -0
- package/dist/src/platform/dependency-rule.d.ts +27 -0
- package/dist/src/platform/dependency-rule.js +21 -0
- package/dist/src/platform/dependency-rule.js.map +1 -0
- package/dist/src/platform/deps.d.ts +86 -0
- package/dist/src/platform/deps.js +304 -0
- package/dist/src/platform/deps.js.map +1 -0
- package/dist/src/platform/php-facts.d.ts +49 -0
- package/dist/src/platform/php-facts.js +67 -0
- package/dist/src/platform/php-facts.js.map +1 -0
- package/dist/src/platform/runtime-version.d.ts +78 -0
- package/dist/src/platform/runtime-version.js +573 -0
- package/dist/src/platform/runtime-version.js.map +1 -0
- package/dist/src/report/colors.d.ts +50 -0
- package/dist/src/report/colors.js +97 -0
- package/dist/src/report/colors.js.map +1 -0
- package/dist/src/report/coverage-table.d.ts +90 -0
- package/dist/src/report/coverage-table.js +291 -0
- package/dist/src/report/coverage-table.js.map +1 -0
- package/dist/src/report/html-report.d.ts +66 -0
- package/dist/src/report/html-report.js +489 -0
- package/dist/src/report/html-report.js.map +1 -0
- package/dist/src/report/human.d.ts +44 -0
- package/dist/src/report/human.js +575 -0
- package/dist/src/report/human.js.map +1 -0
- package/dist/src/report/json.d.ts +24 -0
- package/dist/src/report/json.js +178 -0
- package/dist/src/report/json.js.map +1 -0
- package/dist/src/report/mark.d.ts +17 -0
- package/dist/src/report/mark.js +39 -0
- package/dist/src/report/mark.js.map +1 -0
- package/dist/src/report/pricing.d.ts +33 -0
- package/dist/src/report/pricing.js +343 -0
- package/dist/src/report/pricing.js.map +1 -0
- package/dist/src/report/sarif.d.ts +39 -0
- package/dist/src/report/sarif.js +219 -0
- package/dist/src/report/sarif.js.map +1 -0
- package/dist/src/report/site.d.ts +87 -0
- package/dist/src/report/site.js +742 -0
- package/dist/src/report/site.js.map +1 -0
- package/dist/src/rules/code-injection.d.ts +47 -0
- package/dist/src/rules/code-injection.js +326 -0
- package/dist/src/rules/code-injection.js.map +1 -0
- package/dist/src/rules/command-injection.d.ts +30 -0
- package/dist/src/rules/command-injection.js +286 -0
- package/dist/src/rules/command-injection.js.map +1 -0
- package/dist/src/rules/contract.d.ts +198 -0
- package/dist/src/rules/contract.js +39 -0
- package/dist/src/rules/contract.js.map +1 -0
- package/dist/src/rules/format-string.d.ts +46 -0
- package/dist/src/rules/format-string.js +146 -0
- package/dist/src/rules/format-string.js.map +1 -0
- package/dist/src/rules/hardcoded-secret.d.ts +38 -0
- package/dist/src/rules/hardcoded-secret.js +440 -0
- package/dist/src/rules/hardcoded-secret.js.map +1 -0
- package/dist/src/rules/lib/guards.d.ts +168 -0
- package/dist/src/rules/lib/guards.js +1179 -0
- package/dist/src/rules/lib/guards.js.map +1 -0
- package/dist/src/rules/lib/html-safety.d.ts +75 -0
- package/dist/src/rules/lib/html-safety.js +755 -0
- package/dist/src/rules/lib/html-safety.js.map +1 -0
- package/dist/src/rules/lib/local-build.d.ts +59 -0
- package/dist/src/rules/lib/local-build.js +320 -0
- package/dist/src/rules/lib/local-build.js.map +1 -0
- package/dist/src/rules/lib/strings.d.ts +208 -0
- package/dist/src/rules/lib/strings.js +1970 -0
- package/dist/src/rules/lib/strings.js.map +1 -0
- package/dist/src/rules/path-traversal.d.ts +33 -0
- package/dist/src/rules/path-traversal.js +96 -0
- package/dist/src/rules/path-traversal.js.map +1 -0
- package/dist/src/rules/registry.d.ts +19 -0
- package/dist/src/rules/registry.js +77 -0
- package/dist/src/rules/registry.js.map +1 -0
- package/dist/src/rules/sql-injection.d.ts +36 -0
- package/dist/src/rules/sql-injection.js +299 -0
- package/dist/src/rules/sql-injection.js.map +1 -0
- package/dist/src/rules/ssrf.d.ts +39 -0
- package/dist/src/rules/ssrf.js +111 -0
- package/dist/src/rules/ssrf.js.map +1 -0
- package/dist/src/rules/unbounded-copy.d.ts +37 -0
- package/dist/src/rules/unbounded-copy.js +147 -0
- package/dist/src/rules/unbounded-copy.js.map +1 -0
- package/dist/src/rules/unsafe-deserialization.d.ts +43 -0
- package/dist/src/rules/unsafe-deserialization.js +276 -0
- package/dist/src/rules/unsafe-deserialization.js.map +1 -0
- package/dist/src/rules/weak-hash.d.ts +37 -0
- package/dist/src/rules/weak-hash.js +197 -0
- package/dist/src/rules/weak-hash.js.map +1 -0
- package/dist/src/rules/xss.d.ts +38 -0
- package/dist/src/rules/xss.js +527 -0
- package/dist/src/rules/xss.js.map +1 -0
- package/dist/src/taint/content-type.d.ts +19 -0
- package/dist/src/taint/content-type.js +20 -0
- package/dist/src/taint/content-type.js.map +1 -0
- package/dist/src/taint/dictionaries.d.ts +23 -0
- package/dist/src/taint/dictionaries.js +1778 -0
- package/dist/src/taint/dictionaries.js.map +1 -0
- package/dist/src/taint/fold.d.ts +59 -0
- package/dist/src/taint/fold.js +1177 -0
- package/dist/src/taint/fold.js.map +1 -0
- package/dist/src/taint/java-scope.d.ts +61 -0
- package/dist/src/taint/java-scope.js +212 -0
- package/dist/src/taint/java-scope.js.map +1 -0
- package/dist/src/taint/local-map.d.ts +79 -0
- package/dist/src/taint/local-map.js +603 -0
- package/dist/src/taint/local-map.js.map +1 -0
- package/dist/src/taint/project.d.ts +172 -0
- package/dist/src/taint/project.js +617 -0
- package/dist/src/taint/project.js.map +1 -0
- package/dist/src/taint/tracer.d.ts +265 -0
- package/dist/src/taint/tracer.js +3817 -0
- package/dist/src/taint/tracer.js.map +1 -0
- package/dist/src/taint/types.d.ts +484 -0
- package/dist/src/taint/types.js +47 -0
- package/dist/src/taint/types.js.map +1 -0
- package/dist/src/taint/visibility.d.ts +25 -0
- package/dist/src/taint/visibility.js +96 -0
- package/dist/src/taint/visibility.js.map +1 -0
- package/docs/examples/defuse.json +20 -0
- package/docs/examples/dvwa-urls.json +14 -0
- package/docs/examples/github-code-scanning.yml +54 -0
- package/docs/examples/tiny.js +4 -0
- package/package.json +73 -4
- package/src/cli.ts +747 -0
- package/src/core/analyze.ts +1072 -0
- package/src/core/coverage.ts +269 -0
- package/src/core/finding.ts +311 -0
- package/src/core/licence.ts +61 -0
- package/src/core/paths.ts +59 -0
- package/src/core/score.ts +353 -0
- package/src/dast/targets.ts +121 -0
- package/src/dast/zap.ts +246 -0
- package/src/engine/scan.ts +200 -0
- package/src/engine/shapes.ts +348 -0
- package/src/engine/walk.ts +196 -0
- package/src/parse/astDump.ts +85 -0
- package/src/parse/languages.ts +232 -0
- package/src/parse/location.ts +44 -0
- package/src/parse/node-grammars.ts +41 -0
- package/src/parse/parser.ts +262 -0
- package/src/parse/tree-store.ts +301 -0
- package/src/platform/dependency-rule.ts +33 -0
- package/src/platform/deps.ts +374 -0
- package/src/platform/php-facts.ts +85 -0
- package/src/platform/runtime-version.ts +710 -0
- package/src/report/colors.ts +107 -0
- package/src/report/coverage-table.ts +359 -0
- package/src/report/html-report.ts +601 -0
- package/src/report/human.ts +811 -0
- package/src/report/json.ts +189 -0
- package/src/report/mark.ts +47 -0
- package/src/report/pricing.ts +374 -0
- package/src/report/sarif.ts +235 -0
- package/src/report/site.ts +760 -0
- package/src/rules/code-injection.ts +346 -0
- package/src/rules/command-injection.ts +296 -0
- package/src/rules/contract.ts +220 -0
- package/src/rules/format-string.ts +158 -0
- package/src/rules/hardcoded-secret.ts +485 -0
- package/src/rules/lib/guards.ts +1235 -0
- package/src/rules/lib/html-safety.ts +793 -0
- package/src/rules/lib/local-build.ts +329 -0
- package/src/rules/lib/strings.ts +2034 -0
- package/src/rules/path-traversal.ts +101 -0
- package/src/rules/registry.ts +90 -0
- package/src/rules/sql-injection.ts +311 -0
- package/src/rules/ssrf.ts +118 -0
- package/src/rules/unbounded-copy.ts +162 -0
- package/src/rules/unsafe-deserialization.ts +291 -0
- package/src/rules/weak-hash.ts +226 -0
- package/src/rules/xss.ts +572 -0
- package/src/taint/content-type.ts +20 -0
- package/src/taint/dictionaries.ts +1855 -0
- package/src/taint/fold.ts +1206 -0
- package/src/taint/java-scope.ts +200 -0
- package/src/taint/local-map.ts +594 -0
- package/src/taint/project.ts +774 -0
- package/src/taint/tracer.ts +4298 -0
- package/src/taint/types.ts +511 -0
- package/src/taint/visibility.ts +100 -0
- 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;
|