@nikhil_telkar/codeshield 0.0.0-stage → 0.1.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 (103) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +289 -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 +56 -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,290 @@
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 reproduce dangerous security anti-patterns: hardcoding secrets, hallucinating nonexistent npm packages, string-concatenating SQL queries, using `Math.random()` for security tokens, or omitting basic security headers.
6
+
7
+ **CodeShield** acts as a lightweight 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 directory
17
+ npx codeshield scan .
18
+
19
+ # Automatically apply safe fixes (.gitignore, .env.example)
20
+ npx codeshield fix .
21
+
22
+ # Check if an npm package is real, safe, or a typosquat
23
+ npx codeshield verify express
24
+ ```
25
+
26
+ Or install globally:
27
+
28
+ ```bash
29
+ npm install -g codeshield
30
+ codeshield scan .
31
+ ```
32
+
33
+ ---
34
+
35
+ ## 🖥️ Example 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 : 4 [1 critical, 2 high, 1 medium]
45
+ Duration : 32ms
46
+ ────────────────────────────────────────────────────────────
47
+
48
+ 🎯 Fix These First (Top Priorities):
49
+
50
+ 🔴 CRITICAL [SEC-001] Hardcoded AWS Access Key
51
+ Location : src/config/aws.ts:14
52
+ CWE : CWE-798
53
+ Why : An AWS Access Key ID was found directly in your code. Anyone with access
54
+ to this repo can compromise your AWS account and spin up costly resources.
55
+ Fix : Move credentials to process.env.AWS_ACCESS_KEY_ID or use IAM roles.
56
+ Prompt : Refactor src/config/aws.ts to load AWS credentials from
57
+ process.env.AWS_ACCESS_KEY_ID and process.env.AWS_SECRET_ACCESS_KEY.
58
+ Update .env.example with placeholders.
59
+
60
+ 🟠 HIGH [DEP-001] Likely Hallucinated npm Package
61
+ Location : package.json:18
62
+ CWE : CWE-829
63
+ Why : "auth0-express-secure-kit" does not exist in the npm registry.
64
+ AI models often hallucinate plausible-sounding package names.
65
+ Fix : Remove the package from package.json and replace it with an official library.
66
+ Prompt : The dependency "auth0-express-secure-kit" does not exist on npm.
67
+ Rewrite our auth integration using the official "express-openid-connect" SDK.
68
+
69
+ 🟡 MEDIUM [ENV-001] .env File Not in .gitignore
70
+ Location : .env:1
71
+ CWE : CWE-552
72
+ Why : A .env file containing environment variables exists but is not ignored by git.
73
+ Fix : Run `codeshield fix` to automatically add .env to .gitignore.
74
+ ```
75
+
76
+ ---
77
+
78
+ ## 🔍 What CodeShield Checks
79
+
80
+ CodeShield evaluates codebases across four core dimensions:
81
+
82
+ ### 1. Secrets Scanner (`src/scanners/secrets.ts`)
83
+ - **AWS Credentials:** Hardcoded `AKIA...` access keys and credentials (`CWE-798`).
84
+ - **Stripe Keys:** Live API keys (`sk_live_...`) (`CWE-798`).
85
+ - **GitHub Tokens:** Personal access tokens (`ghp_...`, `github_pat_...`) (`CWE-798`).
86
+ - **AI Provider API Keys:** OpenAI (`sk-...`), Anthropic (`sk-ant-...`) keys (`CWE-798`).
87
+ - **Supabase Service Keys:** Hardcoded `service_role` JWTs (`CWE-798`).
88
+ - **Database Connection Strings:** URLs containing credentials (`postgres://user:pass@host/db`) (`CWE-256`).
89
+ - **Private Key Headers:** Unencrypted PEM blocks (`BEGIN RSA/OPENSSH PRIVATE KEY`) (`CWE-312`).
90
+ - **Hardcoded JWT Secrets:** Literal strings passed to `jwt.sign()` (`CWE-798`).
91
+ - **High-Entropy Generic Secrets:** Assignments to API key / secret variables (`CWE-798`).
92
+ - **Client-Side Secret Leakage:** Private keys placed in `NEXT_PUBLIC_*` or `VITE_*` variables (`CWE-200`).
93
+
94
+ ### 2. Environment Scanner (`src/scanners/env.ts`)
95
+ - **Unignored `.env` Files:** Real credentials exposed to git tracking (`CWE-552`).
96
+ - **Committed `.env` Files:** Credentials already committed into git (`CWE-552`).
97
+ - **Missing `.env.example`:** Repositories with `.env` but no sanitized template for teammates (`CWE-552`).
98
+ - **Production Source Maps:** `productionBrowserSourceMaps: true` or `sourcemap: true` leaking proprietary source code in production bundles (`CWE-540`).
99
+
100
+ ### 3. Dependency Scanner (`src/scanners/dependencies.ts`)
101
+ - **Hallucinated Packages (DEP-001):** Packages in `package.json` that do not exist on npm (`CWE-829`).
102
+ - **Newly Published Packages (DEP-002):** Dependencies published $< 30$ days ago (`CWE-829`).
103
+ - **Install Scripts (DEP-003):** Packages with `preinstall`, `install`, or `postinstall` lifecycle hooks that run arbitrary shell code (`CWE-829`).
104
+ - **Typosquatting (DEP-004):** Dependencies 1 edit away from popular libraries (`expres`, `reakt`, `lodahs`) (`CWE-829`).
105
+ - **Registry Errors (DEP-005):** Unreachable packages reported as "Could not check" (never silently passed as safe).
106
+
107
+ ### 4. Code Scanner (`src/scanners/code.ts`)
108
+ - **Arbitrary Code Execution:** `eval()` and `new Function()` (`CWE-95`).
109
+ - **SQL Injection:** String concatenation in `db.query()`, `prisma.$queryRawUnsafe()`, etc. (`CWE-89`).
110
+ - **NoSQL Injection:** Raw `req.body` or `req.query` passed directly into MongoDB/Mongoose filters (`CWE-943`).
111
+ - **Command Injection:** `child_process.exec()` called with variables (`CWE-78`).
112
+ - **Insecure Randomness:** `Math.random()` used for passwords, secrets, or tokens (`CWE-338`).
113
+ - **Broken Cryptography:** MD5 or SHA-1 used for password hashing (`CWE-328`).
114
+ - **Cross-Site Scripting (XSS):** `dangerouslySetInnerHTML` or `element.innerHTML` with dynamic variables (`CWE-79`).
115
+ - **Permissive CORS:** `cors({ origin: '*' })` with credentials enabled (`CWE-942`).
116
+ - **Insecure Cookies:** `res.cookie()` without `httpOnly: true` or `secure: true` (`CWE-1004`, `CWE-614`).
117
+ - **Indefinite JWTs:** `jwt.sign()` calls missing an `expiresIn` option (`CWE-613`).
118
+ - **Missing Helmet:** Express applications without the `helmet` security header middleware (`CWE-693`).
119
+ - **Stack Trace Leakage:** Returning `err.stack` in HTTP responses (`CWE-209`).
120
+ - **Client-Side Supabase Admin:** Using Supabase `service_role` keys inside frontend files (`CWE-200`).
121
+
122
+ ---
123
+
124
+ ## 🛠️ CLI Commands & Options
125
+
126
+ ```text
127
+ Usage:
128
+ codeshield scan [path] [options] Scan directory (default: current dir)
129
+ codeshield fix [path] [--yes] Apply safe, reversible fixes automatically
130
+ codeshield verify <package> Check a single npm package
131
+ codeshield --help Show this help
132
+ codeshield --version Show version
133
+ ```
134
+
135
+ ### Scan Options
136
+
137
+ | Option | Description |
138
+ | :--- | :--- |
139
+ | `--detailed` | Show full metadata for all findings (CWE, rule ID, file, line, explanation). |
140
+ | `--json` | Output machine-readable JSON (ideal for CI pipelines). |
141
+ | `--sarif` | Output static analysis results in SARIF v2.1.0 format (for GitHub Security). |
142
+ | `--fail-on <severity>` | Set exit code to 1 if any findings match or exceed `<severity>` (`critical`, `high`, `medium`, `low`, `info`). Default: `info`. |
143
+ | `--severity <severity>` | Filter the report to only include findings at or above `<severity>`. Default: `info`. |
144
+ | `--offline` | Skip all npm registry lookups (runs purely offline). |
145
+
146
+ ### Fix Options
147
+
148
+ | Option | Description |
149
+ | :--- | :--- |
150
+ | `-y, --yes` | Apply safe fixes automatically without an interactive prompt. |
151
+
152
+ *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.
153
+
154
+ ### Exit Codes
155
+
156
+ | Code | Meaning |
157
+ | :---: | :--- |
158
+ | `0` | **Passed:** No findings at or above the `--fail-on` threshold. |
159
+ | `1` | **Failed:** One or more findings detected at or above the `--fail-on` threshold. |
160
+ | `2` | **Tool Error:** Invalid CLI arguments, missing files, or unreadable directory. |
161
+
162
+ ---
163
+
164
+ ## 📊 How the Security Score Works
165
+
166
+ CodeShield calculates an objective score between **0 and 100**:
167
+
168
+ $$\text{Score} = \max\left(0, 100 - \sum \text{Deductions}\right)$$
169
+
170
+ ### Severity Weights & Deductions
171
+
172
+ | Severity | Points Deducted per Finding | Maximum Deductions per Rule |
173
+ | :--- | :---: | :---: |
174
+ | **Critical** | -25 | Max 2 findings counted (-50) |
175
+ | **High** | -15 | Max 2 findings counted (-30) |
176
+ | **Medium** | -8 | Max 2 findings counted (-16) |
177
+ | **Low** | -3 | Max 2 findings counted (-6) |
178
+ | **Info** | -1 | Max 2 findings counted (-2) |
179
+
180
+ ### Anti-Noise Rule Capping
181
+ To ensure that a single noisy rule in a large codebase does not artificially zero out your score, deductions are capped at **2 findings per individual rule**.
182
+
183
+ ### Grade Scale
184
+
185
+ - **90–100 [Grade A]** — Excellent: No critical or high issues found.
186
+ - **75–89 [Grade B]** — Good: Minor low/medium issues.
187
+ - **50–74 [Grade C]** — Needs Attention: High-risk findings present.
188
+ - **25–49 [Grade D]** — Poor: Multiple severe vulnerabilities.
189
+ - **0–24 [Grade F]** — Failing: Immediate remediation required.
190
+
191
+ ---
192
+
193
+ ## 🤖 CI / CD Integration
194
+
195
+ ### GitHub Actions Workflow
196
+
197
+ Add `.github/workflows/security.yml`:
198
+
199
+ ```yaml
200
+ name: CodeShield Security Scan
201
+
202
+ on:
203
+ push:
204
+ branches: [main]
205
+ pull_request:
206
+ branches: [main]
207
+
208
+ jobs:
209
+ scan:
210
+ runs-on: ubuntu-latest
211
+ steps:
212
+ - name: Checkout repository
213
+ uses: actions/checkout@v4
214
+
215
+ - name: Set up Node.js
216
+ uses: actions/setup-node@v4
217
+ with:
218
+ node-version: '20'
219
+
220
+ # Option A: Fail the build on high/critical findings
221
+ - name: Run CodeShield Scan
222
+ run: npx codeshield scan . --fail-on high
223
+
224
+ # Option B: Upload SARIF report to GitHub Advanced Security tab
225
+ - name: Generate SARIF report
226
+ if: always()
227
+ run: npx codeshield scan . --sarif > results.sarif
228
+
229
+ - name: Upload SARIF to GitHub Code Scanning
230
+ uses: github/codeql-action/upload-sarif@v3
231
+ if: always()
232
+ with:
233
+ sarif_file: results.sarif
234
+ ```
235
+
236
+ ---
237
+
238
+ ## 🔒 Privacy & Security Statement
239
+
240
+ - **100% Local Execution:** CodeShield never uploads your source code, filenames, or directory paths to external servers.
241
+ - **Zero Telemetry:** No analytics, no phone-home pings, no cookies, no tracking.
242
+ - **Zero Runtime Dependencies:** Zero third-party packages installed in production. Zero supply chain risk.
243
+ - **Strict Read-Only Scanning:** CodeShield inspects text files using Node built-in file APIs. It **never** dynamically evaluates, requires, or imports your code.
244
+ - **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 from the network.
245
+
246
+ ---
247
+
248
+ ## ⚠️ Honest Limitations
249
+
250
+ > **"CodeShield catches common security mistakes; it does not prove your code is secure."**
251
+
252
+ 1. **Heuristic Pattern Matching:** CodeShield scans for known insecure patterns, signatures, and anti-patterns common to AI-generated code. It does not perform symbolic execution or full AST taint tracking across modules.
253
+ 2. **Obfuscation & Dynamic Code:** Heavily obfuscated code or multi-step indirect injections (e.g., retrieving a malicious SQL string from a third-party microservice) will not be detected.
254
+ 3. **Business Logic Vulnerabilities:** Flaws in business logic (such as missing multi-tenant authorization checks or broken role-based access control) require human review and threat modeling.
255
+ 4. **Defense in Depth:** CodeShield is designed as a fast pre-commit check and CI gate. It should be used alongside comprehensive unit/integration testing, dynamic testing (DAST), and professional security audits.
256
+
257
+ ---
258
+
259
+ ## 🧩 How to Add a Rule
260
+
261
+ CodeShield uses a data-driven rule registry. To add a new rule:
262
+
263
+ 1. Open [`src/scanners/code.ts`](file:///Users/nikhiltelkar19gmail.com/Desktop/CODESHILD/src/scanners/code.ts) (or `secrets.ts` / `env.ts`).
264
+ 2. Add a rule object to `CODE_RULES`:
265
+
266
+ ```typescript
267
+ {
268
+ id: 'COD-014',
269
+ severity: 'high',
270
+ cwe: 'CWE-312',
271
+ title: 'Sensitive Token Stored in LocalStorage',
272
+ explanation: 'Storing session tokens in localStorage exposes them to XSS attacks.',
273
+ fix: 'Store tokens in HttpOnly, secure cookies instead.',
274
+ prompt: 'Refactor this code to store auth tokens in HttpOnly secure cookies instead of localStorage.',
275
+ matches(line: string, _file: ScannedFile): boolean {
276
+ return /localStorage\.setItem\s*\(\s*['"`](?:token|jwt|auth)['"`]/i.test(line);
277
+ },
278
+ }
279
+ ```
280
+
281
+ 3. Add unit tests and ReDoS performance benchmarks in `tests/code.test.ts`.
282
+ 4. Run `npm test` to verify.
283
+
284
+ See [CONTRIBUTING.md](file:///Users/nikhiltelkar19gmail.com/Desktop/CODESHILD/CONTRIBUTING.md) for full instructions and best practices.
285
+
286
+ ---
287
+
288
+ ## 📄 License
289
+
290
+ [MIT](file:///Users/nikhiltelkar19gmail.com/Desktop/CODESHILD/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"}