Skip to content

Commit 1fb55a9

Browse files
authored
Merge pull request #297 from NodeSecure/prepare-major-8
Prepare major 8
2 parents 81e44c5 + 32e71b3 commit 1fb55a9

File tree

15 files changed

+215
-425
lines changed

15 files changed

+215
-425
lines changed

README.md

Lines changed: 9 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ The analysis will return: `http` (in try), `crypto`, `util` and `fs`.
8585
> [!TIP]
8686
> There is also a lot of suspicious code example in the `./examples` cases directory. Feel free to try the tool on these files.
8787
88+
## API
89+
90+
- [AstAnalyser](./docs/api/AstAnalyser.md)
91+
- [EntryFilesAnalyser](./docs/api/EntryFilesAnalyser.md)
92+
8893
## Warnings
8994

9095
This section describes how use `warnings` export.
@@ -118,7 +123,7 @@ import * as i18n from "@nodesecure/i18n";
118123
console.log(i18n.getTokenSync(jsxray.warnings["parsing-error"].i18n));
119124
```
120125

121-
## Warnings Legends
126+
### Legends
122127

123128
This section describe all the possible warnings returned by JSXRay. Click on the warning **name** for additional information and examples.
124129

@@ -131,161 +136,10 @@ This section describe all the possible warnings returned by JSXRay. Click on the
131136
| [encoded-literal](./docs/encoded-literal.md) || An encoded literal has been detected (it can be an hexa value, unicode sequence or a base64 string) |
132137
| [short-identifiers](./docs/short-identifiers.md) || This mean that all identifiers has an average length below 1.5. |
133138
| [suspicious-literal](./docs/suspicious-literal.md) || A suspicious literal has been found in the source code. |
134-
| [suspicious-file](./docs/suspicious-file.md) | ✔️ | A suspicious file with more than ten encoded-literal in it |
139+
| [suspicious-file](./docs/suspicious-file.md) | | A suspicious file with more than ten encoded-literal in it |
135140
| [obfuscated-code](./docs/obfuscated-code.md) | ✔️ | There's a very high probability that the code is obfuscated. |
136-
| [weak-crypto](./docs/weak-crypto.md) | ✔️ | The code probably contains a weak crypto algorithm (md5, sha1...) |
137-
| [shady-link](./docs/shady-link.md) | ✔️ | The code contains shady/unsafe link |
138-
139-
## Custom Probes
140-
141-
You can also create custom probes to detect specific pattern in the code you are analyzing.
142-
143-
A probe is a pair of two functions (`validateNode` and `main`) that will be called on each node of the AST. It will return a warning if the pattern is detected.
144-
Below a basic probe that detect a string assignation to `danger`:
145-
146-
```ts
147-
export const customProbes = [
148-
{
149-
name: "customProbeUnsafeDanger",
150-
validateNode: (node, sourceFile) => [
151-
node.type === "VariableDeclaration" && node.declarations[0].init.value === "danger"
152-
],
153-
main: (node, options) => {
154-
const { sourceFile, data: calleeName } = options;
155-
if (node.declarations[0].init.value === "danger") {
156-
sourceFile.addWarning("unsafe-danger", calleeName, node.loc);
157-
158-
return ProbeSignals.Skip;
159-
}
160-
161-
return null;
162-
}
163-
}
164-
];
165-
```
166-
167-
You can pass an array of probes to the `runASTAnalysis/runASTAnalysisOnFile` functions as `options`, or directly to the `AstAnalyser` constructor.
168-
169-
| Name | Type | Description | Default Value |
170-
|------------------|----------------------------------|-----------------------------------------------------------------------|-----------------|
171-
| `customParser` | `SourceParser \| undefined` | An optional custom parser to be used for parsing the source code. | `JsSourceParser` |
172-
| `customProbes` | `Probe[] \| undefined` | An array of custom probes to be used during AST analysis. | `[]` |
173-
| `skipDefaultProbes` | `boolean \| undefined` | If `true`, default probes will be skipped and only custom probes will be used. | `false` |
174-
175-
176-
Here using the example probe upper:
177-
178-
```ts
179-
import { AstAnalyser } from "@nodesecure/js-x-ray";
180-
181-
// add your customProbes here (see example above)
182-
183-
const scanner = new AstAnalyser({
184-
customProbes,
185-
skipDefaultProbes: true
186-
});
187-
188-
const result = scanner.analyse("const danger = 'danger';");
189-
190-
console.log(result);
191-
```
192-
193-
Result:
194-
195-
```sh
196-
✗ node example.js
197-
{
198-
idsLengthAvg: 0,
199-
stringScore: 0,
200-
warnings: [ { kind: 'unsafe-danger', location: [Array], source: 'JS-X-Ray' } ],
201-
dependencies: Map(0) {},
202-
isOneLineRequire: false
203-
}
204-
```
205-
206-
Congrats, you have created your first custom probe! 🎉
207-
208-
> [!TIP]
209-
> Check the types in [index.d.ts](index.d.ts) and [types/api.d.ts](types/api.d.ts) for more details about the `options`
210-
211-
## API
212-
213-
- [AstAnalyser](./docs/api/AstAnalyser.md)
214-
- [EntryFilesAnalyser](./docs/api/EntryFilesAnalyser.md)
215-
216-
Legacy APIs waiting to be deprecated;
217-
218-
<details>
219-
<summary>runASTAnalysis(str: string, options?: RuntimeOptions & AstAnalyserOptions): Report</summary>
220-
221-
```ts
222-
interface RuntimeOptions {
223-
module?: boolean;
224-
removeHTMLComments?: boolean;
225-
isMinified?: boolean;
226-
initialize?: (sourceFile: SourceFile) => void;
227-
finalize?: (sourceFile: SourceFile) => void;
228-
}
229-
```
230-
231-
```ts
232-
interface AstAnalyserOptions {
233-
customParser?: SourceParser;
234-
customProbes?: Probe[];
235-
skipDefaultProbes?: boolean;
236-
}
237-
```
238-
239-
The method take a first argument which is the code you want to analyse. It will return a Report Object:
240-
241-
```ts
242-
interface Report {
243-
dependencies: ASTDeps;
244-
warnings: Warning[];
245-
idsLengthAvg: number;
246-
stringScore: number;
247-
isOneLineRequire: boolean;
248-
}
249-
```
250-
251-
</details>
252-
253-
<details>
254-
<summary>runASTAnalysisOnFile(pathToFile: string, options?: RuntimeFileOptions & AstAnalyserOptions): Promise< ReportOnFile ></summary>
255-
256-
```ts
257-
interface RuntimeFileOptions {
258-
module?: boolean;
259-
removeHTMLComments?: boolean;
260-
packageName?: string;
261-
initialize?: (sourceFile: SourceFile) => void;
262-
finalize?: (sourceFile: SourceFile) => void;
263-
}
264-
```
265-
266-
```ts
267-
interface AstAnalyserOptions {
268-
customParser?: SourceParser;
269-
customProbes?: Probe[];
270-
skipDefaultProbes?: boolean;
271-
}
272-
```
273-
274-
Run the SAST scanner on a given JavaScript file.
275-
276-
```ts
277-
export type ReportOnFile = {
278-
ok: true,
279-
warnings: Warning[];
280-
dependencies: ASTDeps;
281-
isMinified: boolean;
282-
} | {
283-
ok: false,
284-
warnings: Warning[];
285-
}
286-
```
287-
288-
</details>
141+
| [weak-crypto](./docs/weak-crypto.md) || The code probably contains a weak crypto algorithm (md5, sha1...) |
142+
| [shady-link](./docs/shady-link.md) || The code contains shady/unsafe link |
289143

290144
## Workspaces
291145

docs/api/AstAnalyser.md

Lines changed: 89 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,30 @@ declare class AstAnalyser {
4040
constructor(options?: AstAnalyserOptions);
4141
analyse: (str: string, options?: RuntimeOptions) => Report;
4242
analyseFile(pathToFile: string, options?: RuntimeFileOptions): Promise<ReportOnFile>;
43+
analyseFileSync(pathToFile: string, options?: RuntimeFileOptions): ReportOnFile;
4344
}
4445
```
4546

