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
package/package.json CHANGED
@@ -1,104 +1,71 @@
1
1
  {
2
- "name": "sentinel-scanner",
3
- "description": "[WIP] An open-source web app vulnerability scanner developed by Rebackk.",
4
- "version": "2.4.1",
5
- "exports": "./build/index.js",
6
- "types": "./build/index.d.ts",
7
- "bin": "./build/bin.js",
8
- "type": "module",
9
- "main": "./build/index.js",
10
- "license": "Apache-2.0",
11
- "engines": {
12
- "node": "^22.11.0",
13
- "npm": "^10.5.0"
14
- },
15
- "volta": {
16
- "node": "^22.11.0",
17
- "npm": "^10.5.0"
18
- },
19
- "keywords": [
20
- "nodejs",
21
- "npm-package",
22
- "owasp",
23
- "sentinel",
24
- "cybersecurity",
25
- "penetration-testing",
26
- "web-security",
27
- "vulnerability-detection",
28
- "vulnerability-scanner",
29
- "api-security",
30
- "threat-detection",
31
- "security-tool",
32
- "webapp-scanner",
33
- "ai-powered",
34
- "automated-scanning",
35
- "spider-scanner",
36
- "scanner",
37
- "typescript"
38
- ],
39
- "publishConfig": {
40
- "access": "public"
41
- },
42
- "scripts": {
43
- "build": "node --disable-warning=ExperimentalWarning --experimental-strip-types ./scripts/build.ts",
44
- "clean": "rimraf build coverage",
45
- "type:check": "tsc --noEmit",
46
- "lint": "biome check . --write --unsafe",
47
- "lint:check": "biome ci .",
48
- "test": "npm run build && ava src/__tests__/*.ts",
49
- "test:watch": "npm run build && ava src/__tests__/*.ts --watch",
50
- "test:coverage": "npm run build && ava src/__tests__/*.ts --coverage",
51
- "spell:check": "cspell \"{DISCLAIMER.md,README.md,CODE_OF_CONDUCT.md,CONTRIBUTING.md,.github/*.md,src/**/*.ts}\"",
52
- "cz": "cz",
53
- "semantic-release": "semantic-release",
54
- "prepare": "husky",
55
- "audit": "better-npm-audit audit",
56
- "audit:fix": "better-npm-audit --fix"
57
- },
58
- "devDependencies": {
59
- "@biomejs/biome": "^1.9.4",
60
- "@microsoft/api-extractor": "^7.47.11",
61
- "@ryansonshine/commitizen": "^4.2.8",
62
- "@ryansonshine/cz-conventional-changelog": "^3.3.4",
63
- "@semantic-release/changelog": "^6.0.3",
64
- "@semantic-release/commit-analyzer": "^13.0.0",
65
- "@semantic-release/github": "^10.3.5",
66
- "@semantic-release/npm": "^12.0.1",
67
- "@semantic-release/release-notes-generator": "^14.0.1",
68
- "@types/axios": "^0.9.36",
69
- "@types/isomorphic-fetch": "^0.0.39",
70
- "@types/jsdom": "^21.1.7",
71
- "@types/node": "^22.9.0",
72
- "@types/prompts": "^2.4.9",
73
- "@types/puppeteer": "^5.4.7",
74
- "@types/user-agents": "^1.0.4",
75
- "@types/yargs": "^17.0.33",
76
- "ae-cvss-calculator": "^1.0.2",
77
- "ava": "^6.2.0",
78
- "better-npm-audit": "^3.11.0",
79
- "c8": "^10.1.2",
80
- "cspell": "^8.15.7",
81
- "cz-conventional-changelog": "^3.3.0",
82
- "esbuild": "^0.24.0",
83
- "husky": "^9.1.6",
84
- "rimraf": "^6.0.1",
85
- "semantic-release": "^24.2.0",
86
- "threads": "^1.7.0",
87
- "tiny-worker": "^2.3.0",
88
- "typescript": "^5.4.2",
89
- "winston": "^3.17.0"
90
- },
91
- "config": {
92
- "commitizen": {
93
- "path": "./node_modules/cz-conventional-changelog"
94
- }
95
- },
96
- "dependencies": {
97
- "cross-spawn": "^7.0.5",
98
- "cvssify": "^1.0.0",
99
- "jsdom": "^25.0.1",
100
- "puppeteer": "^23.8.0",
101
- "user-agents": "^1.1.359",
102
- "yargs": "^17.7.2"
103
- }
2
+ "name": "sentinel-scanner",
3
+ "version": "2.5.0",
4
+ "description": "[WIP] An open-source web app vulnerability scanner developed by Rebackk.",
5
+ "type": "module",
6
+ "bin": "./build/index.js",
7
+ "types": "./build/index.d.ts",
8
+ "license": "Apache-2.0",
9
+ "homepage": "https://rebackkhq.github.io/webapp-scanner/",
10
+ "engines": {
11
+ "node": "^22.8.0",
12
+ "npm": "^10.9.1"
13
+ },
14
+ "volta": {
15
+ "node": "22.8.0",
16
+ "npm": "^10.9.1"
17
+ },
18
+ "publishConfig": {
19
+ "access": "public"
20
+ },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "https://github.com/RebackkHQ/webapp-scanner.git"
24
+ },
25
+ "scripts": {
26
+ "build": "node --disable-warning=ExperimentalWarning --experimental-strip-types ./scripts/build.ts",
27
+ "clean": "rimraf build coverage",
28
+ "type:check": "tsc --noEmit",
29
+ "lint": "biome check . --write --unsafe",
30
+ "lint:check": "biome ci .",
31
+ "test": "node --disable-warning=ExperimentalWarning --experimental-strip-types ./scripts/test.ts test",
32
+ "test:watch": "node --disable-warning=ExperimentalWarning --experimental-strip-types ./scripts/test.ts test:watch",
33
+ "test:coverage": "node --disable-warning=ExperimentalWarning --experimental-strip-types ./scripts/test.ts test:coverage",
34
+ "spell:check": "cspell \"{README.md,CODE_OF_CONDUCT.md,CONTRIBUTING.md,.github/*.md,src/**/*.ts}\"",
35
+ "cz": "cz",
36
+ "semantic-release": "semantic-release",
37
+ "prepare": "husky"
38
+ },
39
+ "devDependencies": {
40
+ "@biomejs/biome": "^1.9.4",
41
+ "@microsoft/api-extractor": "^7.47.11",
42
+ "@ryansonshine/commitizen": "^4.2.8",
43
+ "@ryansonshine/cz-conventional-changelog": "^3.3.4",
44
+ "@semantic-release/changelog": "^6.0.3",
45
+ "@semantic-release/commit-analyzer": "^13.0.0",
46
+ "@semantic-release/github": "^10.3.5",
47
+ "@semantic-release/npm": "^12.0.1",
48
+ "@semantic-release/release-notes-generator": "^14.0.1",
49
+ "@types/node": "^22.9.0",
50
+ "@types/prompts": "^2.4.9",
51
+ "@types/yargs": "17.0.33",
52
+ "c8": "^10.1.2",
53
+ "cspell": "^8.16.0",
54
+ "cvssify": "1.0.1",
55
+ "cz-conventional-changelog": "^3.3.0",
56
+ "esbuild": "^0.23.1",
57
+ "husky": "9.1.7",
58
+ "node-html-parser": "6.1.13",
59
+ "rimraf": "^6.0.1",
60
+ "semantic-release": "^24.2.0",
61
+ "typescript": "^5.6.3",
62
+ "winston": "3.17.0",
63
+ "yargs": "17.7.2",
64
+ "zod": "3.23.8"
65
+ },
66
+ "config": {
67
+ "commitizen": {
68
+ "path": "./node_modules/cz-conventional-changelog"
69
+ }
70
+ }
104
71
  }
