sentinel-scanner 2.4.1 → 2.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/.cspell.json +19 -51
- package/.github/ISSUE_TEMPLATE/config.yml +1 -1
- package/.github/PULL_REQUEST_TEMPLATE.md +2 -2
- package/.github/workflows/stale.yaml +20 -0
- package/.github/workflows/webapp-scanner.yml +31 -19
- package/.github/workflows/welcome.yaml +9 -55
- package/.husky/pre-commit +35 -0
- package/.vscode/extensions.json +7 -0
- package/.vscode/launch.json +20 -0
- package/.vscode/settings.json +32 -0
- package/.vscode/tasks.json +24 -0
- package/CHANGELOG.md +7 -3
- package/CODE_OF_CONDUCT.md +4 -1
- package/CONTRIBUTING.md +2 -2
- package/README.md +5 -0
- package/api-extractor.json +30 -30
- package/biome.json +6 -32
- package/build/index.d.ts +0 -147
- package/build/index.js +111 -2633
- package/package.json +69 -102
- package/scripts/build.ts +68 -78
- package/scripts/test.ts +55 -0
- package/src/__tests__/spider.test.ts +44 -0
- package/src/commands/spider.ts +61 -126
- package/src/index.ts +23 -26
- package/src/spider/index.ts +345 -0
- package/src/spider/types/index.ts +21 -0
- package/src/spider/types/schema.ts +54 -0
- package/src/utils/index.ts +199 -3
- package/tsconfig.json +19 -18
- package/.github/assets/header.png +0 -0
- package/.github/dependabot.yml +0 -11
- package/.github/workflows/pr.yaml +0 -64
- package/.nsprc +0 -3
- package/build/bin.js +0 -2679
- package/build/xhr-sync-worker.js +0 -59
- package/docs/CNAME +0 -1
- package/docs/disclaimer.md +0 -68
- package/docs/headers/details.md +0 -114
- package/docs/headers/index.md +0 -73
- package/docs/index.md +0 -82
- package/docs/ports/index.md +0 -86
- package/docs/scoring.md +0 -91
- package/docs/spider/index.md +0 -61
- package/docs/sql-injection/details.md +0 -109
- package/docs/sql-injection/index.md +0 -73
- package/docs/xss/details.md +0 -92
- package/docs/xss/index.md +0 -73
- package/scripts/extras/document-shim.js +0 -4
- package/src/bin.ts +0 -29
- package/src/commands/header.ts +0 -150
- package/src/commands/ports.ts +0 -175
- package/src/commands/sqli.ts +0 -150
- package/src/commands/xss.ts +0 -149
- package/src/modules/headers/headers.ts +0 -161
- package/src/modules/headers/index.ts +0 -179
- package/src/modules/ports/index.ts +0 -311
- package/src/modules/spider/index.ts +0 -178
- package/src/modules/sqli/index.ts +0 -486
- package/src/modules/sqli/payloads.json +0 -156
- package/src/modules/xss/index.ts +0 -401
- package/src/modules/xss/payloads.json +0 -2692
- package/src/utils/types.ts +0 -7
package/src/utils/index.ts
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
import fs from "node:fs";
|
2
|
+
import path from "node:path";
|
1
3
|
import {
|
2
4
|
EnvironmentalMetric,
|
3
5
|
type Metric,
|
@@ -14,7 +16,45 @@ import {
|
|
14
16
|
} from "cvssify";
|
15
17
|
import winston from "winston";
|
16
18
|
|
17
|
-
|
19
|
+
/**
|
20
|
+
* The regular expression used to extract the CVSS score from a CVSS vector.
|
21
|
+
*/
|
22
|
+
const scoreRegex = /(\/[A-Z]+:[A-Z]+)?$/;
|
23
|
+
|
24
|
+
/**
|
25
|
+
* Generates CVSS scores and associated metadata from a CVSS vector.
|
26
|
+
*
|
27
|
+
* @param cvssVector - The CVSS vector string to be parsed and analyzed.
|
28
|
+
* @returns An object containing various CVSS scores, human-readable metric details, and severity level.
|
29
|
+
*
|
30
|
+
* @throws {Error} If the CVSS vector is invalid or does not contain the required version or metrics map.
|
31
|
+
*
|
32
|
+
* @example
|
33
|
+
* ```ts
|
34
|
+
* const cvssVector = "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H";
|
35
|
+
* const cvssScores = generateCvss(cvssVector);
|
36
|
+
* console.log(cvssScores);
|
37
|
+
* // Output: {
|
38
|
+
* // baseScore: 9.8,
|
39
|
+
* // impactScore: 6.4,
|
40
|
+
* // exploitabilityScore: 3.9,
|
41
|
+
* // temporalScore: null,
|
42
|
+
* // environmentalScore: null,
|
43
|
+
* // metricsMap: [
|
44
|
+
* // { metric: "Attack Vector", value: "Network" },
|
45
|
+
* // { metric: "Attack Complexity", value: "Low" },
|
46
|
+
* // { metric: "Privileges Required", value: "None" },
|
47
|
+
* // { metric: "User Interaction", value: "Required" },
|
48
|
+
* // { metric: "Scope", value: "Changed" },
|
49
|
+
* // { metric: "Confidentiality Impact", value: "High" },
|
50
|
+
* // { metric: "Integrity Impact", value: "High" },
|
51
|
+
* // { metric: "Availability Impact", value: "High" }
|
52
|
+
* // ],
|
53
|
+
* // severity: "Critical"
|
54
|
+
* // }
|
55
|
+
* ```
|
56
|
+
*/
|
57
|
+
export const generateCvss = (cvssVector: string) => {
|
18
58
|
// Validate the input CVSS vector
|
19
59
|
const validationResult: ValidationResult = validate(cvssVector);
|
20
60
|
|
@@ -58,7 +98,7 @@ export const generateCVSS = (cvssVector: string) => {
|
|
58
98
|
);
|
59
99
|
|
60
100
|
temporalScore = calculateBaseScore(
|
61
|
-
cvssVector.replace(
|
101
|
+
cvssVector.replace(scoreRegex, "") + temporalMetrics,
|
62
102
|
);
|
63
103
|
}
|
64
104
|
|
@@ -76,7 +116,7 @@ export const generateCVSS = (cvssVector: string) => {
|
|
76
116
|
);
|
77
117
|
|
78
118
|
environmentalScore = calculateBaseScore(
|
79
|
-
cvssVector.replace(
|
119
|
+
cvssVector.replace(scoreRegex, "") + environmentalMetrics,
|
80
120
|
);
|
81
121
|
}
|
82
122
|
|
@@ -94,6 +134,21 @@ export const generateCVSS = (cvssVector: string) => {
|
|
94
134
|
};
|
95
135
|
};
|
96
136
|
|
137
|
+
/**
|
138
|
+
* Determines the level of vulnerability based on the base score.
|
139
|
+
*
|
140
|
+
* @param score - The CVSS base score.
|
141
|
+
* @returns The severity level as one of the following: "Critical", "High", "Medium", "Low", or "Info".
|
142
|
+
*
|
143
|
+
* @example
|
144
|
+
* ```ts
|
145
|
+
* console.log(getLevelOfVulnerability(9.0)); // Output: Critical
|
146
|
+
* console.log(getLevelOfVulnerability(7.0)); // Output: High
|
147
|
+
* console.log(getLevelOfVulnerability(4.0)); // Output: Medium
|
148
|
+
* console.log(getLevelOfVulnerability(2.0)); // Output: Low
|
149
|
+
* console.log(getLevelOfVulnerability(0.0)); // Output: Info
|
150
|
+
* ```
|
151
|
+
*/
|
97
152
|
const getLevelOfVulnerability = (
|
98
153
|
score: number,
|
99
154
|
): "Critical" | "High" | "Medium" | "Low" | "Info" => {
|
@@ -116,6 +171,18 @@ const getLevelOfVulnerability = (
|
|
116
171
|
return "Info";
|
117
172
|
};
|
118
173
|
|
174
|
+
/**
|
175
|
+
* Creates a logger instance with the specified label for logging messages.
|
176
|
+
*
|
177
|
+
* @param label - The label to associate with the logger.
|
178
|
+
* @returns A configured Winston logger instance.
|
179
|
+
*
|
180
|
+
* @example
|
181
|
+
* ```ts
|
182
|
+
* const logger = createLogger("MyApp");
|
183
|
+
* logger.info("Hello, world!");
|
184
|
+
* ```
|
185
|
+
*/
|
119
186
|
export const createLogger = (label: string) =>
|
120
187
|
winston.createLogger({
|
121
188
|
level: "silly",
|
@@ -144,3 +211,132 @@ export const createLogger = (label: string) =>
|
|
144
211
|
),
|
145
212
|
transports: [new winston.transports.Console()],
|
146
213
|
});
|
214
|
+
|
215
|
+
/**
|
216
|
+
* Determines if a value is an object.
|
217
|
+
*
|
218
|
+
* @param value - The value to check.
|
219
|
+
* @returns `true` if the value is an object (excluding arrays), otherwise `false`.
|
220
|
+
*
|
221
|
+
* @example
|
222
|
+
* ```ts
|
223
|
+
* console.log(isObject({})); // Output: true
|
224
|
+
* console.log(isObject([])); // Output: false
|
225
|
+
* console.log(isObject(null)); // Output: false
|
226
|
+
* ```
|
227
|
+
*/
|
228
|
+
export const isObject = (value: unknown): value is Record<string, unknown> => {
|
229
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
230
|
+
};
|
231
|
+
|
232
|
+
/**
|
233
|
+
* Safely stringifies a value into a JSON string.
|
234
|
+
* Handles circular references by replacing them with `[Circular]`.
|
235
|
+
*
|
236
|
+
* @param value - The value to stringify.
|
237
|
+
* @returns A JSON string representation of the value.
|
238
|
+
*
|
239
|
+
* @example
|
240
|
+
* ```ts
|
241
|
+
* const obj = { a: 1, b: { c: 2 } };
|
242
|
+
* console.log(safeStringify(obj));
|
243
|
+
* // Output: {"a":1,"b":{"c":2}}
|
244
|
+
* ```
|
245
|
+
*/
|
246
|
+
export const safeStringify = (value: unknown): string => {
|
247
|
+
const seen = new Array<unknown>();
|
248
|
+
|
249
|
+
return JSON.stringify(value, (_, value) => {
|
250
|
+
if (isObject(value)) {
|
251
|
+
if (seen.includes(value)) {
|
252
|
+
return "[Circular]";
|
253
|
+
}
|
254
|
+
|
255
|
+
seen.push(value);
|
256
|
+
}
|
257
|
+
|
258
|
+
return value;
|
259
|
+
});
|
260
|
+
};
|
261
|
+
|
262
|
+
/**
|
263
|
+
*
|
264
|
+
* @param fn - The function to execute with retries.
|
265
|
+
* @param args - The arguments to pass to the function as an array.
|
266
|
+
* @param maxRetries - The maximum number of retries to attempt.
|
267
|
+
* @param numRetry - The current number of retries attempted.
|
268
|
+
* @returns The result of the function after successful execution
|
269
|
+
* or an error if the maximum number of retries is exceeded.
|
270
|
+
*
|
271
|
+
* @template Result - The return type of the function.
|
272
|
+
* @template Args - The argument types of the function.
|
273
|
+
*
|
274
|
+
* @example
|
275
|
+
* ```ts
|
276
|
+
* const fetchPage = async (url: string): Promise<string> => {
|
277
|
+
* const response = await fetch(url);
|
278
|
+
* return response.text();
|
279
|
+
* };
|
280
|
+
*
|
281
|
+
* const url = "https://example.com";
|
282
|
+
*
|
283
|
+
* withRetries(fetchPage, [url], 3).then((content) => {
|
284
|
+
* console.log(content);
|
285
|
+
* }).catch((error) => {
|
286
|
+
* console.error(error);
|
287
|
+
* });
|
288
|
+
* ```
|
289
|
+
*/
|
290
|
+
// biome-ignore lint/complexity/noUselessTypeConstraint: This is a return type for a function.
|
291
|
+
export function withRetries<Result extends unknown, Args extends unknown[]>(
|
292
|
+
fn: (...args: Args) => Promise<Result>,
|
293
|
+
args: Args,
|
294
|
+
maxRetries = 3,
|
295
|
+
numRetry = 0,
|
296
|
+
): Promise<Result> {
|
297
|
+
return fn(...args).catch((error) => {
|
298
|
+
if (numRetry >= maxRetries) {
|
299
|
+
throw error;
|
300
|
+
}
|
301
|
+
|
302
|
+
return withRetries(fn, args, maxRetries, numRetry + 1);
|
303
|
+
});
|
304
|
+
}
|
305
|
+
|
306
|
+
/**
|
307
|
+
* Chunks an array into smaller arrays of a specified size.
|
308
|
+
*
|
309
|
+
* @param arr - The array to chunk.
|
310
|
+
* @param size - The size of each chunk.
|
311
|
+
* @returns An array of chunks containing the original array elements.
|
312
|
+
*
|
313
|
+
* @template T - The type of the array elements.
|
314
|
+
*
|
315
|
+
* @example
|
316
|
+
* ```ts
|
317
|
+
* const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
318
|
+
* const chunkedArray = chunkArray(arr, 3);
|
319
|
+
* console.log(chunkedArray);
|
320
|
+
* // Output: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
|
321
|
+
* ```
|
322
|
+
*/
|
323
|
+
export function chunkArray<T>(arr: T[], size: number): T[][] {
|
324
|
+
const chunkedArray: T[][] = [];
|
325
|
+
|
326
|
+
for (let i = 0; i < arr.length; i += size) {
|
327
|
+
chunkedArray.push(arr.slice(i, i + size));
|
328
|
+
}
|
329
|
+
|
330
|
+
return chunkedArray;
|
331
|
+
}
|
332
|
+
|
333
|
+
export const getPackageData = () => {
|
334
|
+
const packageJsonPath = path.join(import.meta.dirname, "..", "package.json");
|
335
|
+
|
336
|
+
const packageJson = fs.readFileSync(packageJsonPath, "utf-8");
|
337
|
+
|
338
|
+
return {
|
339
|
+
name: JSON.parse(packageJson).name,
|
340
|
+
version: JSON.parse(packageJson).version,
|
341
|
+
};
|
342
|
+
};
|
package/tsconfig.json
CHANGED
@@ -1,22 +1,23 @@
|
|
1
1
|
{
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
2
|
+
"include": ["./src/**/*.ts"],
|
3
|
+
"compilerOptions": {
|
4
|
+
"lib": ["es2023"],
|
5
|
+
"module": "nodenext",
|
6
|
+
"target": "es2022",
|
7
|
+
"moduleResolution": "nodenext",
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
"rootDir": "./src",
|
10
|
+
"outDir": "build",
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
12
|
+
"strict": true,
|
13
|
+
"noUncheckedIndexedAccess": true,
|
14
|
+
"sourceMap": true,
|
15
|
+
"esModuleInterop": true,
|
16
|
+
"skipLibCheck": true,
|
17
|
+
"forceConsistentCasingInFileNames": true,
|
18
|
+
"declaration": true,
|
19
|
+
"resolveJsonModule": true,
|
20
|
+
"emitDeclarationOnly": true,
|
21
|
+
"allowImportingTsExtensions": true
|
22
|
+
}
|
22
23
|
}
|
Binary file
|
package/.github/dependabot.yml
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
version: 2
|
2
|
-
updates:
|
3
|
-
- package-ecosystem: "npm" # Use the appropriate ecosystem (e.g., npm, yarn, pip)
|
4
|
-
directory: "/" # Root directory of your project or specify subdirectory
|
5
|
-
schedule:
|
6
|
-
interval: "daily"
|
7
|
-
commit-message:
|
8
|
-
prefix: "fix"
|
9
|
-
prefix-development: "chore"
|
10
|
-
include: "scope"
|
11
|
-
open-pull-requests-limit: 10
|
@@ -1,64 +0,0 @@
|
|
1
|
-
name: "check PR"
|
2
|
-
|
3
|
-
on:
|
4
|
-
pull_request:
|
5
|
-
branches:
|
6
|
-
- main
|
7
|
-
- alpha
|
8
|
-
|
9
|
-
permissions: "write-all"
|
10
|
-
|
11
|
-
jobs:
|
12
|
-
dependencies:
|
13
|
-
name: 📦 Dependencies
|
14
|
-
runs-on: macos-latest
|
15
|
-
steps:
|
16
|
-
- uses: actions/checkout@v4
|
17
|
-
- uses: actions/setup-node@v4
|
18
|
-
with:
|
19
|
-
node-version-file: package.json
|
20
|
-
cache: "npm"
|
21
|
-
- run: npm ci && npm install -g better-npm-audit
|
22
|
-
|
23
|
-
lint:
|
24
|
-
name: 🔬 Lint & Format
|
25
|
-
runs-on: macos-latest
|
26
|
-
needs: [dependencies]
|
27
|
-
steps:
|
28
|
-
- uses: actions/checkout@v4
|
29
|
-
- uses: actions/setup-node@v4
|
30
|
-
with:
|
31
|
-
node-version-file: package.json
|
32
|
-
cache: "npm"
|
33
|
-
- run: npm ci
|
34
|
-
- name: 🔬 Lint & Format
|
35
|
-
run: npm run lint:check
|
36
|
-
|
37
|
-
audit:
|
38
|
-
name: 🛡️ Audit
|
39
|
-
runs-on: macos-latest
|
40
|
-
needs: [dependencies]
|
41
|
-
steps:
|
42
|
-
- uses: actions/checkout@v4
|
43
|
-
- uses: actions/setup-node@v4
|
44
|
-
with:
|
45
|
-
node-version-file: package.json
|
46
|
-
cache: "npm"
|
47
|
-
- name: Install better-npm-audit
|
48
|
-
run: npm install -g better-npm-audit
|
49
|
-
- name: 🛡️ Audit
|
50
|
-
run: npm run audit
|
51
|
-
|
52
|
-
spell:
|
53
|
-
name: 🈸 Spellcheck
|
54
|
-
runs-on: macos-latest
|
55
|
-
needs: [dependencies]
|
56
|
-
steps:
|
57
|
-
- uses: actions/checkout@v4
|
58
|
-
- uses: actions/setup-node@v4
|
59
|
-
with:
|
60
|
-
node-version-file: package.json
|
61
|
-
cache: "npm"
|
62
|
-
- run: npm ci
|
63
|
-
- name: 🈸 Spellcheck
|
64
|
-
run: npm run spell:check
|
package/.nsprc
DELETED