46-
The `analyseFile` method is a superset of `analyse` with the ability to read the file on the local filesystem with additional features like detecting if the file is ESM or CJS.
47+
The `analyseFile` and `analyseFileSync` methods is a superset of `analyse` with the ability to read the file on the local filesystem with additional features like detecting if the file is ESM/CJS (using the extension).
4748

4849
```ts
50+
interface RuntimeOptions {
51+
/**
52+
* @default true
53+
*/
54+
module?: boolean;
55+
/**
56+
* @default false
57+
*/
58+
removeHTMLComments?: boolean;
59+
/**
60+
* @default false
61+
*/
62+
isMinified?: boolean;
63+
initialize?: (sourceFile: SourceFile) => void;
64+
finalize?: (sourceFile: SourceFile) => void;
65+
}
66+
4967
interface Report {
5068
dependencies: Map<string, Dependency>;
5169
warnings: Warning[];
@@ -65,9 +83,7 @@ type ReportOnFile = {
6583
}
6684
```
6785
68-
## Examples
69-
70-
### `initialize`/`finalize` Hooks
86+
### Hooks
7187
7288
The `analyse` method allows for the integration of two hooks: `initialize` and `finalize`.
7389
These hooks are triggered before and after the analysis process, respectively.
@@ -90,3 +106,72 @@ scanner.analyse("const foo = 'bar';", {
90106
}
91107
});
92108
```
109+
110+
## Custom Probes
111+
112+
You can also create custom probes to detect specific pattern in the code you are analyzing.
113+
114+
A probe is a pair of two functions (`validateNode` and `main`) that will be called on each node of the AST. It will return a warning if the pattern is detected.
115+
116+
Below a basic probe that detect a string assignation to `danger`:
117+
118+
```ts
119+
export const customProbes = [
120+
{
121+
name: "customProbeUnsafeDanger",
122+
validateNode: (node, sourceFile) => [
123+
node.type === "VariableDeclaration" && node.declarations[0].init.value === "danger"
124+
],
125+
main: (node, options) => {
126+
const { sourceFile, data: calleeName } = options;
127+
if (node.declarations[0].init.value === "danger") {
128+
sourceFile.addWarning("unsafe-danger", calleeName, node.loc);
129+
130+
return ProbeSignals.Skip;
131+
}
132+
133+
return null;
134+
}
135+
}
136+
];
137+
```
138+
139+
You can pass an array of probes to the `AstAnalyser` constructor.
140+
141+
| Name | Type | Description | Default Value |
142+
|---|---|---|---|
143+
| **customParser** | `SourceParser \| undefined` | An optional custom parser to be used for parsing the source code. | `JsSourceParser` |
144+
| **customProbes** | `Probe[] \| undefined` | An array of custom probes to be used during AST analysis. | `[]` |
145+
| **skipDefaultProbes** | `boolean \| undefined` | If **true**, default probes will be skipped and only custom probes will be used. | `false` |
146+
147+
Here using the example probe upper:
148+
149+
```ts
150+
import { AstAnalyser } from "@nodesecure/js-x-ray";
151+
152+
// add your customProbes here (see example above)
153+
154+
const scanner = new AstAnalyser({
155+
customProbes,
156+
skipDefaultProbes: true
157+
});
158+
159+
const result = scanner.analyse("const danger = 'danger';");
160+
161+
console.log(result);
162+
```
163+
164+
Result:
165+
166+
```sh
167+
✗ node example.js
168+
{
169+
idsLengthAvg: 0,
170+
stringScore: 0,
171+
warnings: [ { kind: 'unsafe-danger', location: [Array], source: 'JS-X-Ray' } ],
172+
dependencies: Map(0) {},
173+
isOneLineRequire: false
174+
}
175+
```
176+
177+
Congrats, you have created your first custom probe! 🎉

docs/shady-link.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Shady link
22
| Code | Severity | i18n | Experimental |
33
| --- | --- | --- | :-: |
4-
| shady-link | `Warning` | `sast_warnings.shady_link` | ✔️ |
4+
| shady-link | `Warning` | `sast_warnings.shady_link` | |
55

66
## Introduction
77

@@ -36,4 +36,4 @@ const IPv6URL = "http://2444:1130:80:2aa8:c313:150d:b8cf:c321/script";
3636

3737
> [!IMPORTANT]\
3838
> Credit goes to the [guarddog](https://github.dev/DataDog/guarddog) team.\
39-
> Credit goes to the [ietf.org](https://www.ietf.org/rfc/rfc3986.txt).
39+
> Credit goes to the [ietf.org](https://www.ietf.org/rfc/rfc3986.txt).

docs/suspicious-file.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
| Code | Severity | i18n | Experimental |
44
| --- | --- | --- | :-: |
5-
| suspicious-file | `Critical` | `sast_warnings.suspicious_file` | ✔️ |
5+
| suspicious-file | `Critical` | `sast_warnings.suspicious_file` | |
66

77
## Introduction
88

docs/weak-crypto.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
| Code | Severity | i18n | Experimental |
44
| --- | --- | --- | :-: |
5-
| weak-crypto | `Information` | `sast_warnings.weak_crypto` | ✔️ |
5+
| weak-crypto | `Information` | `sast_warnings.weak_crypto` | |
66

77
## Introduction
88

index.d.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ import {
77

88
SourceParser,
99
JsSourceParser,
10-
runASTAnalysis,
11-
runASTAnalysisOnFile,
1210
Report,
1311
ReportOnFile,
1412
RuntimeFileOptions,
@@ -34,8 +32,6 @@ export {
3432
EntryFilesAnalyserOptions,
3533
JsSourceParser,
3634
SourceParser,
37-
runASTAnalysis,
38-
runASTAnalysisOnFile,
3935
Report,
4036
ReportOnFile,
4137
RuntimeFileOptions,

0 commit comments

Comments
 (0)