package/scripts/build.ts CHANGED
@@ -11,100 +11,90 @@ const srcPath = path.join(process.cwd(), "src");
11
11
  const buildPath = path.join(process.cwd(), "build");
12
12
 
13
13
  async function clear(): Promise<void> {
14
- const time = Date.now();
14
+ const time = Date.now();
15
15
 
16
- await fs.rm(buildPath, { recursive: true, force: true });
16
+ await fs.rm(buildPath, { recursive: true, force: true });
17
17
 
18
- // biome-ignore lint/suspicious/noConsoleLog: script file
19
- console.log(`🚀 cleared in ${Date.now() - time}ms`);
18
+ // biome-ignore lint/suspicious/noConsoleLog: script file
19
+ // biome-ignore lint/suspicious/noConsole : script file
20
+ console.log(`🚀 cleared in ${Date.now() - time}ms`);
20
21
  }
21
22
 
22
23
  async function buildDts(): Promise<void> {
23
- const time = Date.now();
24
-
25
- const { stderr } = await execFile("tsc", [
26
- "--emitDeclarationOnly",
27
- "--project",
28
- "tsconfig.build.json",
29
- ]);
30
-
31
- if (stderr) {
32
- console.error(stderr);
33
- }
34
-
35
- // biome-ignore lint/suspicious/noConsoleLog: script file
36
- console.log(`🚀 built definitions files in ${Date.now() - time} ms`);
24
+ const time = Date.now();
25
+
26
+ const { stderr } = await execFile("tsc", [
27
+ "--emitDeclarationOnly",
28
+ "--project",
29
+ "tsconfig.build.json",
30
+ ]);
31
+
32
+ if (stderr) {
33
+ // biome-ignore lint/suspicious/noConsoleLog: script file
34
+ // biome-ignore lint/suspicious/noConsole : script file
35
+ console.error(stderr);
36
+ }
37
+
38
+ // biome-ignore lint/suspicious/noConsoleLog: script file
39
+ // biome-ignore lint/suspicious/noConsole : script file
40
+ console.log(`🚀 built definitions files in ${Date.now() - time} ms`);
37
41
  }
