@heossi/qnsi 0.5.6 → 0.6.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 (71) hide show
  1. package/dist/cli/commands/crypto-scan.d.ts +13 -0
  2. package/dist/cli/commands/crypto-scan.d.ts.map +1 -0
  3. package/dist/cli/commands/crypto-scan.js +247 -0
  4. package/dist/cli/commands/crypto-scan.js.map +1 -0
  5. package/dist/cli/index.js +2 -0
  6. package/dist/cli/index.js.map +1 -1
  7. package/dist/code-scan/canonical.d.ts +25 -0
  8. package/dist/code-scan/canonical.d.ts.map +1 -0
  9. package/dist/code-scan/canonical.js +80 -0
  10. package/dist/code-scan/canonical.js.map +1 -0
  11. package/dist/code-scan/index.d.ts +6 -0
  12. package/dist/code-scan/index.d.ts.map +1 -0
  13. package/dist/code-scan/index.js +5 -0
  14. package/dist/code-scan/index.js.map +1 -0
  15. package/dist/code-scan/rules/artifacts.d.ts +7 -0
  16. package/dist/code-scan/rules/artifacts.d.ts.map +1 -0
  17. package/dist/code-scan/rules/artifacts.js +83 -0
  18. package/dist/code-scan/rules/artifacts.js.map +1 -0
  19. package/dist/code-scan/rules/c.d.ts +6 -0
  20. package/dist/code-scan/rules/c.d.ts.map +1 -0
  21. package/dist/code-scan/rules/c.js +77 -0
  22. package/dist/code-scan/rules/c.js.map +1 -0
  23. package/dist/code-scan/rules/csharp.d.ts +6 -0
  24. package/dist/code-scan/rules/csharp.d.ts.map +1 -0
  25. package/dist/code-scan/rules/csharp.js +67 -0
  26. package/dist/code-scan/rules/csharp.js.map +1 -0
  27. package/dist/code-scan/rules/go.d.ts +8 -0
  28. package/dist/code-scan/rules/go.d.ts.map +1 -0
  29. package/dist/code-scan/rules/go.js +93 -0
  30. package/dist/code-scan/rules/go.js.map +1 -0
  31. package/dist/code-scan/rules/index.d.ts +8 -0
  32. package/dist/code-scan/rules/index.d.ts.map +1 -0
  33. package/dist/code-scan/rules/index.js +24 -0
  34. package/dist/code-scan/rules/index.js.map +1 -0
  35. package/dist/code-scan/rules/java.d.ts +8 -0
  36. package/dist/code-scan/rules/java.d.ts.map +1 -0
  37. package/dist/code-scan/rules/java.js +160 -0
  38. package/dist/code-scan/rules/java.js.map +1 -0
  39. package/dist/code-scan/rules/javascript.d.ts +7 -0
  40. package/dist/code-scan/rules/javascript.d.ts.map +1 -0
  41. package/dist/code-scan/rules/javascript.js +179 -0
  42. package/dist/code-scan/rules/javascript.js.map +1 -0
  43. package/dist/code-scan/rules/python.d.ts +6 -0
  44. package/dist/code-scan/rules/python.d.ts.map +1 -0
  45. package/dist/code-scan/rules/python.js +133 -0
  46. package/dist/code-scan/rules/python.js.map +1 -0
  47. package/dist/code-scan/rules/rust.d.ts +8 -0
  48. package/dist/code-scan/rules/rust.d.ts.map +1 -0
  49. package/dist/code-scan/rules/rust.js +86 -0
  50. package/dist/code-scan/rules/rust.js.map +1 -0
  51. package/dist/code-scan/scanner.d.ts +18 -0
  52. package/dist/code-scan/scanner.d.ts.map +1 -0
  53. package/dist/code-scan/scanner.js +254 -0
  54. package/dist/code-scan/scanner.js.map +1 -0
  55. package/dist/code-scan/strip.d.ts +25 -0
  56. package/dist/code-scan/strip.d.ts.map +1 -0
  57. package/dist/code-scan/strip.js +150 -0
  58. package/dist/code-scan/strip.js.map +1 -0
  59. package/dist/code-scan/types.d.ts +76 -0
  60. package/dist/code-scan/types.d.ts.map +1 -0
  61. package/dist/code-scan/types.js +9 -0
  62. package/dist/code-scan/types.js.map +1 -0
  63. package/dist/index.d.ts +1 -1
  64. package/dist/index.d.ts.map +1 -1
  65. package/dist/index.js +1 -1
  66. package/dist/index.js.map +1 -1
  67. package/dist/kms.d.ts +59 -0
  68. package/dist/kms.d.ts.map +1 -1
  69. package/dist/kms.js +41 -0
  70. package/dist/kms.js.map +1 -1
  71. package/package.json +5 -1
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Python rule pack: pyca/cryptography, PyCryptodome, hashlib, PyJWT.
3
+ */
4
+ const LANGS = ["python"];
5
+ export const pythonRules = [
6
+ {
7
+ id: "py-cryptography-rsa-generate",
8
+ languages: LANGS,
9
+ pattern: /rsa\.generate_private_key\s*\(/,
10
+ algorithm: "rsa-unknown",
11
+ category: "asymmetric",
12
+ classification: "classical",
13
+ confidence: "high",
14
+ library: "pyca/cryptography",
15
+ wantsKeySize: true,
16
+ },
17
+ {
18
+ id: "py-cryptography-ec-curve",
19
+ languages: LANGS,
20
+ pattern: /\bec\.(SECP192R1|SECP256R1|SECP256K1|SECP384R1|SECP521R1)\b/,
21
+ algorithm: (match) => {
22
+ const curve = match[1] ?? "";
23
+ if (curve.includes("192"))
24
+ return "ecdsa-p192";
25
+ if (curve.includes("256"))
26
+ return "ecdsa-p256";
27
+ if (curve.includes("384"))
28
+ return "ecdsa-p384";
29
+ return "ecdsa-p521";
30
+ },
31
+ category: "asymmetric",
32
+ classification: "classical",
33
+ confidence: "high",
34
+ library: "pyca/cryptography",
35
+ },
36
+ {
37
+ id: "py-cryptography-pkcs1v15",
38
+ languages: LANGS,
39
+ pattern: /padding\.PKCS1v15\s*\(/,
40
+ algorithm: "rsa-unknown",
41
+ category: "asymmetric",
42
+ classification: "classical",
43
+ confidence: "high",
44
+ library: "pyca/cryptography",
45
+ },
46
+ {
47
+ id: "py-cryptography-ed25519",
48
+ languages: LANGS,
49
+ pattern: /\b(Ed25519PrivateKey|Ed448PrivateKey|X25519PrivateKey|X448PrivateKey)\b/,
50
+ algorithm: (match) => {
51
+ const cls = match[1] ?? "";
52
+ if (cls.startsWith("Ed25519"))
53
+ return "ed25519";
54
+ if (cls.startsWith("Ed448"))
55
+ return "ed448";
56
+ return cls.startsWith("X25519") ? "ecdh-x25519" : "ecdh-x448";
57
+ },
58
+ category: "asymmetric",
59
+ classification: "classical",
60
+ confidence: "high",
61
+ library: "pyca/cryptography",
62
+ },
63
+ {
64
+ id: "py-pycryptodome-rsa",
65
+ languages: LANGS,
66
+ pattern: /\bRSA\.generate\s*\(\s*(\d{3,5})?/,
67
+ algorithm: "rsa-unknown",
68
+ category: "asymmetric",
69
+ classification: "classical",
70
+ confidence: "high",
71
+ library: "PyCryptodome",
72
+ wantsKeySize: true,
73
+ },
74
+ {
75
+ id: "py-pycryptodome-weak-cipher",
76
+ languages: LANGS,
77
+ pattern: /from\s+Crypto(?:dome)?\.Cipher\s+import\s+.*\b(DES3|DES|ARC4|ARC2)\b|\b(DES3|DES|ARC4)\.new\s*\(/,
78
+ algorithm: (match) => {
79
+ const name = (match[1] ?? match[2] ?? "").toUpperCase();
80
+ if (name === "DES3")
81
+ return "3des";
82
+ if (name === "DES")
83
+ return "des";
84
+ return "rc4";
85
+ },
86
+ category: "symmetric",
87
+ classification: "classical",
88
+ confidence: "high",
89
+ library: "PyCryptodome",
90
+ },
91
+ {
92
+ id: "py-hashlib-weak-hash",
93
+ languages: LANGS,
94
+ pattern: /hashlib\.(md5|sha1)\s*\(/,
95
+ algorithm: (match) => (match[1] ?? "").toLowerCase(),
96
+ category: "hash",
97
+ classification: "classical",
98
+ confidence: "high",
99
+ library: "hashlib",
100
+ },
101
+ {
102
+ id: "py-jwt-classical-alg",
103
+ languages: LANGS,
104
+ pattern: /algorithms?\s*=\s*\[?\s*["'](RS256|RS384|RS512|PS256|PS384|PS512|ES256|ES384|ES512|EdDSA)["']/,
105
+ algorithm: (match) => {
106
+ const alg = match[1] ?? "";
107
+ if (alg.startsWith("RS") || alg.startsWith("PS"))
108
+ return "rsa-unknown";
109
+ if (alg === "ES256")
110
+ return "ecdsa-p256";
111
+ if (alg === "ES384")
112
+ return "ecdsa-p384";
113
+ if (alg === "ES512")
114
+ return "ecdsa-p521";
115
+ return "ed25519";
116
+ },
117
+ category: "asymmetric",
118
+ classification: "classical",
119
+ confidence: "high",
120
+ library: "PyJWT",
121
+ },
122
+ {
123
+ id: "py-pqc-liboqs",
124
+ languages: LANGS,
125
+ pattern: /\boqs\.(KeyEncapsulation|Signature)\s*\(\s*["']([A-Za-z0-9_-]+)["']/,
126
+ algorithm: (match) => (match[2] ?? "").toLowerCase().replace(/_/g, "-"),
127
+ category: "asymmetric",
128
+ classification: "pqc",
129
+ confidence: "high",
130
+ library: "liboqs-python",
131
+ },
132
+ ];
133
+ //# sourceMappingURL=python.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"python.js","sourceRoot":"","sources":["../../../src/code-scan/rules/python.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Rust rule pack: rsa/p256/p384/ed25519-dalek/ring/openssl crates.
3
+ * `use` declarations are strong evidence; Cargo.toml dependency lines are
4
+ * matched by the artifacts pack (config language).
5
+ */
6
+ import type { CryptoDetectionRule } from "../types.js";
7
+ export declare const rustRules: readonly CryptoDetectionRule[];
8
+ //# sourceMappingURL=rust.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rust.d.ts","sourceRoot":"","sources":["../../../src/code-scan/rules/rust.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAIvD,eAAO,MAAM,SAAS,EAAE,SAAS,mBAAmB,EAuEnD,CAAC"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Rust rule pack: rsa/p256/p384/ed25519-dalek/ring/openssl crates.
3
+ * `use` declarations are strong evidence; Cargo.toml dependency lines are
4
+ * matched by the artifacts pack (config language).
5
+ */
6
+ const LANGS = ["rust"];
7
+ export const rustRules = [
8
+ {
9
+ id: "rs-use-classical-crates",
10
+ languages: LANGS,
11
+ pattern: /\buse\s+(rsa|p256|p384|k256|ed25519_dalek|x25519_dalek)\b/,
12
+ algorithm: (match) => {
13
+ const crate = match[1] ?? "";
14
+ if (crate === "rsa")
15
+ return "rsa-unknown";
16
+ if (crate === "p256" || crate === "k256")
17
+ return "ecdsa-p256";
18
+ if (crate === "p384")
19
+ return "ecdsa-p384";
20
+ if (crate === "ed25519_dalek")
21
+ return "ed25519";
22
+ return "ecdh-x25519";
23
+ },
24
+ category: "asymmetric",
25
+ classification: "classical",
26
+ confidence: "high",
27
+ library: "rust crates",
28
+ },
29
+ {
30
+ id: "rs-rsa-generate",
31
+ languages: LANGS,
32
+ pattern: /RsaPrivateKey::new\s*\(/,
33
+ algorithm: "rsa-unknown",
34
+ category: "asymmetric",
35
+ classification: "classical",
36
+ confidence: "high",
37
+ library: "rsa crate",
38
+ wantsKeySize: true,
39
+ },
40
+ {
41
+ id: "rs-ring-classical",
42
+ languages: LANGS,
43
+ pattern: /ring::signature::(?:RSA|ECDSA|ED25519)[A-Z0-9_]*/,
44
+ algorithm: (match) => {
45
+ const token = match[0];
46
+ if (token.includes("RSA"))
47
+ return "rsa-unknown";
48
+ if (token.includes("ECDSA"))
49
+ return "ecdsa-unknown";
50
+ return "ed25519";
51
+ },
52
+ category: "asymmetric",
53
+ classification: "classical",
54
+ confidence: "high",
55
+ library: "ring",
56
+ },
57
+ {
58
+ id: "rs-weak-hash-crates",
59
+ languages: LANGS,
60
+ pattern: /\buse\s+(md5|md_5|sha1|sha_1)\b|\b(Md5|Sha1)::(?:new|digest)\b/,
61
+ algorithm: (match) => {
62
+ const token = (match[1] ?? match[2] ?? "").toLowerCase().replace(/_/g, "");
63
+ return token.includes("md5") ? "md5" : "sha1";
64
+ },
65
+ category: "hash",
66
+ classification: "classical",
67
+ confidence: "high",
68
+ library: "rust crates",
69
+ },
70
+ {
71
+ id: "rs-pqc-crates",
72
+ languages: LANGS,
73
+ pattern: /\buse\s+(?:pqcrypto|ml_kem|ml_dsa|fips203|fips204|fips205|oqs)\b/,
74
+ algorithm: (match) => {
75
+ const token = match[0];
76
+ if (token.includes("dsa") || token.includes("204"))
77
+ return "ml-dsa-65";
78
+ return "ml-kem-768";
79
+ },
80
+ category: "asymmetric",
81
+ classification: "pqc",
82
+ confidence: "medium",
83
+ library: "rust pqc crates",
84
+ },
85
+ ];
86
+ //# sourceMappingURL=rust.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rust.js","sourceRoot":"","sources":["../../../src/code-scan/rules/rust.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,MAAM,KAAK,GAAG,CAAC,MAAM,CAAU,CAAC;AAEhC,MAAM,CAAC,MAAM,SAAS,GAAmC;IACxD;QACC,EAAE,EAAE,yBAAyB;QAC7B,SAAS,EAAE,KAAK;QAChB,OAAO,EAAE,2DAA2D;QACpE,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE;YACpB,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC7B,IAAI,KAAK,KAAK,KAAK;gBAAE,OAAO,aAAa,CAAC;YAC1C,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,MAAM;gBAAE,OAAO,YAAY,CAAC;YAC9D,IAAI,KAAK,KAAK,MAAM;gBAAE,OAAO,YAAY,CAAC;YAC1C,IAAI,KAAK,KAAK,eAAe;gBAAE,OAAO,SAAS,CAAC;YAChD,OAAO,aAAa,CAAC;QACtB,CAAC;QACD,QAAQ,EAAE,YAAY;QACtB,cAAc,EAAE,WAAW;QAC3B,UAAU,EAAE,MAAM;QAClB,OAAO,EAAE,aAAa;KACtB;IACD;QACC,EAAE,EAAE,iBAAiB;QACrB,SAAS,EAAE,KAAK;QAChB,OAAO,EAAE,yBAAyB;QAClC,SAAS,EAAE,aAAa;QACxB,QAAQ,EAAE,YAAY;QACtB,cAAc,EAAE,WAAW;QAC3B,UAAU,EAAE,MAAM;QAClB,OAAO,EAAE,WAAW;QACpB,YAAY,EAAE,IAAI;KAClB;IACD;QACC,EAAE,EAAE,mBAAmB;QACvB,SAAS,EAAE,KAAK;QAChB,OAAO,EAAE,kDAAkD;QAC3D,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE;YACpB,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACvB,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,OAAO,aAAa,CAAC;YAChD,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAAE,OAAO,eAAe,CAAC;YACpD,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,QAAQ,EAAE,YAAY;QACtB,cAAc,EAAE,WAAW;QAC3B,UAAU,EAAE,MAAM;QAClB,OAAO,EAAE,MAAM;KACf;IACD;QACC,EAAE,EAAE,qBAAqB;QACzB,SAAS,EAAE,KAAK;QAChB,OAAO,EAAE,gEAAgE;QACzE,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE;YACpB,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC3E,OAAO,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;QAC/C,CAAC;QACD,QAAQ,EAAE,MAAM;QAChB,cAAc,EAAE,WAAW;QAC3B,UAAU,EAAE,MAAM;QAClB,OAAO,EAAE,aAAa;KACtB;IACD;QACC,EAAE,EAAE,eAAe;QACnB,SAAS,EAAE,KAAK;QAChB,OAAO,EAAE,kEAAkE;QAC3E,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE;YACpB,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACvB,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,OAAO,WAAW,CAAC;YACvE,OAAO,YAAY,CAAC;QACrB,CAAC;QACD,QAAQ,EAAE,YAAY;QACtB,cAAc,EAAE,KAAK;QACrB,UAAU,EAAE,QAAQ;QACpB,OAAO,EAAE,iBAAiB;KAC1B;CACD,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * File walker + rule matcher. Parse-only: files are read as text, comments
3
+ * are stripped, rules are matched line-by-line. Nothing is executed and no
4
+ * network is touched — scanning an untrusted repository is safe by
5
+ * construction.
6
+ */
7
+ import type { CodeCryptoFinding, Language, ScanOptions, ScanSummary } from "./types.js";
8
+ export declare function detectLanguage(fileName: string): Language | null;
9
+ export declare function isTestPath(relativePath: string): boolean;
10
+ export declare function hashLine(line: string): string;
11
+ /**
12
+ * Scan a single file's content. Exported for tests, the CLI's single-file
13
+ * mode, and future host integrations (qnsp-agent).
14
+ */
15
+ export declare function scanFileContent(relativePath: string, content: string, language: Language): CodeCryptoFinding[];
16
+ /** Recursively scan a directory tree. */
17
+ export declare function scanDirectory(options: ScanOptions): Promise<ScanSummary>;
18
+ //# sourceMappingURL=scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/code-scan/scanner.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,OAAO,KAAK,EACX,iBAAiB,EAEjB,QAAQ,EACR,WAAW,EACX,WAAW,EACX,MAAM,YAAY,CAAC;AA8EpB,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAUhE;AAED,wBAAgB,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAQxD;AAYD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7C;AA4BD;;;GAGG;AACH,wBAAgB,eAAe,CAC9B,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,GAChB,iBAAiB,EAAE,CAiDrB;AAED,yCAAyC;AACzC,wBAAsB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAyE9E"}
@@ -0,0 +1,254 @@
1
+ /**
2
+ * File walker + rule matcher. Parse-only: files are read as text, comments
3
+ * are stripped, rules are matched line-by-line. Nothing is executed and no
4
+ * network is touched — scanning an untrusted repository is safe by
5
+ * construction.
6
+ */
7
+ import { createHash } from "node:crypto";
8
+ import { readdir, readFile, stat } from "node:fs/promises";
9
+ import { join, relative, sep } from "node:path";
10
+ import { canonicalRsa, findKeySizeNear } from "./canonical.js";
11
+ import { ALL_RULES } from "./rules/index.js";
12
+ import { stripComments } from "./strip.js";
13
+ const DEFAULT_MAX_FILE_BYTES = 2 * 1024 * 1024;
14
+ const DEFAULT_MAX_FINDINGS = 50_000;
15
+ const BINARY_SNIFF_BYTES = 8 * 1024;
16
+ /** Directories never worth scanning (build output, VCS, dependencies). */
17
+ const SKIP_DIRS = new Set([
18
+ ".git",
19
+ ".hg",
20
+ ".svn",
21
+ "node_modules",
22
+ "vendor",
23
+ "dist",
24
+ "build",
25
+ "out",
26
+ "target",
27
+ "bin",
28
+ "obj",
29
+ ".next",
30
+ ".turbo",
31
+ "coverage",
32
+ "__pycache__",
33
+ ".venv",
34
+ "venv",
35
+ ".terraform",
36
+ ]);
37
+ const SKIP_FILES = new Set([
38
+ "pnpm-lock.yaml",
39
+ "package-lock.json",
40
+ "yarn.lock",
41
+ "Cargo.lock",
42
+ "go.sum",
43
+ "poetry.lock",
44
+ "uv.lock",
45
+ ]);
46
+ const EXTENSION_LANGUAGE = {
47
+ ".js": "javascript",
48
+ ".mjs": "javascript",
49
+ ".cjs": "javascript",
50
+ ".jsx": "javascript",
51
+ ".ts": "typescript",
52
+ ".mts": "typescript",
53
+ ".cts": "typescript",
54
+ ".tsx": "typescript",
55
+ ".py": "python",
56
+ ".java": "java",
57
+ ".kt": "kotlin",
58
+ ".kts": "kotlin",
59
+ ".go": "go",
60
+ ".c": "c",
61
+ ".h": "c",
62
+ ".cc": "cpp",
63
+ ".cpp": "cpp",
64
+ ".cxx": "cpp",
65
+ ".hpp": "cpp",
66
+ ".hh": "cpp",
67
+ ".cs": "csharp",
68
+ ".rs": "rust",
69
+ ".yaml": "config",
70
+ ".yml": "config",
71
+ ".toml": "config",
72
+ ".json": "config",
73
+ ".conf": "config",
74
+ ".cfg": "config",
75
+ ".ini": "config",
76
+ ".properties": "config",
77
+ ".pem": "config",
78
+ ".crt": "config",
79
+ ".cer": "config",
80
+ ".pub": "config",
81
+ };
82
+ const TEST_PATH_SEGMENTS = ["test", "tests", "__tests__", "spec", "specs", "testdata", "fixtures"];
83
+ const TEST_FILE_PATTERN = /(\.test\.|\.spec\.|_test\.(?:go|py|rb)$|Tests?\.(?:java|kt|cs)$)/;
84
+ export function detectLanguage(fileName) {
85
+ const lower = fileName.toLowerCase();
86
+ if (lower.endsWith(".min.js") || lower.endsWith(".min.mjs")) {
87
+ return null; // minified bundles: line-based findings are meaningless
88
+ }
89
+ const dot = lower.lastIndexOf(".");
90
+ if (dot === -1) {
91
+ return fileName === "Dockerfile" ? "config" : null;
92
+ }
93
+ return EXTENSION_LANGUAGE[lower.slice(dot)] ?? null;
94
+ }
95
+ export function isTestPath(relativePath) {
96
+ const posixPath = relativePath.split(sep).join("/");
97
+ const segments = posixPath.toLowerCase().split("/");
98
+ if (segments.some((segment) => TEST_PATH_SEGMENTS.includes(segment))) {
99
+ return true;
100
+ }
101
+ const base = segments[segments.length - 1] ?? "";
102
+ return TEST_FILE_PATTERN.test(base);
103
+ }
104
+ function looksBinary(buffer) {
105
+ const limit = Math.min(buffer.length, BINARY_SNIFF_BYTES);
106
+ for (let i = 0; i < limit; i++) {
107
+ if (buffer[i] === 0) {
108
+ return true;
109
+ }
110
+ }
111
+ return false;
112
+ }
113
+ export function hashLine(line) {
114
+ const normalized = line.trim().replace(/\s+/g, " ");
115
+ return createHash("sha256").update(normalized).digest("hex");
116
+ }
117
+ function resolveAlgorithm(rule, match, line, strippedLines, lineIndex) {
118
+ const base = typeof rule.algorithm === "function" ? rule.algorithm(match, line) : rule.algorithm;
119
+ if (base === null || base.length === 0) {
120
+ return null;
121
+ }
122
+ if (!rule.wantsKeySize) {
123
+ return { algorithm: base, keySize: null };
124
+ }
125
+ const keySize = findKeySizeNear(strippedLines, lineIndex);
126
+ if (base.startsWith("rsa")) {
127
+ return { algorithm: canonicalRsa(keySize), keySize };
128
+ }
129
+ if (base.startsWith("dsa") && keySize === 1024) {
130
+ return { algorithm: "dsa-1024", keySize };
131
+ }
132
+ return { algorithm: base, keySize };
133
+ }
134
+ /**
135
+ * Scan a single file's content. Exported for tests, the CLI's single-file
136
+ * mode, and future host integrations (qnsp-agent).
137
+ */
138
+ export function scanFileContent(relativePath, content, language) {
139
+ const rules = ALL_RULES.filter((rule) => rule.languages.includes(language));
140
+ if (rules.length === 0) {
141
+ return [];
142
+ }
143
+ const strippedLines = stripComments(content, language);
144
+ const findings = [];
145
+ const testContext = isTestPath(relativePath);
146
+ const seen = new Set();
147
+ for (let i = 0; i < strippedLines.length; i++) {
148
+ const line = strippedLines[i] ?? "";
149
+ if (line.length === 0) {
150
+ continue;
151
+ }
152
+ for (const rule of rules) {
153
+ // Fresh exec per line: rule patterns are not /g, so lastIndex is 0.
154
+ const match = rule.pattern.exec(line);
155
+ if (!match) {
156
+ continue;
157
+ }
158
+ const resolved = resolveAlgorithm(rule, match, line, strippedLines, i);
159
+ if (!resolved) {
160
+ continue;
161
+ }
162
+ const dedupKey = `${rule.id}:${i}`;
163
+ if (seen.has(dedupKey)) {
164
+ continue;
165
+ }
166
+ seen.add(dedupKey);
167
+ findings.push({
168
+ path: relativePath.split(sep).join("/"),
169
+ line: i + 1,
170
+ language,
171
+ ruleId: rule.id,
172
+ library: rule.library,
173
+ algorithm: resolved.algorithm,
174
+ category: rule.category,
175
+ classification: rule.classification,
176
+ confidence: rule.confidence,
177
+ lineHash: hashLine(line),
178
+ ...(resolved.keySize !== null ? { keySize: resolved.keySize } : {}),
179
+ ...(testContext ? { testContext: true } : {}),
180
+ });
181
+ }
182
+ }
183
+ return findings;
184
+ }
185
+ /** Recursively scan a directory tree. */
186
+ export async function scanDirectory(options) {
187
+ const maxFileBytes = options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES;
188
+ const maxFindings = options.maxFindings ?? DEFAULT_MAX_FINDINGS;
189
+ const skipDirs = new Set([...SKIP_DIRS, ...(options.excludeDirs ?? [])]);
190
+ const findings = [];
191
+ let filesScanned = 0;
192
+ let filesSkipped = 0;
193
+ let truncated = false;
194
+ async function walk(dir) {
195
+ if (truncated) {
196
+ return;
197
+ }
198
+ const entries = await readdir(dir, { withFileTypes: true });
199
+ // Deterministic order — identical trees produce identical summaries.
200
+ entries.sort((a, b) => a.name.localeCompare(b.name));
201
+ for (const entry of entries) {
202
+ if (truncated) {
203
+ return;
204
+ }
205
+ const fullPath = join(dir, entry.name);
206
+ if (entry.isSymbolicLink()) {
207
+ filesSkipped++;
208
+ continue; // never follow symlinks out of the scan root
209
+ }
210
+ if (entry.isDirectory()) {
211
+ if (skipDirs.has(entry.name)) {
212
+ continue;
213
+ }
214
+ await walk(fullPath);
215
+ continue;
216
+ }
217
+ if (!entry.isFile()) {
218
+ continue;
219
+ }
220
+ if (SKIP_FILES.has(entry.name)) {
221
+ filesSkipped++;
222
+ continue;
223
+ }
224
+ const language = detectLanguage(entry.name);
225
+ if (!language) {
226
+ filesSkipped++;
227
+ continue;
228
+ }
229
+ const info = await stat(fullPath);
230
+ if (info.size > maxFileBytes) {
231
+ filesSkipped++;
232
+ continue;
233
+ }
234
+ const buffer = await readFile(fullPath);
235
+ if (looksBinary(buffer)) {
236
+ filesSkipped++;
237
+ continue;
238
+ }
239
+ filesScanned++;
240
+ const relPath = relative(options.rootDir, fullPath);
241
+ const fileFindings = scanFileContent(relPath, buffer.toString("utf8"), language);
242
+ for (const finding of fileFindings) {
243
+ if (findings.length >= maxFindings) {
244
+ truncated = true;
245
+ break;
246
+ }
247
+ findings.push(finding);
248
+ }
249
+ }
250
+ }
251
+ await walk(options.rootDir);
252
+ return { filesScanned, filesSkipped, findings, truncated };
253
+ }
254
+ //# sourceMappingURL=scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../src/code-scan/scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Comment stripping — string-aware, per language family.
3
+ *
4
+ * Comments are removed BEFORE rule matching so a migration note that merely
5
+ * mentions a crypto API can never become a finding (the
6
+ * guard-that-reads-its-own-comment failure class, see
7
+ * .claude/rules/toolchain-single-source.md). String literals are KEPT:
8
+ * crypto APIs take algorithm names as string arguments
9
+ * (`Cipher.getInstance("RSA")`), so rules anchor on API context instead.
10
+ */
11
+ import type { Language } from "./types.js";
12
+ interface StripState {
13
+ /** Inside a C-style block comment. */
14
+ inBlockComment: boolean;
15
+ /** Python triple-quote delimiter currently open, or null. */
16
+ inTripleQuote: string | null;
17
+ }
18
+ export declare function createStripState(): StripState;
19
+ /**
20
+ * Strip comments from a full file, returning one entry per original line so
21
+ * finding line numbers stay 1:1 with the source.
22
+ */
23
+ export declare function stripComments(content: string, language: Language): string[];
24
+ export {};
25
+ //# sourceMappingURL=strip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strip.d.ts","sourceRoot":"","sources":["../../src/code-scan/strip.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAkB3C,UAAU,UAAU;IACnB,sCAAsC;IACtC,cAAc,EAAE,OAAO,CAAC;IACxB,6DAA6D;IAC7D,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,wBAAgB,gBAAgB,IAAI,UAAU,CAE7C;AA0HD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,MAAM,EAAE,CAiB3E"}