itworksbut 0.1.1

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 (53) hide show
  1. package/README.md +241 -0
  2. package/bin/itworksbut.js +63 -0
  3. package/itworksbut.config.json +5 -0
  4. package/package.json +46 -0
  5. package/src/checks/auth/idor-risk.js +45 -0
  6. package/src/checks/auth/missing-auth-on-routes.js +55 -0
  7. package/src/checks/ci/no-build-step.js +23 -0
  8. package/src/checks/ci/no-ci-config.js +20 -0
  9. package/src/checks/ci/no-test-step.js +23 -0
  10. package/src/checks/ci/npm-install-instead-of-npm-ci.js +29 -0
  11. package/src/checks/database/no-migrations.js +33 -0
  12. package/src/checks/database/raw-sql-interpolation.js +41 -0
  13. package/src/checks/dependencies/audit-script-missing.js +23 -0
  14. package/src/checks/dependencies/install-scripts-risk.js +18 -0
  15. package/src/checks/dependencies/lockfile-missing.js +21 -0
  16. package/src/checks/dependencies/multiple-lockfiles.js +21 -0
  17. package/src/checks/electron/context-isolation-disabled.js +51 -0
  18. package/src/checks/electron/node-integration-enabled.js +26 -0
  19. package/src/checks/env/env-example-missing.js +28 -0
  20. package/src/checks/env/env-file-tracked.js +20 -0
  21. package/src/checks/env/frontend-secret-exposure.js +44 -0
  22. package/src/checks/env/possible-secret-in-code.js +72 -0
  23. package/src/checks/git/gitignore-incomplete.js +47 -0
  24. package/src/checks/git/gitignore-missing.js +16 -0
  25. package/src/checks/git/ignored-files-tracked.js +38 -0
  26. package/src/checks/helpers.js +122 -0
  27. package/src/checks/index.js +63 -0
  28. package/src/checks/node/cors-wildcard.js +35 -0
  29. package/src/checks/node/express-json-limit-missing.js +30 -0
  30. package/src/checks/node/helmet-missing.js +22 -0
  31. package/src/checks/node/rate-limit-missing.js +30 -0
  32. package/src/checks/package/scripts-missing.js +30 -0
  33. package/src/checks/tauri/dangerous-allowlist-or-capabilities.js +142 -0
  34. package/src/checks/web/client-side-auth-only.js +40 -0
  35. package/src/checks/web/dangerous-inner-html.js +33 -0
  36. package/src/checks/web/missing-output-sanitization.js +34 -0
  37. package/src/cli/output.js +29 -0
  38. package/src/cli/parseArgs.js +75 -0
  39. package/src/cli/terminal.js +112 -0
  40. package/src/core/config.js +51 -0
  41. package/src/core/context.js +87 -0
  42. package/src/core/fileWalker.js +44 -0
  43. package/src/core/findings.js +39 -0
  44. package/src/core/git.js +92 -0
  45. package/src/core/scanner.js +56 -0
  46. package/src/reporters/consoleReporter.js +107 -0
  47. package/src/reporters/consoleStyle.js +155 -0
  48. package/src/reporters/jsonReporter.js +17 -0
  49. package/src/reporters/sarifReporter.js +82 -0
  50. package/src/utils/fs.js +57 -0
  51. package/src/utils/mask.js +14 -0
  52. package/src/utils/packageJson.js +31 -0
  53. package/src/utils/path.js +71 -0
@@ -0,0 +1,31 @@
1
+ import path from "node:path";
2
+ import { readJsonSafe } from "./fs.js";
3
+
4
+ export async function readPackageJson(rootPath) {
5
+ return await readJsonSafe(path.join(rootPath, "package.json"));
6
+ }
7
+
8
+ export function getAllDependencies(packageJson = {}) {
9
+ return {
10
+ ...(packageJson.dependencies || {}),
11
+ ...(packageJson.devDependencies || {}),
12
+ ...(packageJson.peerDependencies || {}),
13
+ ...(packageJson.optionalDependencies || {})
14
+ };
15
+ }
16
+
17
+ export function hasDependency(packageJson, name) {
18
+ return Object.hasOwn(getAllDependencies(packageJson), name);
19
+ }
20
+
21
+ export function hasDevDependency(packageJson, name) {
22
+ return Object.hasOwn(packageJson?.devDependencies || {}, name);
23
+ }
24
+
25
+ export function detectPackageManager(packageJson, files) {
26
+ if (packageJson?.packageManager) return packageJson.packageManager.split("@")[0];
27
+ if (files.includes("pnpm-lock.yaml")) return "pnpm";
28
+ if (files.includes("yarn.lock")) return "yarn";
29
+ if (files.includes("package-lock.json")) return "npm";
30
+ return "npm";
31
+ }
@@ -0,0 +1,71 @@
1
+ import path from "node:path";
2
+
3
+ export function toPosixPath(value) {
4
+ return value.split(path.sep).join("/");
5
+ }
6
+
7
+ export function normalizeRelativePath(value) {
8
+ return toPosixPath(value).replace(/^\.\//, "").replace(/^\/+/, "");
9
+ }
10
+
11
+ export function relativePath(rootPath, absolutePath) {
12
+ return normalizeRelativePath(path.relative(rootPath, absolutePath));
13
+ }
14
+
15
+ export function basename(value) {
16
+ const normalized = normalizeRelativePath(value);
17
+ const parts = normalized.split("/");
18
+ return parts[parts.length - 1] || normalized;
19
+ }
20
+
21
+ export function hasGlobMagic(pattern) {
22
+ return /[*?[\]{}]/.test(pattern);
23
+ }
24
+
25
+ export function matchesGlob(filePath, pattern) {
26
+ const normalizedPath = normalizeRelativePath(filePath);
27
+ const normalizedPattern = normalizeRelativePath(pattern).replace(/^\//, "");
28
+
29
+ if (!normalizedPattern) return false;
30
+
31
+ if (normalizedPattern.endsWith("/**")) {
32
+ const base = normalizedPattern.slice(0, -3).replace(/\/$/, "");
33
+ return normalizedPath === base || normalizedPath.startsWith(`${base}/`);
34
+ }
35
+
36
+ if (normalizedPattern.endsWith("/")) {
37
+ const base = normalizedPattern.slice(0, -1);
38
+ return normalizedPath === base || normalizedPath.startsWith(`${base}/`);
39
+ }
40
+
41
+ const target = normalizedPattern.includes("/") ? normalizedPath : basename(normalizedPath);
42
+ return globToRegExp(normalizedPattern.includes("/") ? normalizedPattern : normalizedPattern).test(target);
43
+ }
44
+
45
+ export function matchesAnyGlob(filePath, patterns = []) {
46
+ return patterns.some((pattern) => matchesGlob(filePath, pattern));
47
+ }
48
+
49
+ function globToRegExp(pattern) {
50
+ let source = "";
51
+ for (let index = 0; index < pattern.length; index += 1) {
52
+ const char = pattern[index];
53
+ const next = pattern[index + 1];
54
+
55
+ if (char === "*" && next === "*") {
56
+ source += ".*";
57
+ index += 1;
58
+ } else if (char === "*") {
59
+ source += "[^/]*";
60
+ } else if (char === "?") {
61
+ source += "[^/]";
62
+ } else {
63
+ source += escapeRegExp(char);
64
+ }
65
+ }
66
+ return new RegExp(`^${source}$`);
67
+ }
68
+
69
+ function escapeRegExp(value) {
70
+ return value.replace(/[|\\{}()[\]^$+?.]/g, "\\$&");
71
+ }