38
42
 
39
43
  async function extractDts(): Promise<void> {
40
- const time = Date.now();
44
+ const time = Date.now();
41
45
 
42
- const { stderr } = await execFile("api-extractor", ["run"]);
46
+ const { stderr } = await execFile("api-extractor", ["run"]);
43
47
 
44
- if (stderr) {
45
- console.error(stderr);
46
- }
48
+ if (stderr) {
49
+ // biome-ignore lint/suspicious/noConsoleLog: script file
50
+ // biome-ignore lint/suspicious/noConsole : script file
51
+ console.error(stderr);
52
+ }
47
53
 
48
- await rimraf("./build/*", { glob: true });
49
- await fs.rename("trimmed.d.ts", "build/index.d.ts");
54
+ await rimraf("./build/*", { glob: true });
55
+ await fs.rename("trimmed.d.ts", "build/index.d.ts");
50
56
 
51
- // biome-ignore lint/suspicious/noConsoleLog: script file
52
- console.log(`🚀 extracted definitions files in ${Date.now() - time} ms`);
57
+ // biome-ignore lint/suspicious/noConsoleLog: script file
58
+ // biome-ignore lint/suspicious/noConsole : script file
59
+ console.log(`🚀 extracted definitions files in ${Date.now() - time} ms`);
53
60
  }
54
61
 
55
62
  async function build(): Promise<void> {
56
- const time = Date.now();
57
-
58
- const banner =
59
- "const require = (await import('node:module')).createRequire(import.meta.url);";
60
-
61
- await esbuild({
62
- banner: { js: banner },
63
- platform: "node",
64
- format: "esm",
65
- nodePaths: [srcPath],
66
- sourcemap: false,
67
- external: [],
68
- bundle: true,
69
- entryPoints: [path.join(srcPath, "index.ts"), path.join(srcPath, "bin.ts")],
70
- outdir: buildPath,
71
- footer: {
72
- js: "// https://github.com/RebackkHQ/webapp-scanner",
73
- },
74
- inject: [path.resolve("./scripts/extras/document-shim.js")],
75
- minify: true,
76
- });
77
-
78
- // biome-ignore lint/suspicious/noConsoleLog: script file
79
- console.log(`🚀 bundled in ${Date.now() - time}ms`);
80
- }
81
-
82
- async function copyXhrSync() {
83
- const currentPath = path.join(
84
- process.cwd(),
85
- "node_modules/jsdom/lib/jsdom/living/xhr/xhr-sync-worker.js"
86
- );
87
- const targetPath = path.join(buildPath, "xhr-sync-worker.js");
88
-
89
- try {
90
- // Check if the source file exists
91
- await fs.access(currentPath);
92
-
93
- // Copy the file to the build path
94
- await fs.copyFile(currentPath, targetPath);
95
-
96
- console.log(
97
- "📄 xhr-sync-worker.js copied successfully to the build folder."
98
- );
99
- } catch (error) {
100
- console.error("❌ Failed to copy xhr-sync-worker.js:", error);
101
- }
63
+ const time = Date.now();
64
+
65
+ await esbuild({
66
+ platform: "node",
67
+ target: "node21",
68
+ format: "esm",
69
+ nodePaths: [srcPath],
70
+ sourcemap: false,
71
+ external: [],
72
+ bundle: true,
73
+ entryPoints: [path.join(srcPath, "index.ts")],
74
+ outdir: buildPath,
75
+ minify: true,
76
+ banner: {
77
+ js: "const require = (await import('node:module')).createRequire(import.meta.url);const __filename = (await import('node:url')).fileURLToPath(import.meta.url);const __dirname = (await import('node:path')).dirname(__filename);",
78
+ },
79
+ footer: {
80
+ js: `
81
+ /**
82
+ * Github Repository: https://github.com/RebackkHQ/webapp-scanner
83
+ * Author: Rebackk Team
84
+ * License: Apache-2.0
85
+ */
86
+ `,
87
+ },
88
+ });
89
+
90
+ // biome-ignore lint/suspicious/noConsoleLog: script file
91
+ // biome-ignore lint/suspicious/noConsole : script file
92
+ console.log(`🚀 bundled in ${Date.now() - time}ms`);
102
93
  }
