@nikhil_telkar/codeshield 0.0.0-stage → 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 (103) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +239 -2
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +237 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/engine/fileWalker.d.ts +15 -0
  8. package/dist/engine/fileWalker.d.ts.map +1 -0
  9. package/dist/engine/fileWalker.js +170 -0
  10. package/dist/engine/fileWalker.js.map +1 -0
  11. package/dist/engine/index.d.ts +4 -0
  12. package/dist/engine/index.d.ts.map +1 -0
  13. package/dist/engine/index.js +4 -0
  14. package/dist/engine/index.js.map +1 -0
  15. package/dist/engine/projectDetector.d.ts +10 -0
  16. package/dist/engine/projectDetector.d.ts.map +1 -0
  17. package/dist/engine/projectDetector.js +44 -0
  18. package/dist/engine/projectDetector.js.map +1 -0
  19. package/dist/engine/runner.d.ts +8 -0
  20. package/dist/engine/runner.d.ts.map +1 -0
  21. package/dist/engine/runner.js +87 -0
  22. package/dist/engine/runner.js.map +1 -0
  23. package/dist/fix/fixer.d.ts +17 -0
  24. package/dist/fix/fixer.d.ts.map +1 -0
  25. package/dist/fix/fixer.js +190 -0
  26. package/dist/fix/fixer.js.map +1 -0
  27. package/dist/fix/history.d.ts +23 -0
  28. package/dist/fix/history.d.ts.map +1 -0
  29. package/dist/fix/history.js +107 -0
  30. package/dist/fix/history.js.map +1 -0
  31. package/dist/fix/index.d.ts +3 -0
  32. package/dist/fix/index.d.ts.map +1 -0
  33. package/dist/fix/index.js +3 -0
  34. package/dist/fix/index.js.map +1 -0
  35. package/dist/index.d.ts +8 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +8 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/report/colors.d.ts +21 -0
  40. package/dist/report/colors.d.ts.map +1 -0
  41. package/dist/report/colors.js +70 -0
  42. package/dist/report/colors.js.map +1 -0
  43. package/dist/report/index.d.ts +15 -0
  44. package/dist/report/index.d.ts.map +1 -0
  45. package/dist/report/index.js +39 -0
  46. package/dist/report/index.js.map +1 -0
  47. package/dist/report/sarif.d.ts +44 -0
  48. package/dist/report/sarif.d.ts.map +1 -0
  49. package/dist/report/sarif.js +69 -0
  50. package/dist/report/sarif.js.map +1 -0
  51. package/dist/report/score.d.ts +14 -0
  52. package/dist/report/score.d.ts.map +1 -0
  53. package/dist/report/score.js +62 -0
  54. package/dist/report/score.js.map +1 -0
  55. package/dist/report/terminal.d.ts +10 -0
  56. package/dist/report/terminal.d.ts.map +1 -0
  57. package/dist/report/terminal.js +77 -0
  58. package/dist/report/terminal.js.map +1 -0
  59. package/dist/scanners/code.d.ts +22 -0
  60. package/dist/scanners/code.d.ts.map +1 -0
  61. package/dist/scanners/code.js +319 -0
  62. package/dist/scanners/code.js.map +1 -0
  63. package/dist/scanners/dependencies.d.ts +10 -0
  64. package/dist/scanners/dependencies.d.ts.map +1 -0
  65. package/dist/scanners/dependencies.js +240 -0
  66. package/dist/scanners/dependencies.js.map +1 -0
  67. package/dist/scanners/env.d.ts +7 -0
  68. package/dist/scanners/env.d.ts.map +1 -0
  69. package/dist/scanners/env.js +195 -0
  70. package/dist/scanners/env.js.map +1 -0
  71. package/dist/scanners/helper.d.ts +27 -0
  72. package/dist/scanners/helper.d.ts.map +1 -0
  73. package/dist/scanners/helper.js +50 -0
  74. package/dist/scanners/helper.js.map +1 -0
  75. package/dist/scanners/index.d.ts +6 -0
  76. package/dist/scanners/index.d.ts.map +1 -0
  77. package/dist/scanners/index.js +6 -0
  78. package/dist/scanners/index.js.map +1 -0
  79. package/dist/scanners/secrets.d.ts +19 -0
  80. package/dist/scanners/secrets.d.ts.map +1 -0
  81. package/dist/scanners/secrets.js +213 -0
  82. package/dist/scanners/secrets.js.map +1 -0
  83. package/dist/types.d.ts +43 -0
  84. package/dist/types.d.ts.map +1 -0
  85. package/dist/types.js +2 -0
  86. package/dist/types.js.map +1 -0
  87. package/dist/utils/constants.d.ts +9 -0
  88. package/dist/utils/constants.d.ts.map +1 -0
  89. package/dist/utils/constants.js +54 -0
  90. package/dist/utils/constants.js.map +1 -0
  91. package/dist/utils/levenshtein.d.ts +2 -0
  92. package/dist/utils/levenshtein.d.ts.map +1 -0
  93. package/dist/utils/levenshtein.js +35 -0
  94. package/dist/utils/levenshtein.js.map +1 -0
  95. package/dist/utils/registry.d.ts +18 -0
  96. package/dist/utils/registry.d.ts.map +1 -0
  97. package/dist/utils/registry.js +106 -0
  98. package/dist/utils/registry.js.map +1 -0
  99. package/dist/utils/sanitize.d.ts +3 -0
  100. package/dist/utils/sanitize.d.ts.map +1 -0
  101. package/dist/utils/sanitize.js +10 -0
  102. package/dist/utils/sanitize.js.map +1 -0
  103. package/package.json +59 -4
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nikhil Telkar
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md CHANGED
@@ -1,3 +1,240 @@
1
- # Temporary Holding Version
1
+ # CodeShield
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ > **A fast, zero-dependency security scanner for AI-generated codebases.**
4
+
5
+ AI coding assistants (Cursor, Copilot, ChatGPT, Claude, v0, Bolt) are extraordinary at writing code quickly, but they frequently introduce dangerous security flaws: hardcoding API keys, hallucinating nonexistent npm packages, writing SQL queries with string concatenation, using `Math.random()` for auth tokens, or forgetting basic security headers like `helmet`.
6
+
7
+ **CodeShield** acts as an instant security guardrail for your development workflow and CI/CD pipelines.
8
+
9
+ ---
10
+
11
+ ## ⚡ 30-Second Quick Start
12
+
13
+ No installation required. Run directly with `npx`:
14
+
15
+ ```bash
16
+ # Scan current project
17
+ npx @nikhil_telkar/codeshield scan .
18
+
19
+ # Automatically apply safe fixes (.gitignore, .env.example)
20
+ npx @nikhil_telkar/codeshield fix .
21
+
22
+ # Check if an npm package is real, safe, or an AI hallucination
23
+ npx @nikhil_telkar/codeshield verify express
24
+ ```
25
+
26
+ Or install globally to use the short `codeshield` command anywhere:
27
+
28
+ ```bash
29
+ npm install -g @nikhil_telkar/codeshield
30
+ codeshield scan .
31
+ ```
32
+
33
+ ---
34
+
35
+ ## 🖥️ Clean, Developer-Friendly Terminal Output
36
+
37
+ ```text
38
+ CodeShield — scanning /Users/dev/my-ai-app
39
+ (offline mode: npm registry checks skipped)
40
+
41
+ ────────────────────────────────────────────────────────────
42
+ Security Score : 54/100 [Grade C] (Needs Attention)
43
+ Files Scanned : 42 files
44
+ Findings : 3 [1 critical, 1 high, 1 medium]
45
+ Duration : 28ms
46
+ ────────────────────────────────────────────────────────────
47
+
48
+ 🎯 Fix These First (Top Priorities):
49
+
50
+ 🔴 CRITICAL [SEC-001] Hardcoded AWS Access Key
51
+ File : src/config/aws.ts:14
52
+ Line : AWS_ACCESS_KEY_ID=AKIA****
53
+ Issue : An AWS Access Key ID was found directly in your code. Anyone with access to this repo can compromise your AWS account.
54
+ Fix : Move credentials to process.env.AWS_ACCESS_KEY_ID or use IAM roles.
55
+ AI Prompt : Refactor src/config/aws.ts to load AWS credentials from process.env.AWS_ACCESS_KEY_ID.
56
+
57
+ 🟠 HIGH [COD-002] SQL Query Built via String Concatenation (SQL Injection)
58
+ File : src/routes/users.ts:28
59
+ Line : const query = "SELECT * FROM users WHERE id = '" + req.query.id + "'";
60
+ Issue : Constructing SQL queries using template literals or string concatenation allows SQL Injection.
61
+ Fix : Use parameterized queries (e.g., db.query("SELECT * FROM users WHERE id = $1", [id])).
62
+ AI Prompt : Refactor the SQL query on line 28 to use parameterized queries with placeholders.
63
+
64
+ 🟡 MEDIUM [COD-011] Missing Security Headers Middleware (Helmet) in Express App
65
+ File : src/server.ts:1
66
+ Issue : Express application initialized without helmet() security headers middleware.
67
+ Fix : Install helmet (`npm install helmet`) and add `app.use(helmet())` near the top of your Express middleware stack.
68
+ AI Prompt : Import `helmet` from "helmet" and add `app.use(helmet())` right after initializing the Express application.
69
+ ```
70
+
71
+ ---
72
+
73
+ ## 🔍 What CodeShield Checks
74
+
75
+ CodeShield evaluates codebases across four core dimensions with **zero runtime dependencies**:
76
+
77
+ ### 1. Secrets Scanner
78
+ - **AWS Credentials:** Hardcoded `AKIA...` access keys (`CWE-798`).
79
+ - **Stripe Keys:** Live API keys (`sk_live_...`) (`CWE-798`).
80
+ - **GitHub Tokens:** Personal access tokens (`ghp_...`, `github_pat_...`) (`CWE-798`).
81
+ - **AI Provider API Keys:** OpenAI (`sk-...`), Anthropic (`sk-ant-...`) keys (`CWE-798`).
82
+ - **Supabase Service Keys:** Hardcoded `service_role` administrative keys (`CWE-798`).
83
+ - **Database Connection Strings:** URLs containing embedded passwords (`postgres://user:pass@host/db`) (`CWE-256`).
84
+ - **Private Key Headers:** Unencrypted PEM blocks (`BEGIN RSA/OPENSSH PRIVATE KEY`) (`CWE-312`).
85
+ - **Hardcoded JWT Secrets:** Literal strings passed to `jwt.sign()` (`CWE-798`).
86
+ - **Generic API Credentials:** High-entropy API key and token assignments (`CWE-798`).
87
+ - **Public Client Leaks:** Private keys placed in `NEXT_PUBLIC_*` or `VITE_*` variables (`CWE-200`).
88
+
89
+ ### 2. Dependency Scanner (AI Hallucination Guard)
90
+ - **Hallucinated Packages (DEP-001):** Verifies all dependencies in `package.json` against the npm registry to catch non-existent packages invented by AI tools (`CWE-829`).
91
+ - **Newly Published Packages (DEP-002):** Warns if dependencies were published $< 30$ days ago (`CWE-829`).
92
+ - **Install Scripts (DEP-003):** Flags packages that run `preinstall`, `install`, or `postinstall` shell scripts (`CWE-829`).
93
+ - **Typosquatting (DEP-004):** Detects packages that are 1 character away from popular libraries (`expres`, `lodahs`) (`CWE-829`).
94
+
95
+ ### 3. Environment & Config Scanner
96
+ - **Unignored `.env` Files:** Credentials exposed to git tracking (`CWE-552`).
97
+ - **Missing `.env.example`:** Repositories with `.env` but no sanitized template for collaborators (`CWE-552`).
98
+ - **Production Source Maps:** `productionBrowserSourceMaps: true` or `sourcemap: true` leaking unminified code in production (`CWE-540`).
99
+
100
+ ### 4. Code Pattern Scanner
101
+ - **Dynamic Code Execution:** `eval()` and `new Function()` (`CWE-95`).
102
+ - **SQL Injection:** String concatenation in `db.query()`, `prisma.$queryRawUnsafe()`, etc. (`CWE-89`).
103
+ - **NoSQL Injection:** Raw `req.body` or `req.query` passed directly into MongoDB/Mongoose queries (`CWE-943`).
104
+ - **Command Injection:** `child_process.exec()` called with variables (`CWE-78`).
105
+ - **Insecure Randomness:** `Math.random()` used for tokens, passwords, or session IDs (`CWE-338`).
106
+ - **Broken Cryptography:** MD5 or SHA-1 used for password hashing (`CWE-328`).
107
+ - **Cross-Site Scripting (XSS):** `dangerouslySetInnerHTML` or `element.innerHTML` with dynamic variables (`CWE-79`).
108
+ - **Permissive CORS:** `cors({ origin: '*' })` (`CWE-942`).
109
+ - **Insecure Cookies:** `res.cookie()` without `httpOnly: true` or `secure: true` (`CWE-1004`, `CWE-614`).
110
+ - **Indefinite JWTs:** `jwt.sign()` calls missing an `expiresIn` option (`CWE-613`).
111
+ - **Missing Helmet:** Express applications without `helmet` security header middleware (`CWE-693`).
112
+ - **Stack Trace Leakage:** Returning `err.stack` in HTTP responses (`CWE-209`).
113
+ - **Client-Side Supabase Admin:** Using Supabase `service_role` keys inside frontend components (`CWE-200`).
114
+
115
+ ---
116
+
117
+ ## 🛠️ CLI Commands & Options
118
+
119
+ ```text
120
+ Usage:
121
+ codeshield scan [path] [options] Scan directory (default: current dir)
122
+ codeshield fix [path] [--yes] Apply safe, reversible fixes automatically
123
+ codeshield verify <package> Check a single npm package
124
+ codeshield --help Show this help
125
+ codeshield --version Show version
126
+ ```
127
+
128
+ ### Scan Options
129
+
130
+ | Option | Description |
131
+ | :--- | :--- |
132
+ | `--detailed` | Show full metadata for all findings (CWE, rule ID, file, line, explanation). |
133
+ | `--json` | Output machine-readable JSON (ideal for CI pipelines). |
134
+ | `--sarif` | Output static analysis results in SARIF v2.1.0 format (for GitHub Security). |
135
+ | `--fail-on <severity>` | Set exit code to 1 if any findings match or exceed `<severity>` (`critical`, `high`, `medium`, `low`, `info`). Default: `info`. |
136
+ | `--severity <severity>` | Filter the report to only include findings at or above `<severity>`. Default: `info`. |
137
+ | `--offline` | Skip all npm registry lookups (runs purely offline in $< 50\text{ms}$). |
138
+
139
+ ### Fix Options
140
+
141
+ | Option | Description |
142
+ | :--- | :--- |
143
+ | `-y, --yes` | Apply safe fixes automatically without an interactive prompt. |
144
+
145
+ *Safety guarantee:* `codeshield fix` only applies reversible, non-destructive changes (`.gitignore` additions, creating `.env.example`). It creates `.codeshield.bak` backups before modifying files and never writes outside the scan root.
146
+
147
+ ### Exit Codes
148
+
149
+ | Code | Meaning |
150
+ | :---: | :--- |
151
+ | `0` | **Passed:** No findings at or above the `--fail-on` threshold. |
152
+ | `1` | **Failed:** One or more findings detected at or above the `--fail-on` threshold. |
153
+ | `2` | **Tool Error:** Invalid CLI arguments, missing files, or unreadable directory. |
154
+
155
+ ---
156
+
157
+ ## 📊 How the Security Score Works
158
+
159
+ CodeShield calculates an objective score between **0 and 100**:
160
+
161
+ $$\text{Score} = \max\left(0, 100 - \sum \text{Capped Deductions}\right)$$
162
+
163
+ ### Severity Weights & Deductions
164
+
165
+ | Severity | Points Deducted per Finding | Maximum Deductions per Rule |
166
+ | :--- | :---: | :---: |
167
+ | **Critical** | -25 | Capped at -35 max per rule |
168
+ | **High** | -15 | Capped at -35 max per rule |
169
+ | **Medium** | -8 | Capped at -35 max per rule |
170
+ | **Low** | -3 | Capped at -35 max per rule |
171
+ | **Info** | 0 | 0 |
172
+
173
+ ### Anti-Noise Rule Capping
174
+ To prevent a single repetitive issue (such as 50 missing cookie flags) from zeroing out the entire score, deductions for any single rule are capped at **35 points**.
175
+
176
+ ### Grade Scale
177
+ - **90–100 [Grade A]** — Excellent: Clean security posture.
178
+ - **75–89 [Grade B]** — Good: Minor low/medium issues.
179
+ - **60–74 [Grade C]** — Needs Attention: High-risk findings present.
180
+ - **40–59 [Grade D]** — Poor: Multiple severe vulnerabilities.
181
+ - **0–39 [Grade F]** — Critical: Immediate attention required.
182
+
183
+ ---
184
+
185
+ ## 🤖 CI / CD Integration
186
+
187
+ Add `.github/workflows/security.yml`:
188
+
189
+ ```yaml
190
+ name: CodeShield Security Scan
191
+
192
+ on:
193
+ push:
194
+ branches: [main]
195
+ pull_request:
196
+ branches: [main]
197
+
198
+ jobs:
199
+ scan:
200
+ runs-on: ubuntu-latest
201
+ steps:
202
+ - name: Checkout repository
203
+ uses: actions/checkout@v4
204
+
205
+ - name: Set up Node.js
206
+ uses: actions/setup-node@v4
207
+ with:
208
+ node-version: '20'
209
+
210
+ # Option A: Fail the build on high/critical findings
211
+ - name: Run CodeShield Scan
212
+ run: npx @nikhil_telkar/codeshield scan . --fail-on high
213
+
214
+ # Option B: Upload SARIF report to GitHub Advanced Security tab
215
+ - name: Generate SARIF report
216
+ if: always()
217
+ run: npx @nikhil_telkar/codeshield scan . --sarif > results.sarif
218
+
219
+ - name: Upload SARIF to GitHub Code Scanning
220
+ uses: github/codeql-action/upload-sarif@v3
221
+ if: always()
222
+ with:
223
+ sarif_file: results.sarif
224
+ ```
225
+
226
+ ---
227
+
228
+ ## 🔒 Privacy & Security Statement
229
+
230
+ - **100% Local Execution:** CodeShield never uploads your source code, filenames, or directory paths to external servers.
231
+ - **Zero Telemetry:** No analytics, no phone-home pings, no cookies, no tracking.
232
+ - **Zero Runtime Dependencies:** Zero third-party packages installed in production. Zero supply chain risk.
233
+ - **Strict Read-Only Scanning:** CodeShield inspects text files using Node built-in file APIs. It **never** dynamically evaluates, requires, or imports your code.
234
+ - **Optional Network Access:** The only network request CodeShield can make is an HTTPS query to `https://registry.npmjs.org/<package>` to verify npm packages during `codeshield verify` or standard scans. Pass `--offline` to run completely disconnected.
235
+
236
+ ---
237
+
238
+ ## 📄 License
239
+
240
+ [MIT](LICENSE) © 2026 Nikhil Telkar
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export declare function runCli(argv?: string[]): Promise<number>;
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AA4LA,wBAAsB,MAAM,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,CAyFpF"}
package/dist/cli.js ADDED
@@ -0,0 +1,237 @@
1
+ #!/usr/bin/env node
2
+ import { readFileSync } from 'node:fs';
3
+ import { dirname, resolve } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { parseArgs } from 'node:util';
6
+ import { secretsScanner } from './scanners/secrets.js';
7
+ import { envScanner } from './scanners/env.js';
8
+ import { codeScanner } from './scanners/code.js';
9
+ import { fetchRegistry } from './utils/registry.js';
10
+ import { isValidNpmName } from './scanners/dependencies.js';
11
+ import { runScanAsync } from './engine/runner.js';
12
+ import { SEVERITY_RANK, SEVERITIES } from './utils/constants.js';
13
+ import { sanitize } from './utils/sanitize.js';
14
+ import { renderReport, calculateScore } from './report/index.js';
15
+ import { runFix } from './fix/fixer.js';
16
+ import { readLastScan, saveLastScan, compareWithLastScan } from './fix/history.js';
17
+ function getVersion() {
18
+ try {
19
+ const currentDir = dirname(fileURLToPath(import.meta.url));
20
+ const pkgPath = resolve(currentDir, '..', 'package.json');
21
+ const content = readFileSync(pkgPath, 'utf8');
22
+ const parsed = JSON.parse(content);
23
+ return parsed.version ?? '0.1.0';
24
+ }
25
+ catch {
26
+ return '0.1.0';
27
+ }
28
+ }
29
+ function isValidSeverity(s) {
30
+ return SEVERITIES.includes(s);
31
+ }
32
+ const HELP_TEXT = `
33
+ CodeShield — Security scanner for AI-generated codebases
34
+
35
+ Usage:
36
+ codeshield scan [path] [options] Scan directory (default: current dir)
37
+ codeshield fix [path] [--yes] Apply safe, reversible fixes automatically
38
+ codeshield verify <package> Check a single npm package
39
+ codeshield --help Show this help
40
+ codeshield --version Show version
41
+
42
+ Scan options:
43
+ --detailed Show all findings with full metadata
44
+ --json Output results as JSON (for CI)
45
+ --sarif Output results as SARIF v2.1.0
46
+ --fail-on <severity> Exit code 1 if findings >= severity
47
+ (critical|high|medium|low|info, default: info)
48
+ --severity <severity> Minimum severity to include in report
49
+ (critical|high|medium|low|info, default: info)
50
+ --offline Skip npm registry network checks
51
+
52
+ Fix options:
53
+ -y, --yes Skip confirmation prompt and apply fixes
54
+
55
+ Examples:
56
+ codeshield scan .
57
+ codeshield scan ./my-project --detailed
58
+ codeshield scan . --fail-on high
59
+ codeshield scan . --json
60
+ codeshield scan . --sarif > results.sarif
61
+ codeshield fix .
62
+ codeshield fix ./my-project --yes
63
+ codeshield verify express
64
+
65
+ Exit codes:
66
+ 0 Passed (no findings at or above fail-on threshold)
67
+ 1 Findings detected at or above fail-on threshold
68
+ 2 Tool error
69
+ `.trim();
70
+ async function runVerify(pkgName) {
71
+ const safeName = sanitize(pkgName);
72
+ if (!isValidNpmName(pkgName)) {
73
+ console.error(`Error: "${safeName}" is not a valid npm package name.`);
74
+ return 2;
75
+ }
76
+ console.log(`Checking "${safeName}" on npm registry…`);
77
+ const result = await fetchRegistry(pkgName, 5_000);
78
+ if (result.status === 'not-found') {
79
+ console.log(`\n🔴 CRITICAL [DEP-001] Package does not exist on npm.`);
80
+ console.log(` "${safeName}" was not found in the npm registry.`);
81
+ console.log(` This may be a hallucinated package name from an AI tool.`);
82
+ console.log(` Verify at https://www.npmjs.com/package/${safeName}`);
83
+ return 1;
84
+ }
85
+ if (result.status === 'error') {
86
+ console.error(`\n⚠️ Could not check "${safeName}": ${sanitize(result.reason)}`);
87
+ console.error(` The package has NOT been verified as safe.`);
88
+ return 2;
89
+ }
90
+ const { data } = result;
91
+ const thirtyDaysMs = 30 * 24 * 60 * 60 * 1000;
92
+ let hasFindings = false;
93
+ console.log(`\n✅ Package "${safeName}" exists on npm.`);
94
+ if (data.created) {
95
+ console.log(` First published : ${data.created}`);
96
+ if (Date.now() - Date.parse(data.created) < thirtyDaysMs) {
97
+ console.log(` 🟠 HIGH [DEP-002] Published less than 30 days ago — verify this is intentional.`);
98
+ hasFindings = true;
99
+ }
100
+ }
101
+ const dangerScripts = ['install', 'postinstall', 'preinstall'].filter((s) => s in data.latestScripts);
102
+ if (dangerScripts.length > 0) {
103
+ console.log(` 🟠 HIGH [DEP-003] Has install script(s): ${dangerScripts.join(', ')}`);
104
+ console.log(` Audit the script source before installing.`);
105
+ hasFindings = true;
106
+ }
107
+ if (!hasFindings) {
108
+ console.log(` No issues found. Always review packages before use.`);
109
+ }
110
+ return hasFindings ? 1 : 0;
111
+ }
112
+ async function runScan(opts) {
113
+ const root = resolve(opts.targetPath);
114
+ const isStructuredOutput = opts.mode === 'json' || opts.mode === 'sarif';
115
+ if (!isStructuredOutput) {
116
+ console.log(`CodeShield — scanning ${root}`);
117
+ if (opts.offline)
118
+ console.log('(offline mode: npm registry checks skipped)');
119
+ }
120
+ let result;
121
+ try {
122
+ result = await runScanAsync({
123
+ root,
124
+ minSeverity: opts.minSeverity,
125
+ scanners: [secretsScanner, envScanner, codeScanner],
126
+ depOptions: { offline: opts.offline },
127
+ });
128
+ }
129
+ catch (err) {
130
+ const msg = err instanceof Error ? err.message : String(err);
131
+ console.error(`Error during scan: ${sanitize(msg)}`);
132
+ return 2;
133
+ }
134
+ const scoreDetails = calculateScore(result.findings);
135
+ const previousScan = readLastScan(root);
136
+ let historyText;
137
+ if (previousScan) {
138
+ const comparison = compareWithLastScan(previousScan, scoreDetails.score, result.findings);
139
+ historyText = comparison.summaryText;
140
+ }
141
+ saveLastScan(root, scoreDetails.score, scoreDetails.grade, result.findings);
142
+ const output = renderReport(result, {
143
+ mode: opts.mode,
144
+ version: getVersion(),
145
+ ...(historyText ? { historyText } : {}),
146
+ });
147
+ console.log(output);
148
+ const failOnRank = SEVERITY_RANK[opts.failOn] ?? 0;
149
+ const hasFailingFindings = result.findings.some((f) => (SEVERITY_RANK[f.severity] ?? 0) >= failOnRank);
150
+ return hasFailingFindings ? 1 : 0;
151
+ }
152
+ export async function runCli(argv = process.argv.slice(2)) {
153
+ try {
154
+ const { values, positionals } = parseArgs({
155
+ args: argv,
156
+ options: {
157
+ help: { type: 'boolean', short: 'h', default: false },
158
+ version: { type: 'boolean', short: 'v', default: false },
159
+ offline: { type: 'boolean', default: false },
160
+ detailed: { type: 'boolean', default: false },
161
+ json: { type: 'boolean', default: false },
162
+ sarif: { type: 'boolean', default: false },
163
+ yes: { type: 'boolean', short: 'y', default: false },
164
+ severity: { type: 'string', default: 'info' },
165
+ 'fail-on': { type: 'string' },
166
+ },
167
+ allowPositionals: true,
168
+ strict: true,
169
+ });
170
+ if (values.version) {
171
+ console.log(`codeshield v${getVersion()}`);
172
+ return 0;
173
+ }
174
+ if (values.help || positionals.length === 0) {
175
+ console.log(HELP_TEXT);
176
+ return 0;
177
+ }
178
+ const severityArg = values.severity ?? 'info';
179
+ if (!isValidSeverity(severityArg)) {
180
+ console.error(`Error: Invalid severity "${sanitize(severityArg)}". ` +
181
+ `Valid values: ${SEVERITIES.join(', ')}`);
182
+ return 2;
183
+ }
184
+ const failOnArg = values['fail-on'] ?? severityArg;
185
+ if (!isValidSeverity(failOnArg)) {
186
+ console.error(`Error: Invalid fail-on severity "${sanitize(failOnArg)}". ` +
187
+ `Valid values: ${SEVERITIES.join(', ')}`);
188
+ return 2;
189
+ }
190
+ let mode = 'simple';
191
+ if (values.json)
192
+ mode = 'json';
193
+ else if (values.sarif)
194
+ mode = 'sarif';
195
+ else if (values.detailed)
196
+ mode = 'detailed';
197
+ const command = positionals[0];
198
+ if (command === 'scan') {
199
+ const targetPath = positionals[1] ?? '.';
200
+ return await runScan({
201
+ targetPath,
202
+ offline: values.offline ?? false,
203
+ minSeverity: severityArg,
204
+ failOn: failOnArg,
205
+ mode,
206
+ });
207
+ }
208
+ if (command === 'fix') {
209
+ const targetPath = positionals[1] ?? '.';
210
+ return await runFix(targetPath, values.yes ?? false);
211
+ }
212
+ if (command === 'verify') {
213
+ const pkgName = positionals[1];
214
+ if (!pkgName) {
215
+ console.error('Error: "verify" requires a package name. Example: codeshield verify express');
216
+ return 2;
217
+ }
218
+ return await runVerify(pkgName);
219
+ }
220
+ console.error(`Error: Unknown command "${sanitize(command)}". Run "codeshield --help" for available commands.`);
221
+ return 2;
222
+ }
223
+ catch (err) {
224
+ const message = err instanceof Error ? err.message : String(err);
225
+ console.error(`Error: ${sanitize(message)}`);
226
+ return 2;
227
+ }
228
+ }
229
+ const isDirectlyExecuted = process.argv[1] !== undefined &&
230
+ (process.argv[1] === fileURLToPath(import.meta.url) ||
231
+ process.argv[1].endsWith('/codeshield') ||
232
+ process.argv[1].endsWith('\\codeshield'));
233
+ if (isDirectlyExecuted) {
234
+ const exitCode = await runCli();
235
+ process.exit(exitCode);
236
+ }
237
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { ScannedFile } from '../types.js';
2
+ export interface FileWalkerOptions {
3
+ root: string;
4
+ maxFiles?: number;
5
+ maxBytes?: number;
6
+ onSkip?: (filePath: string, reason: string) => void;
7
+ }
8
+ export interface FileWalkerResult {
9
+ files: ScannedFile[];
10
+ filesVisited: number;
11
+ filesSkipped: number;
12
+ truncated: boolean;
13
+ }
14
+ export declare function walkFiles(root: string, options?: Partial<FileWalkerOptions>): FileWalkerResult;
15
+ //# sourceMappingURL=fileWalker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileWalker.d.ts","sourceRoot":"","sources":["../../src/engine/fileWalker.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAS1C,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACrD;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,OAAO,CAAC,iBAAiB,CAAM,GAAG,gBAAgB,CAkLlG"}