shipcheck-cli 0.2.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Tate Lyman
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.
package/README.md ADDED
@@ -0,0 +1,110 @@
1
+ # shipcheck-cli
2
+
3
+ Release-readiness and AI-app exposure scanner for JavaScript and TypeScript repositories.
4
+
5
+ `shipcheck` inspects a repo before you publish, hand it to a client, or ask someone to review it. It catches the boring issues that make projects feel unfinished: missing CI, missing lockfiles, thin documentation, loose dependency versions, unsafe package scripts, and local environment-file hygiene problems.
6
+
7
+ It also checks the failure points that show up in AI-built apps made with Lovable, Bolt, Replit, Cursor, v0, Base44, Supabase, Firebase, Stripe, and AI API integrations: exposed private keys, public frontend env vars that look private, unsigned Stripe webhooks, missing Firebase rules, undocumented Supabase RLS, debug API routes, and missing AI usage guardrails.
8
+
9
+ ## Install
10
+
11
+ Run from GitHub without publishing to npm:
12
+
13
+ ```bash
14
+ npx --yes github:TateLyman/shipcheck-cli .
15
+ ```
16
+
17
+ Clone and build locally:
18
+
19
+ ```bash
20
+ npm install
21
+ npm run build
22
+ ```
23
+
24
+ Run locally:
25
+
26
+ ```bash
27
+ node dist/src/cli.js .
28
+ ```
29
+
30
+ After publishing or linking:
31
+
32
+ ```bash
33
+ shipcheck ../my-app --format markdown
34
+ ```
35
+
36
+ ## Usage
37
+
38
+ ```bash
39
+ shipcheck [path] [--format text|markdown|json] [--fail-on info|low|medium|high] [--strict]
40
+ ```
41
+
42
+ Examples:
43
+
44
+ ```bash
45
+ shipcheck
46
+ shipcheck ../client-app --format markdown
47
+ shipcheck . --strict --fail-on medium
48
+ ```
49
+
50
+ ## What It Checks
51
+
52
+ - `package.json` exists and has repeatable `test` and `build` scripts
53
+ - dangerous package scripts such as broad `rm -rf`, `sudo`, `curl | bash`, and force pushes
54
+ - loose dependency versions such as `latest`, `*`, direct URLs, and Git dependencies
55
+ - dependency lockfile presence and package-manager consistency
56
+ - README depth, license declaration, and `.gitignore` hygiene
57
+ - GitHub Actions workflow presence
58
+ - TypeScript files without `tsconfig.json`
59
+ - `.env` risk and missing `.env.example` when environment variables are used
60
+ - hardcoded private-looking secrets such as Stripe secret keys and AI provider API keys
61
+ - public frontend env names that include `SECRET`, `SERVICE`, `PRIVATE`, `TOKEN`, or `WEBHOOK`
62
+ - Stripe webhook handlers that do not visibly verify signatures
63
+ - Firebase usage without checked-in `firestore.rules` or `storage.rules`
64
+ - Supabase usage without visible RLS migrations, policy notes, or access-boundary proof
65
+ - debug, seed, reset, mock, or test API routes that may ship to production
66
+ - AI/API usage without obvious rate limits, quotas, throttling, or cost guardrails
67
+
68
+ Shipcheck is a defensive static scanner, not a penetration test. It looks for review gaps and risky patterns in repos you own or are authorized to inspect.
69
+
70
+ ## Output
71
+
72
+ Text output is designed for terminal use:
73
+
74
+ ```text
75
+ Shipcheck report: /work/my-app
76
+ Score: 78/100
77
+ Status: pass
78
+ Findings: 0 high, 2 medium, 1 low, 0 info
79
+ ```
80
+
81
+ Markdown output is designed for client handoff:
82
+
83
+ ```bash
84
+ shipcheck ../my-app --format markdown > shipcheck-report.md
85
+ ```
86
+
87
+ JSON output is designed for automation:
88
+
89
+ ```bash
90
+ shipcheck . --format json
91
+ ```
92
+
93
+ ## Exit Codes
94
+
95
+ By default, `shipcheck` exits with code `1` only when a `high` finding is present.
96
+
97
+ Use `--fail-on medium` for CI gates:
98
+
99
+ ```bash
100
+ shipcheck . --strict --fail-on medium
101
+ ```
102
+
103
+ ## Development
104
+
105
+ ```bash
106
+ npm install
107
+ npm run check
108
+ ```
109
+
110
+ The test suite uses Node's built-in test runner and temporary fixture repositories.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env node
2
+ import { formatReport } from "./format.js";
3
+ import { scanRepository, shouldFail } from "./index.js";
4
+ const validFormats = new Set(["text", "markdown", "json"]);
5
+ const validSeverities = new Set(["info", "low", "medium", "high"]);
6
+ async function main() {
7
+ const args = parseArgs(process.argv.slice(2));
8
+ if (args.help) {
9
+ console.log(helpText());
10
+ return;
11
+ }
12
+ if (args.version) {
13
+ console.log("0.2.0");
14
+ return;
15
+ }
16
+ const report = await scanRepository({
17
+ root: args.root,
18
+ strict: args.strict,
19
+ failOn: args.failOn
20
+ });
21
+ console.log(formatReport(report, args.format));
22
+ if (shouldFail(report)) {
23
+ process.exitCode = 1;
24
+ }
25
+ }
26
+ function parseArgs(argv) {
27
+ const parsed = {
28
+ root: process.cwd(),
29
+ format: "text",
30
+ strict: false,
31
+ failOn: "high",
32
+ help: false,
33
+ version: false
34
+ };
35
+ for (let index = 0; index < argv.length; index += 1) {
36
+ const arg = argv[index];
37
+ if (!arg) {
38
+ continue;
39
+ }
40
+ if (arg === "--help" || arg === "-h") {
41
+ parsed.help = true;
42
+ continue;
43
+ }
44
+ if (arg === "--version" || arg === "-v") {
45
+ parsed.version = true;
46
+ continue;
47
+ }
48
+ if (arg === "--strict") {
49
+ parsed.strict = true;
50
+ continue;
51
+ }
52
+ if (arg === "--format") {
53
+ const value = argv[index + 1];
54
+ if (!value || !validFormats.has(value)) {
55
+ throw new Error("--format must be one of: text, markdown, json");
56
+ }
57
+ parsed.format = value;
58
+ index += 1;
59
+ continue;
60
+ }
61
+ if (arg === "--fail-on") {
62
+ const value = argv[index + 1];
63
+ if (!value || !validSeverities.has(value)) {
64
+ throw new Error("--fail-on must be one of: info, low, medium, high");
65
+ }
66
+ parsed.failOn = value;
67
+ index += 1;
68
+ continue;
69
+ }
70
+ if (arg.startsWith("--")) {
71
+ throw new Error(`Unknown option: ${arg}`);
72
+ }
73
+ parsed.root = arg;
74
+ }
75
+ return parsed;
76
+ }
77
+ function helpText() {
78
+ return [
79
+ "shipcheck - release-readiness and AI-app exposure scanner for JavaScript and TypeScript repos",
80
+ "",
81
+ "Usage:",
82
+ " shipcheck [path] [--format text|markdown|json] [--fail-on info|low|medium|high] [--strict]",
83
+ "",
84
+ "Examples:",
85
+ " shipcheck",
86
+ " shipcheck ../my-app --format markdown",
87
+ " shipcheck . --strict --fail-on medium",
88
+ "",
89
+ "Options:",
90
+ " --format Output format. Defaults to text.",
91
+ " --fail-on Exit non-zero when this severity or higher is found. Defaults to high.",
92
+ " --strict Treat missing lint scripts as a release-readiness issue.",
93
+ " --help Show this help message.",
94
+ " --version Show the CLI version."
95
+ ].join("\n");
96
+ }
97
+ main().catch((error) => {
98
+ console.error(error instanceof Error ? error.message : String(error));
99
+ process.exitCode = 1;
100
+ });
101
+ //# 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,2 @@
1
+ import type { ScanReport } from "./index.js";
2
+ export declare function formatReport(report: ScanReport, format: "text" | "markdown" | "json"): string;
@@ -0,0 +1,82 @@
1
+ const severityLabel = {
2
+ high: "High",
3
+ medium: "Medium",
4
+ low: "Low",
5
+ info: "Info"
6
+ };
7
+ export function formatReport(report, format) {
8
+ if (format === "json") {
9
+ return JSON.stringify(report, null, 2);
10
+ }
11
+ if (format === "markdown") {
12
+ return formatMarkdown(report);
13
+ }
14
+ return formatText(report);
15
+ }
16
+ function formatText(report) {
17
+ const lines = [
18
+ `Shipcheck report: ${report.root}`,
19
+ `Score: ${report.score}/100`,
20
+ `Status: ${report.ok ? "pass" : `fail (threshold: ${report.failOn})`}`,
21
+ `Findings: ${summary(report)}`,
22
+ ""
23
+ ];
24
+ if (report.findings.length === 0) {
25
+ lines.push("No findings. This repo has the basics needed for a clean release.");
26
+ return lines.join("\n");
27
+ }
28
+ for (const finding of report.findings) {
29
+ lines.push(renderTextFinding(finding), "");
30
+ }
31
+ return lines.join("\n").trimEnd();
32
+ }
33
+ function formatMarkdown(report) {
34
+ const lines = [
35
+ "# Shipcheck Report",
36
+ "",
37
+ `- **Repository:** \`${report.root}\``,
38
+ `- **Score:** ${report.score}/100`,
39
+ `- **Status:** ${report.ok ? "Pass" : `Fail at \`${report.failOn}\` threshold`}`,
40
+ `- **Findings:** ${summary(report)}`,
41
+ ""
42
+ ];
43
+ if (report.findings.length === 0) {
44
+ lines.push("No findings. This repo has the basics needed for a clean release.");
45
+ return lines.join("\n");
46
+ }
47
+ lines.push("## Findings", "");
48
+ for (const finding of report.findings) {
49
+ const rendered = [
50
+ `### ${severityLabel[finding.severity]}: ${finding.title}`,
51
+ "",
52
+ `- **ID:** \`${finding.id}\``,
53
+ finding.file ? `- **File:** \`${finding.file}\`` : undefined,
54
+ `- **Problem:** ${finding.message}`,
55
+ `- **Fix:** ${finding.remediation}`,
56
+ ""
57
+ ].filter((line) => line !== undefined);
58
+ lines.push(...rendered);
59
+ }
60
+ return lines.join("\n").trimEnd();
61
+ }
62
+ function renderTextFinding(finding) {
63
+ const lines = [
64
+ `[${finding.severity.toUpperCase()}] ${finding.title}`,
65
+ ` id: ${finding.id}`
66
+ ];
67
+ if (finding.file) {
68
+ lines.push(` file: ${finding.file}`);
69
+ }
70
+ lines.push(` problem: ${finding.message}`);
71
+ lines.push(` fix: ${finding.remediation}`);
72
+ return lines.join("\n");
73
+ }
74
+ function summary(report) {
75
+ return [
76
+ `${report.totals.high} high`,
77
+ `${report.totals.medium} medium`,
78
+ `${report.totals.low} low`,
79
+ `${report.totals.info} info`
80
+ ].join(", ");
81
+ }
82
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/format.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export type Severity = "info" | "low" | "medium" | "high";
2
+ export type Finding = {
3
+ id: string;
4
+ title: string;
5
+ severity: Severity;
6
+ message: string;
7
+ remediation: string;
8
+ file?: string;
9
+ };
10
+ export type ScanOptions = {
11
+ root: string;
12
+ strict?: boolean;
13
+ failOn?: Severity;
14
+ };
15
+ export type ScanReport = {
16
+ root: string;
17
+ score: number;
18
+ ok: boolean;
19
+ failOn: Severity;
20
+ totals: Record<Severity, number>;
21
+ findings: Finding[];
22
+ };
23
+ export declare function scanRepository(options: ScanOptions): Promise<ScanReport>;
24
+ export declare function shouldFail(report: ScanReport): boolean;
@@ -0,0 +1,590 @@
1
+ import { readdir, readFile, stat } from "node:fs/promises";
2
+ import path from "node:path";
3
+ const severityRank = {
4
+ info: 0,
5
+ low: 1,
6
+ medium: 2,
7
+ high: 3
8
+ };
9
+ const scorePenalty = {
10
+ info: 0,
11
+ low: 4,
12
+ medium: 10,
13
+ high: 22
14
+ };
15
+ export async function scanRepository(options) {
16
+ const root = path.resolve(options.root);
17
+ const failOn = options.failOn ?? "high";
18
+ const strict = options.strict ?? false;
19
+ const findings = [];
20
+ const pkg = await readPackageJson(root);
21
+ if (!pkg) {
22
+ findings.push({
23
+ id: "missing-package-json",
24
+ title: "No package.json found",
25
+ severity: "high",
26
+ message: "Shipcheck is optimized for JavaScript and TypeScript repositories and could not find package.json.",
27
+ remediation: "Run shipcheck from a JS/TS project root or add package.json before release.",
28
+ file: "package.json"
29
+ });
30
+ }
31
+ await checkReadme(root, findings);
32
+ await checkLicense(root, pkg, findings);
33
+ await checkGitignore(root, findings);
34
+ await checkCi(root, findings);
35
+ await checkTypeScript(root, findings);
36
+ await checkEnvHygiene(root, findings);
37
+ await checkAiAppExposure(root, pkg, findings);
38
+ if (pkg) {
39
+ checkScripts(pkg, findings, strict);
40
+ checkDependencies(pkg, findings);
41
+ await checkPackageManager(root, pkg, findings);
42
+ }
43
+ const totals = countTotals(findings);
44
+ const rawScore = findings.reduce((score, finding) => score - scorePenalty[finding.severity], 100);
45
+ const score = Math.max(0, rawScore);
46
+ const ok = !findings.some((finding) => severityRank[finding.severity] >= severityRank[failOn]);
47
+ return {
48
+ root,
49
+ score,
50
+ ok,
51
+ failOn,
52
+ totals,
53
+ findings: sortFindings(findings)
54
+ };
55
+ }
56
+ export function shouldFail(report) {
57
+ return !report.ok;
58
+ }
59
+ async function readPackageJson(root) {
60
+ const packagePath = path.join(root, "package.json");
61
+ const body = await readText(packagePath);
62
+ if (!body) {
63
+ return null;
64
+ }
65
+ try {
66
+ return JSON.parse(body);
67
+ }
68
+ catch {
69
+ return null;
70
+ }
71
+ }
72
+ async function checkReadme(root, findings) {
73
+ const readmePath = path.join(root, "README.md");
74
+ const readme = await readText(readmePath);
75
+ if (!readme) {
76
+ findings.push({
77
+ id: "missing-readme",
78
+ title: "README.md is missing",
79
+ severity: "medium",
80
+ message: "A release-ready repo should explain what it does, how to install it, and how to verify it.",
81
+ remediation: "Add README.md with install, usage, examples, and test commands.",
82
+ file: "README.md"
83
+ });
84
+ return;
85
+ }
86
+ if (readme.trim().length < 350) {
87
+ findings.push({
88
+ id: "thin-readme",
89
+ title: "README.md is too thin",
90
+ severity: "low",
91
+ message: "The README exists, but it is short enough that users may still need to inspect the code.",
92
+ remediation: "Add usage examples, expected output, design notes, and local verification commands.",
93
+ file: "README.md"
94
+ });
95
+ }
96
+ }
97
+ async function checkLicense(root, pkg, findings) {
98
+ const hasLicenseFile = await exists(path.join(root, "LICENSE")) || await exists(path.join(root, "LICENSE.md"));
99
+ if (!hasLicenseFile && !pkg?.license) {
100
+ findings.push({
101
+ id: "missing-license",
102
+ title: "License is not declared",
103
+ severity: "low",
104
+ message: "Users and companies may avoid using code when reuse rights are unclear.",
105
+ remediation: "Add a LICENSE file or set the license field in package.json.",
106
+ file: "LICENSE"
107
+ });
108
+ }
109
+ }
110
+ async function checkGitignore(root, findings) {
111
+ const gitignore = await readText(path.join(root, ".gitignore"));
112
+ if (!gitignore) {
113
+ findings.push({
114
+ id: "missing-gitignore",
115
+ title: ".gitignore is missing",
116
+ severity: "medium",
117
+ message: "Without a .gitignore, generated files and local secrets are easier to commit by accident.",
118
+ remediation: "Add .gitignore entries for node_modules, dist, coverage, logs, and local env files.",
119
+ file: ".gitignore"
120
+ });
121
+ return;
122
+ }
123
+ const requiredEntries = ["node_modules", ".env"];
124
+ const missing = requiredEntries.filter((entry) => !gitignore.includes(entry));
125
+ if (missing.length > 0) {
126
+ findings.push({
127
+ id: "incomplete-gitignore",
128
+ title: ".gitignore misses common local files",
129
+ severity: "medium",
130
+ message: `Missing entries: ${missing.join(", ")}.`,
131
+ remediation: "Add ignores for dependency directories and local environment files.",
132
+ file: ".gitignore"
133
+ });
134
+ }
135
+ }
136
+ async function checkCi(root, findings) {
137
+ const workflowDir = path.join(root, ".github", "workflows");
138
+ if (!await exists(workflowDir)) {
139
+ findings.push({
140
+ id: "missing-ci",
141
+ title: "No GitHub Actions workflow found",
142
+ severity: "medium",
143
+ message: "The repo does not advertise an automated verification path for pull requests.",
144
+ remediation: "Add a CI workflow that runs install, lint, build, and tests.",
145
+ file: ".github/workflows"
146
+ });
147
+ return;
148
+ }
149
+ const workflows = await listFiles(workflowDir, 1);
150
+ const yamlWorkflows = workflows.filter((file) => file.endsWith(".yml") || file.endsWith(".yaml"));
151
+ if (yamlWorkflows.length === 0) {
152
+ findings.push({
153
+ id: "empty-ci",
154
+ title: "Workflow directory has no YAML workflow",
155
+ severity: "medium",
156
+ message: "The workflow folder exists, but GitHub Actions will not run without a YAML file.",
157
+ remediation: "Add a workflow file such as .github/workflows/ci.yml.",
158
+ file: ".github/workflows"
159
+ });
160
+ }
161
+ }
162
+ async function checkTypeScript(root, findings) {
163
+ const files = await listFiles(root, 4);
164
+ const hasTypeScript = files.some((file) => file.endsWith(".ts") || file.endsWith(".tsx"));
165
+ if (hasTypeScript && !await exists(path.join(root, "tsconfig.json"))) {
166
+ findings.push({
167
+ id: "missing-tsconfig",
168
+ title: "TypeScript files exist without tsconfig.json",
169
+ severity: "medium",
170
+ message: "TypeScript projects need an explicit compiler contract to make local and CI checks consistent.",
171
+ remediation: "Add tsconfig.json with strict compiler options and include it in CI.",
172
+ file: "tsconfig.json"
173
+ });
174
+ }
175
+ }
176
+ async function checkEnvHygiene(root, findings) {
177
+ const envPath = path.join(root, ".env");
178
+ const examplePath = path.join(root, ".env.example");
179
+ const hasEnv = await exists(envPath);
180
+ const hasExample = await exists(examplePath);
181
+ if (hasEnv) {
182
+ findings.push({
183
+ id: "local-env-present",
184
+ title: ".env exists in the project root",
185
+ severity: "medium",
186
+ message: "A local .env file can accidentally leak secrets if it is committed or copied into an artifact.",
187
+ remediation: "Keep .env ignored and commit a redacted .env.example instead.",
188
+ file: ".env"
189
+ });
190
+ }
191
+ const sourceFiles = await listFiles(root, 4);
192
+ const likelyUsesEnv = sourceFiles.some((file) => file.endsWith(".js") || file.endsWith(".ts"))
193
+ && await repoTextMatches(sourceFiles, /process\.env(?:\.[A-Z_][A-Z0-9_]*|\[['"][A-Z_][A-Z0-9_]*['"]\])/);
194
+ if (likelyUsesEnv && !hasExample) {
195
+ findings.push({
196
+ id: "missing-env-example",
197
+ title: "Environment variables are used without .env.example",
198
+ severity: "low",
199
+ message: "New contributors cannot tell which environment variables are required.",
200
+ remediation: "Add .env.example with placeholder values and document each variable.",
201
+ file: ".env.example"
202
+ });
203
+ }
204
+ }
205
+ async function checkAiAppExposure(root, pkg, findings) {
206
+ const files = (await listFiles(root, 5)).filter(isProductionRelevantFile);
207
+ await checkHardcodedSecrets(root, files, findings);
208
+ await checkStripeWebhookVerification(root, pkg, files, findings);
209
+ await checkFirebaseRules(root, pkg, files, findings);
210
+ await checkSupabaseRls(root, pkg, files, findings);
211
+ await checkDebugRoutes(root, files, findings);
212
+ await checkAiUsageGuardrails(root, pkg, files, findings);
213
+ }
214
+ async function checkHardcodedSecrets(root, files, findings) {
215
+ const secretPatterns = [
216
+ { pattern: /\bsk_live_[A-Za-z0-9]{12,}\b/, label: "Stripe live secret key" },
217
+ { pattern: /\bsk_test_[A-Za-z0-9]{12,}\b/, label: "Stripe test secret key" },
218
+ { pattern: /\brk_live_[A-Za-z0-9]{12,}\b/, label: "Stripe restricted key" },
219
+ { pattern: /\b(?:OPENAI|ANTHROPIC|GROQ|XAI|GEMINI|GOOGLE)_API_KEY\s*[:=]\s*["'][^"'\s]{20,}["']/i, label: "AI provider API key" },
220
+ { pattern: /\bSUPABASE_SERVICE_ROLE(?:_KEY)?\s*[:=]\s*["'][^"'\s]{20,}["']/i, label: "Supabase service-role key" }
221
+ ];
222
+ for (const file of files.filter(isSourceOrConfigFile)) {
223
+ const text = await readText(file);
224
+ if (!text) {
225
+ continue;
226
+ }
227
+ const secretMatch = secretPatterns.find(({ pattern }) => pattern.test(text));
228
+ if (secretMatch) {
229
+ findings.push({
230
+ id: "hardcoded-private-secret",
231
+ title: "Private secret appears in repo text",
232
+ severity: "high",
233
+ message: `Detected a likely ${secretMatch.label} in a source or config file.`,
234
+ remediation: "Rotate the key, move it to server-only environment variables, and make sure it is not reachable from browser bundles.",
235
+ file: relativeTo(root, file)
236
+ });
237
+ return;
238
+ }
239
+ const publicPrivateEnv = /\b(?:NEXT_PUBLIC|VITE|PUBLIC)_[A-Z0-9_]*(?:SECRET|SERVICE|PRIVATE|TOKEN|WEBHOOK)[A-Z0-9_]*\b/;
240
+ if (publicPrivateEnv.test(text)) {
241
+ findings.push({
242
+ id: "public-private-env-name",
243
+ title: "Private-looking env var is exposed to browser code",
244
+ severity: "high",
245
+ message: "The repo references a public frontend env var name that includes secret, service, private, token, or webhook.",
246
+ remediation: "Rename private values without a public prefix and read them only from server routes or server actions.",
247
+ file: relativeTo(root, file)
248
+ });
249
+ return;
250
+ }
251
+ const serviceRoleReference = /process\.env\.(?:SUPABASE_SERVICE_ROLE|SUPABASE_SERVICE_ROLE_KEY)\b|["']service_role["']\s*[:=]|serviceRoleKey\s*[:=]/.test(text);
252
+ if (/\bsupabase\b/i.test(text) && serviceRoleReference) {
253
+ findings.push({
254
+ id: "supabase-service-role-reference",
255
+ title: "Supabase service role appears in application code",
256
+ severity: "high",
257
+ message: "Service-role credentials bypass row-level security and should not appear in frontend or shared application code.",
258
+ remediation: "Keep service-role usage inside tightly scoped server-only admin code, rotate any exposed key, and verify no client bundle contains it.",
259
+ file: relativeTo(root, file)
260
+ });
261
+ return;
262
+ }
263
+ }
264
+ }
265
+ async function checkStripeWebhookVerification(root, pkg, files, findings) {
266
+ const usesStripe = hasDependency(pkg, "stripe") || await repoTextMatches(files, /\bstripe\b/i);
267
+ if (!usesStripe) {
268
+ return;
269
+ }
270
+ for (const file of files.filter(isSourceOrConfigFile)) {
271
+ const relative = relativeTo(root, file);
272
+ const text = await readText(file);
273
+ if (!text) {
274
+ continue;
275
+ }
276
+ const looksLikeWebhook = /webhook/i.test(relative) || /checkout\.session|invoice\.|customer\.subscription|payment_intent/i.test(text);
277
+ const verifiesSignature = /webhooks\.constructEvent|constructEvent\(/.test(text);
278
+ if (looksLikeWebhook && /\bstripe\b/i.test(text) && !verifiesSignature) {
279
+ findings.push({
280
+ id: "unsigned-stripe-webhook",
281
+ title: "Stripe webhook handler may skip signature verification",
282
+ severity: "high",
283
+ message: "A Stripe webhook-like file handles Stripe events without an obvious constructEvent signature check.",
284
+ remediation: "Verify the raw request body with stripe.webhooks.constructEvent before granting paid access, credits, roles, or orders.",
285
+ file: relative
286
+ });
287
+ return;
288
+ }
289
+ }
290
+ }
291
+ async function checkFirebaseRules(root, pkg, files, findings) {
292
+ const usesFirebase = hasDependency(pkg, "firebase") || hasDependency(pkg, "@firebase/app")
293
+ || await repoTextMatches(files, /\b(?:getFirestore|initializeApp)\(|firebaseConfig\s*=/);
294
+ if (!usesFirebase) {
295
+ return;
296
+ }
297
+ const hasFirestoreRules = await exists(path.join(root, "firestore.rules"));
298
+ const hasStorageRules = await exists(path.join(root, "storage.rules"));
299
+ if (!hasFirestoreRules && !hasStorageRules) {
300
+ findings.push({
301
+ id: "missing-firebase-rules",
302
+ title: "Firebase app has no checked-in security rules",
303
+ severity: "medium",
304
+ message: "Firebase projects need explicit Firestore or Storage rules to make user-data boundaries reviewable.",
305
+ remediation: "Commit firestore.rules or storage.rules and test denied reads/writes with at least two separate users.",
306
+ file: "firestore.rules"
307
+ });
308
+ }
309
+ }
310
+ async function checkSupabaseRls(root, pkg, files, findings) {
311
+ const usesSupabase = hasDependency(pkg, "@supabase/supabase-js")
312
+ || await repoTextMatches(files, /\bcreateClient\([^)]*supabase|process\.env\.(?:NEXT_PUBLIC_)?SUPABASE_URL|supabaseUrl\s*=/i);
313
+ if (!usesSupabase) {
314
+ return;
315
+ }
316
+ const hasSupabaseFolder = await exists(path.join(root, "supabase"));
317
+ const hasRlsNotes = await repoTextMatches(files, /\b(row level security|rls|auth\.uid\(\)|policy)\b/i);
318
+ if (!hasSupabaseFolder && !hasRlsNotes) {
319
+ findings.push({
320
+ id: "undocumented-supabase-rls",
321
+ title: "Supabase usage has no visible RLS proof",
322
+ severity: "medium",
323
+ message: "The repo uses Supabase, but the scan did not find migrations, policies, or documentation showing row-level security was tested.",
324
+ remediation: "Add Supabase migrations or a short launch note showing RLS policies and two-user access-boundary tests.",
325
+ file: "supabase"
326
+ });
327
+ }
328
+ }
329
+ async function checkDebugRoutes(root, files, findings) {
330
+ const riskyRoute = files.find((file) => {
331
+ const relative = relativeTo(root, file).replace(/\\/g, "/");
332
+ return /(?:^|\/)(?:app|pages|src\/app|src\/pages)\/api\/(?:debug|test|dev|seed|mock|reset)(?:\/|\.|-)/i.test(relative);
333
+ });
334
+ if (riskyRoute) {
335
+ findings.push({
336
+ id: "debug-api-route",
337
+ title: "Debug or seed API route may ship to production",
338
+ severity: "medium",
339
+ message: "Debug, test, seed, reset, and mock API routes are common AI-app leftovers that can expose data or mutate production state.",
340
+ remediation: "Remove the route, gate it behind server-side admin checks, or make it impossible to deploy in production.",
341
+ file: relativeTo(root, riskyRoute)
342
+ });
343
+ }
344
+ }
345
+ async function checkAiUsageGuardrails(root, pkg, files, findings) {
346
+ const usesAiProvider = hasAnyDependency(pkg, ["openai", "@anthropic-ai/sdk", "ai", "@google/generative-ai"])
347
+ || await repoTextMatches(files, /\b(?:from\s+["']openai["']|require\(["']openai["']\)|new\s+OpenAI\(|generateText\(|streamText\(|chat\.completions)\b/i);
348
+ if (!usesAiProvider) {
349
+ return;
350
+ }
351
+ const hasCostGuardrail = await repoTextMatches(files, /\b(rateLimit|rate-limit|quota|usageLimit|usage_limit|throttle|limiter|upstash\/ratelimit)\b/i);
352
+ if (!hasCostGuardrail) {
353
+ findings.push({
354
+ id: "missing-ai-usage-guardrail",
355
+ title: "AI/API usage has no obvious quota or rate limit",
356
+ severity: "low",
357
+ message: "Apps that call paid AI APIs need usage guardrails so one user or bot cannot run up costs.",
358
+ remediation: "Add per-user quotas, route-level rate limits, abuse logging, or a billing-aware usage cap around expensive AI actions.",
359
+ file: "package.json"
360
+ });
361
+ }
362
+ }
363
+ function checkScripts(pkg, findings, strict) {
364
+ const scripts = pkg.scripts ?? {};
365
+ const missingRequired = ["test", "build"].filter((script) => !scripts[script]);
366
+ const missingStrict = strict ? ["lint"].filter((script) => !scripts[script]) : [];
367
+ const missing = [...missingRequired, ...missingStrict];
368
+ if (missing.length > 0) {
369
+ findings.push({
370
+ id: "missing-package-scripts",
371
+ title: "Expected package scripts are missing",
372
+ severity: strict ? "medium" : "low",
373
+ message: `Missing scripts: ${missing.join(", ")}.`,
374
+ remediation: "Add repeatable npm scripts so maintainers and CI run the same checks.",
375
+ file: "package.json"
376
+ });
377
+ }
378
+ const dangerousPatterns = [
379
+ [/\brm\s+-rf\s+(?:\/[^\s]*|\*|~[^\s]*|\.\.[^\s]*)(?:\s|$)/i, "recursive forced deletion outside a clearly scoped build folder"],
380
+ [/\bsudo\b/i, "privileged command execution"],
381
+ [/\bcurl\b.+\|\s*(?:sh|bash)\b/i, "curl piped directly into a shell"],
382
+ [/\bwget\b.+\|\s*(?:sh|bash)\b/i, "wget piped directly into a shell"],
383
+ [/\bgit\s+push\b.+\s--force(?:-with-lease)?\b/i, "force push in a package script"]
384
+ ];
385
+ for (const [name, command] of Object.entries(scripts)) {
386
+ const match = dangerousPatterns.find(([pattern]) => pattern.test(command));
387
+ if (match) {
388
+ findings.push({
389
+ id: "dangerous-package-script",
390
+ title: `Package script "${name}" contains a dangerous command`,
391
+ severity: "high",
392
+ message: `Detected ${match[1]} in: ${command}`,
393
+ remediation: "Replace broad destructive commands with scoped cleanup scripts and require manual confirmation for risky operations.",
394
+ file: "package.json"
395
+ });
396
+ }
397
+ }
398
+ }
399
+ function checkDependencies(pkg, findings) {
400
+ const groups = {
401
+ dependencies: pkg.dependencies ?? {},
402
+ devDependencies: pkg.devDependencies ?? {},
403
+ peerDependencies: pkg.peerDependencies ?? {}
404
+ };
405
+ for (const [groupName, deps] of Object.entries(groups)) {
406
+ for (const [name, version] of Object.entries(deps)) {
407
+ const normalized = version.trim().toLowerCase();
408
+ const loose = normalized === "*" || normalized === "latest" || normalized.startsWith("http://")
409
+ || normalized.startsWith("https://") || normalized.startsWith("git+");
410
+ if (loose) {
411
+ findings.push({
412
+ id: "loose-dependency-version",
413
+ title: `Loose dependency version for ${name}`,
414
+ severity: "medium",
415
+ message: `${groupName}.${name} uses "${version}", which can change without review.`,
416
+ remediation: "Use a semver range or exact version and rely on dependency update tooling for upgrades.",
417
+ file: "package.json"
418
+ });
419
+ }
420
+ }
421
+ }
422
+ }
423
+ async function checkPackageManager(root, pkg, findings) {
424
+ const lockfiles = [
425
+ ["npm", "package-lock.json"],
426
+ ["pnpm", "pnpm-lock.yaml"],
427
+ ["yarn", "yarn.lock"],
428
+ ["bun", "bun.lockb"]
429
+ ];
430
+ const present = [];
431
+ for (const [manager, lockfile] of lockfiles) {
432
+ if (await exists(path.join(root, lockfile))) {
433
+ present.push({ manager, lockfile });
434
+ }
435
+ }
436
+ if (present.length === 0) {
437
+ findings.push({
438
+ id: "missing-lockfile",
439
+ title: "No dependency lockfile found",
440
+ severity: "medium",
441
+ message: "Installs may resolve different dependency trees across machines and CI.",
442
+ remediation: "Commit the lockfile generated by the package manager used by the project.",
443
+ file: "package-lock.json"
444
+ });
445
+ return;
446
+ }
447
+ if (present.length > 1) {
448
+ const firstLockfile = present[0]?.lockfile ?? "package-lock.json";
449
+ findings.push({
450
+ id: "multiple-lockfiles",
451
+ title: "Multiple package manager lockfiles found",
452
+ severity: "medium",
453
+ message: `Found: ${present.map((item) => item.lockfile).join(", ")}.`,
454
+ remediation: "Keep one lockfile and remove stale lockfiles from other package managers.",
455
+ file: firstLockfile
456
+ });
457
+ }
458
+ if (pkg.packageManager) {
459
+ const declaredManager = pkg.packageManager.split("@")[0];
460
+ const lockfileManagers = new Set(present.map((item) => item.manager));
461
+ if (declaredManager && !lockfileManagers.has(declaredManager)) {
462
+ findings.push({
463
+ id: "package-manager-mismatch",
464
+ title: "packageManager does not match lockfile",
465
+ severity: "medium",
466
+ message: `package.json declares ${pkg.packageManager}, but found ${present.map((item) => item.lockfile).join(", ")}.`,
467
+ remediation: "Update packageManager or regenerate the lockfile with the declared tool.",
468
+ file: "package.json"
469
+ });
470
+ }
471
+ }
472
+ }
473
+ async function repoTextMatches(files, pattern) {
474
+ for (const file of files) {
475
+ if (file.includes("node_modules") || file.includes(`${path.sep}dist${path.sep}`)) {
476
+ continue;
477
+ }
478
+ const text = await readText(file);
479
+ if (text && pattern.test(text)) {
480
+ return true;
481
+ }
482
+ }
483
+ return false;
484
+ }
485
+ async function readText(filePath) {
486
+ try {
487
+ return await readFile(filePath, "utf8");
488
+ }
489
+ catch {
490
+ return null;
491
+ }
492
+ }
493
+ async function exists(filePath) {
494
+ try {
495
+ await stat(filePath);
496
+ return true;
497
+ }
498
+ catch {
499
+ return false;
500
+ }
501
+ }
502
+ async function listFiles(root, maxDepth) {
503
+ const output = [];
504
+ async function walk(current, depth) {
505
+ if (depth > maxDepth) {
506
+ return;
507
+ }
508
+ let entries;
509
+ try {
510
+ entries = await readdir(current, { withFileTypes: true });
511
+ }
512
+ catch {
513
+ return;
514
+ }
515
+ for (const entry of entries) {
516
+ if (entry.name === "node_modules" || entry.name === ".git" || entry.name === "dist") {
517
+ continue;
518
+ }
519
+ const fullPath = path.join(current, entry.name);
520
+ if (entry.isDirectory()) {
521
+ await walk(fullPath, depth + 1);
522
+ }
523
+ else if (entry.isFile()) {
524
+ output.push(fullPath);
525
+ }
526
+ }
527
+ }
528
+ await walk(root, 0);
529
+ return output;
530
+ }
531
+ function hasDependency(pkg, name) {
532
+ if (!pkg) {
533
+ return false;
534
+ }
535
+ return Boolean(pkg.dependencies?.[name] || pkg.devDependencies?.[name] || pkg.peerDependencies?.[name]);
536
+ }
537
+ function hasAnyDependency(pkg, names) {
538
+ return names.some((name) => hasDependency(pkg, name));
539
+ }
540
+ function isSourceOrConfigFile(file) {
541
+ const basename = path.basename(file).toLowerCase();
542
+ if (basename.endsWith("-lock.json") || basename.endsWith(".lock") || basename === "license") {
543
+ return false;
544
+ }
545
+ const extension = path.extname(file).toLowerCase();
546
+ return [
547
+ ".js",
548
+ ".jsx",
549
+ ".ts",
550
+ ".tsx",
551
+ ".mjs",
552
+ ".cjs",
553
+ ".json",
554
+ ".env",
555
+ ".local",
556
+ ".toml",
557
+ ".yaml",
558
+ ".yml"
559
+ ].includes(extension) || basename.startsWith(".env");
560
+ }
561
+ function isProductionRelevantFile(file) {
562
+ const normalized = file.replace(/\\/g, "/").toLowerCase();
563
+ const basename = path.basename(normalized);
564
+ return !normalized.includes("/test/")
565
+ && !normalized.includes("/tests/")
566
+ && !normalized.includes("/__tests__/")
567
+ && !normalized.includes("/fixtures/")
568
+ && !normalized.includes("/fixture/")
569
+ && !basename.includes(".test.")
570
+ && !basename.includes(".spec.");
571
+ }
572
+ function relativeTo(root, file) {
573
+ return path.relative(root, file) || path.basename(file);
574
+ }
575
+ function countTotals(findings) {
576
+ return findings.reduce((totals, finding) => {
577
+ totals[finding.severity] += 1;
578
+ return totals;
579
+ }, { info: 0, low: 0, medium: 0, high: 0 });
580
+ }
581
+ function sortFindings(findings) {
582
+ return [...findings].sort((a, b) => {
583
+ const severityDelta = severityRank[b.severity] - severityRank[a.severity];
584
+ if (severityDelta !== 0) {
585
+ return severityDelta;
586
+ }
587
+ return a.id.localeCompare(b.id);
588
+ });
589
+ }
590
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "shipcheck-cli",
3
+ "version": "0.2.0",
4
+ "description": "Release-readiness and AI-app exposure scanner for JavaScript and TypeScript repositories.",
5
+ "type": "module",
6
+ "bin": {
7
+ "shipcheck": "dist/src/cli.js"
8
+ },
9
+ "files": [
10
+ "dist/src",
11
+ "README.md",
12
+ "LICENSE"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc -p tsconfig.json",
16
+ "lint": "tsc -p tsconfig.json --noEmit",
17
+ "test": "npm run build && node --test \"dist/test/**/*.test.js\"",
18
+ "check": "npm run lint && npm test",
19
+ "prepare": "npm run build"
20
+ },
21
+ "keywords": [
22
+ "cli",
23
+ "release",
24
+ "audit",
25
+ "ai-app",
26
+ "vibe-coding",
27
+ "security",
28
+ "supabase",
29
+ "stripe",
30
+ "typescript",
31
+ "javascript"
32
+ ],
33
+ "author": "Tate Lyman",
34
+ "license": "MIT",
35
+ "devDependencies": {
36
+ "@types/node": "^22.15.3",
37
+ "typescript": "^5.8.3"
38
+ },
39
+ "engines": {
40
+ "node": ">=20"
41
+ }
42
+ }