103
94
 
104
95
  if (process.argv[1] === import.meta.filename) {
105
- await clear();
106
- await buildDts();
107
- await extractDts();
108
- await build();
109
- await copyXhrSync();
96
+ await clear();
97
+ await buildDts();
98
+ await extractDts();
99
+ await build();
110
100
  }
@@ -0,0 +1,55 @@
1
+ import { spawn } from "node:child_process";
2
+
3
+ async function runTests(
4
+ nodeOptions: string[] = [],
5
+ program = "node",
6
+ programOptions: string[] = [],
7
+ env: Record<string, string> = {},
8
+ ): Promise<void> {
9
+ const time = Date.now();
10
+
11
+ return new Promise((resolve, reject) => {
12
+ const nodeProcess = spawn(
13
+ program,
14
+ [
15
+ ...programOptions,
16
+ "--disable-warning=ExperimentalWarning",
17
+ "--experimental-strip-types",
18
+ "--test",
19
+ ...nodeOptions,
20
+ "src/**/*.test.ts",
21
+ ],
22
+ { stdio: "inherit", env: { ...process.env, ...env } },
23
+ );
24
+
25
+ nodeProcess.on("close", (code) => {
26
+ if (code === 0) {
27
+ resolve();
28
+ }
29
+
30
+ reject(`🚨 tests failed with code ${code} in ${Date.now() - time}ms`);
31
+ });
32
+ });
33
+ }
34
+
35
+ if (process.argv[1] === import.meta.filename) {
36
+ if (process.argv[2] === "test") {
37
+ await runTests();
38
+ }
39
+
40
+ if (process.argv[2] === "test:watch") {
41
+ await runTests(["--watch"]);
42
+ }
43
+
44
+ if (process.argv[2] === "test:coverage") {
45
+ await runTests(
46
+ ["--experimental-test-coverage"],
47
+ "c8",
48
+ ["-r", "html", "node"],
49
+ {
50
+ // biome-ignore lint/style/useNamingConvention: node options
51
+ NODE_V8_COVERAGE: "./coverage",
52
+ },
53
+ );
54
+ }
55
+ }
@@ -0,0 +1,44 @@
1
+ import { equal } from "node:assert/strict";
2
+ import { describe, it } from "node:test";
3
+ import { Spider } from "../spider/index.ts";
4
+ import type { SpiderConstructorOptions } from "../spider/types/index.ts";
5
+
6
+ describe("Spider", async () => {
7
+ it("Should Throw Error", () => {
8
+ try {
9
+ // @ts-ignore - Testing Purposes
10
+ new Spider();
11
+ } catch (error) {
12
+ equal(error instanceof Error, true);
13
+ }
14
+ });
15
+
16
+ it("Should Return An Array", async () => {
17
+ try {
18
+ /**
19
+ * Options for Spider constructor.
20
+ */
21
+ const opts: SpiderConstructorOptions = {
22
+ seed: "https://www.example.com",
23
+ maxDepth: 1,
24
+ maxRetries: 1,
25
+ concurrency: 1,
26
+ ignoreExternalLinks: true,
27
+ timeout: 1000,
28
+ };
29
+ const spider = new Spider(opts);
30
+ const { seed, urls } = await spider.scan();
31
+
32
+ /**
33
+ * Asserting the seed is equal to the seed URL.
34
+ * Asserting the URLs is an array.
35
+ * @param seed - Seed URL.
36
+ * @param urls - Array of URLs.
37
+ */
38
+ equal(seed, opts.seed);
39
+ equal(Array.isArray(urls), true);
40
+ } catch (_) {
41
+ equal(Array.isArray(_), true);
42
+ }
43
+ });
44
+ });