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.
Files changed (63) hide show
  1. package/.cspell.json +19 -51
  2. package/.github/ISSUE_TEMPLATE/config.yml +1 -1
  3. package/.github/PULL_REQUEST_TEMPLATE.md +2 -2
  4. package/.github/workflows/stale.yaml +20 -0
  5. package/.github/workflows/webapp-scanner.yml +31 -19
  6. package/.github/workflows/welcome.yaml +9 -55
  7. package/.husky/pre-commit +35 -0
  8. package/.vscode/extensions.json +7 -0
  9. package/.vscode/launch.json +20 -0
  10. package/.vscode/settings.json +32 -0
  11. package/.vscode/tasks.json +24 -0
  12. package/CHANGELOG.md +7 -3
  13. package/CODE_OF_CONDUCT.md +4 -1
  14. package/CONTRIBUTING.md +2 -2
  15. package/README.md +5 -0
  16. package/api-extractor.json +30 -30
  17. package/biome.json +6 -32
  18. package/build/index.d.ts +0 -147
  19. package/build/index.js +111 -2633
  20. package/package.json +69 -102
  21. package/scripts/build.ts +68 -78
  22. package/scripts/test.ts +55 -0
  23. package/src/__tests__/spider.test.ts +44 -0
  24. package/src/commands/spider.ts +61 -126
  25. package/src/index.ts +23 -26
  26. package/src/spider/index.ts +345 -0
  27. package/src/spider/types/index.ts +21 -0
  28. package/src/spider/types/schema.ts +54 -0
  29. package/src/utils/index.ts +199 -3
  30. package/tsconfig.json +19 -18
  31. package/.github/assets/header.png +0 -0
  32. package/.github/dependabot.yml +0 -11
  33. package/.github/workflows/pr.yaml +0 -64
  34. package/.nsprc +0 -3
  35. package/build/bin.js +0 -2679
  36. package/build/xhr-sync-worker.js +0 -59
  37. package/docs/CNAME +0 -1
  38. package/docs/disclaimer.md +0 -68
  39. package/docs/headers/details.md +0 -114
  40. package/docs/headers/index.md +0 -73
  41. package/docs/index.md +0 -82
  42. package/docs/ports/index.md +0 -86
  43. package/docs/scoring.md +0 -91
  44. package/docs/spider/index.md +0 -61
  45. package/docs/sql-injection/details.md +0 -109
  46. package/docs/sql-injection/index.md +0 -73
  47. package/docs/xss/details.md +0 -92
  48. package/docs/xss/index.md +0 -73
  49. package/scripts/extras/document-shim.js +0 -4
  50. package/src/bin.ts +0 -29
  51. package/src/commands/header.ts +0 -150
  52. package/src/commands/ports.ts +0 -175
  53. package/src/commands/sqli.ts +0 -150
  54. package/src/commands/xss.ts +0 -149
  55. package/src/modules/headers/headers.ts +0 -161
  56. package/src/modules/headers/index.ts +0 -179
  57. package/src/modules/ports/index.ts +0 -311
  58. package/src/modules/spider/index.ts +0 -178
  59. package/src/modules/sqli/index.ts +0 -486
  60. package/src/modules/sqli/payloads.json +0 -156
  61. package/src/modules/xss/index.ts +0 -401
  62. package/src/modules/xss/payloads.json +0 -2692
  63. package/src/utils/types.ts +0 -7
@@ -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
- export const generateCVSS = (cvssVector: string) => {
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(/(\/[A-Z]+:[A-Z]+)?$/, "") + temporalMetrics,
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(/(\/[A-Z]+:[A-Z]+)?$/, "") + environmentalMetrics,
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
- "include": ["./src/**/*.ts"],
3
- "compilerOptions": {
4
- "lib": ["es2023"],
5
- "module": "nodenext",
6
- "target": "es2022",
7
- "moduleResolution": "nodenext",
2
+ "include": ["./src/**/*.ts"],
3
+ "compilerOptions": {
4
+ "lib": ["es2023"],
5
+ "module": "nodenext",
6
+ "target": "es2022",
7
+ "moduleResolution": "nodenext",
8
8
 
9
- "rootDir": "./src",
10
- "outDir": "build",
9
+ "rootDir": "./src",
10
+ "outDir": "build",
11
11
 
12
- "strict": true,
13
- "noUncheckedIndexedAccess": true,
14
- "sourceMap": true,
15
- "esModuleInterop": true,
16
- "skipLibCheck": true,
17
- "forceConsistentCasingInFileNames": true,
18
- "declaration": true,
19
- "declarationMap": true,
20
- "resolveJsonModule": true
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
@@ -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
@@ -1,3 +0,0 @@
1
- {
2
- "GHSA-3xgq-45jj-v275": "Already opened an Issue for this. It is an issue with npm https://github.com/npm/cli/issues/7916"
3
- }