@fourteensystems/prodcheck 0.3.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/README.md +252 -0
- package/bin/prodcheck.mjs +2 -0
- package/dist/cli/commands/baseline.d.ts +7 -0
- package/dist/cli/commands/baseline.d.ts.map +1 -0
- package/dist/cli/commands/baseline.js +22 -0
- package/dist/cli/commands/baseline.js.map +1 -0
- package/dist/cli/commands/ci.d.ts +14 -0
- package/dist/cli/commands/ci.d.ts.map +1 -0
- package/dist/cli/commands/ci.js +104 -0
- package/dist/cli/commands/ci.js.map +1 -0
- package/dist/cli/commands/explain.d.ts +2 -0
- package/dist/cli/commands/explain.d.ts.map +1 -0
- package/dist/cli/commands/explain.js +20 -0
- package/dist/cli/commands/explain.js.map +1 -0
- package/dist/cli/commands/init.d.ts +7 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +127 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/rules.d.ts +2 -0
- package/dist/cli/commands/rules.d.ts.map +1 -0
- package/dist/cli/commands/rules.js +13 -0
- package/dist/cli/commands/rules.js.map +1 -0
- package/dist/cli/commands/scan.d.ts +10 -0
- package/dist/cli/commands/scan.d.ts.map +1 -0
- package/dist/cli/commands/scan.js +65 -0
- package/dist/cli/commands/scan.js.map +1 -0
- package/dist/cli/commands/waive.d.ts +8 -0
- package/dist/cli/commands/waive.d.ts.map +1 -0
- package/dist/cli/commands/waive.js +34 -0
- package/dist/cli/commands/waive.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +64 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/engine/baseline.d.ts +11 -0
- package/dist/engine/baseline.d.ts.map +1 -0
- package/dist/engine/baseline.js +39 -0
- package/dist/engine/baseline.js.map +1 -0
- package/dist/engine/baseline.test.d.ts +2 -0
- package/dist/engine/baseline.test.d.ts.map +1 -0
- package/dist/engine/baseline.test.js +135 -0
- package/dist/engine/baseline.test.js.map +1 -0
- package/dist/engine/config.d.ts +8 -0
- package/dist/engine/config.d.ts.map +1 -0
- package/dist/engine/config.js +134 -0
- package/dist/engine/config.js.map +1 -0
- package/dist/engine/config.test.d.ts +2 -0
- package/dist/engine/config.test.d.ts.map +1 -0
- package/dist/engine/config.test.js +107 -0
- package/dist/engine/config.test.js.map +1 -0
- package/dist/engine/extensions/load.d.ts +11 -0
- package/dist/engine/extensions/load.d.ts.map +1 -0
- package/dist/engine/extensions/load.js +26 -0
- package/dist/engine/extensions/load.js.map +1 -0
- package/dist/engine/extensions/registry.d.ts +5 -0
- package/dist/engine/extensions/registry.d.ts.map +1 -0
- package/dist/engine/extensions/registry.js +11 -0
- package/dist/engine/extensions/registry.js.map +1 -0
- package/dist/engine/extensions/types.d.ts +51 -0
- package/dist/engine/extensions/types.d.ts.map +1 -0
- package/dist/engine/extensions/types.js +2 -0
- package/dist/engine/extensions/types.js.map +1 -0
- package/dist/engine/license.d.ts +40 -0
- package/dist/engine/license.d.ts.map +1 -0
- package/dist/engine/license.js +104 -0
- package/dist/engine/license.js.map +1 -0
- package/dist/engine/report.d.ts +5 -0
- package/dist/engine/report.d.ts.map +1 -0
- package/dist/engine/report.js +115 -0
- package/dist/engine/report.js.map +1 -0
- package/dist/engine/run.d.ts +11 -0
- package/dist/engine/run.d.ts.map +1 -0
- package/dist/engine/run.js +105 -0
- package/dist/engine/run.js.map +1 -0
- package/dist/engine/sarif.d.ts +3 -0
- package/dist/engine/sarif.d.ts.map +1 -0
- package/dist/engine/sarif.js +58 -0
- package/dist/engine/sarif.js.map +1 -0
- package/dist/engine/sarif.test.d.ts +2 -0
- package/dist/engine/sarif.test.d.ts.map +1 -0
- package/dist/engine/sarif.test.js +152 -0
- package/dist/engine/sarif.test.js.map +1 -0
- package/dist/engine/score.d.ts +13 -0
- package/dist/engine/score.d.ts.map +1 -0
- package/dist/engine/score.js +116 -0
- package/dist/engine/score.js.map +1 -0
- package/dist/engine/score.test.d.ts +2 -0
- package/dist/engine/score.test.d.ts.map +1 -0
- package/dist/engine/score.test.js +227 -0
- package/dist/engine/score.test.js.map +1 -0
- package/dist/engine/types.d.ts +123 -0
- package/dist/engine/types.d.ts.map +1 -0
- package/dist/engine/types.js +2 -0
- package/dist/engine/types.js.map +1 -0
- package/dist/engine/version.d.ts +5 -0
- package/dist/engine/version.d.ts.map +1 -0
- package/dist/engine/version.js +15 -0
- package/dist/engine/version.js.map +1 -0
- package/dist/engine/waivers.d.ts +9 -0
- package/dist/engine/waivers.d.ts.map +1 -0
- package/dist/engine/waivers.js +55 -0
- package/dist/engine/waivers.js.map +1 -0
- package/dist/engine/waivers.test.d.ts +2 -0
- package/dist/engine/waivers.test.d.ts.map +1 -0
- package/dist/engine/waivers.test.js +147 -0
- package/dist/engine/waivers.test.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/next/deps.d.ts +4 -0
- package/dist/next/deps.d.ts.map +1 -0
- package/dist/next/deps.js +118 -0
- package/dist/next/deps.js.map +1 -0
- package/dist/next/deps.test.d.ts +2 -0
- package/dist/next/deps.test.d.ts.map +1 -0
- package/dist/next/deps.test.js +249 -0
- package/dist/next/deps.test.js.map +1 -0
- package/dist/next/detect.d.ts +10 -0
- package/dist/next/detect.d.ts.map +1 -0
- package/dist/next/detect.js +57 -0
- package/dist/next/detect.js.map +1 -0
- package/dist/next/detect.test.d.ts +2 -0
- package/dist/next/detect.test.d.ts.map +1 -0
- package/dist/next/detect.test.js +74 -0
- package/dist/next/detect.test.js.map +1 -0
- package/dist/next/index.d.ts +5 -0
- package/dist/next/index.d.ts.map +1 -0
- package/dist/next/index.js +59 -0
- package/dist/next/index.js.map +1 -0
- package/dist/next/middleware.d.ts +3 -0
- package/dist/next/middleware.d.ts.map +1 -0
- package/dist/next/middleware.js +48 -0
- package/dist/next/middleware.js.map +1 -0
- package/dist/next/middleware.test.d.ts +2 -0
- package/dist/next/middleware.test.d.ts.map +1 -0
- package/dist/next/middleware.test.js +203 -0
- package/dist/next/middleware.test.js.map +1 -0
- package/dist/next/routes.d.ts +10 -0
- package/dist/next/routes.d.ts.map +1 -0
- package/dist/next/routes.js +172 -0
- package/dist/next/routes.js.map +1 -0
- package/dist/next/routes.test.d.ts +2 -0
- package/dist/next/routes.test.d.ts.map +1 -0
- package/dist/next/routes.test.js +175 -0
- package/dist/next/routes.test.js.map +1 -0
- package/dist/next/server-actions.d.ts +4 -0
- package/dist/next/server-actions.d.ts.map +1 -0
- package/dist/next/server-actions.js +107 -0
- package/dist/next/server-actions.js.map +1 -0
- package/dist/next/server-actions.test.d.ts +2 -0
- package/dist/next/server-actions.test.d.ts.map +1 -0
- package/dist/next/server-actions.test.js +138 -0
- package/dist/next/server-actions.test.js.map +1 -0
- package/dist/next/trpc.d.ts +3 -0
- package/dist/next/trpc.d.ts.map +1 -0
- package/dist/next/trpc.js +312 -0
- package/dist/next/trpc.js.map +1 -0
- package/dist/next/types.d.ts +144 -0
- package/dist/next/types.d.ts.map +1 -0
- package/dist/next/types.js +2 -0
- package/dist/next/types.js.map +1 -0
- package/dist/next/wrappers.d.ts +10 -0
- package/dist/next/wrappers.d.ts.map +1 -0
- package/dist/next/wrappers.js +536 -0
- package/dist/next/wrappers.js.map +1 -0
- package/dist/next/wrappers.test.d.ts +2 -0
- package/dist/next/wrappers.test.d.ts.map +1 -0
- package/dist/next/wrappers.test.js +361 -0
- package/dist/next/wrappers.test.js.map +1 -0
- package/dist/rules/auth-boundary-missing.d.ts +5 -0
- package/dist/rules/auth-boundary-missing.d.ts.map +1 -0
- package/dist/rules/auth-boundary-missing.js +463 -0
- package/dist/rules/auth-boundary-missing.js.map +1 -0
- package/dist/rules/auth-boundary-missing.test.d.ts +2 -0
- package/dist/rules/auth-boundary-missing.test.d.ts.map +1 -0
- package/dist/rules/auth-boundary-missing.test.js +492 -0
- package/dist/rules/auth-boundary-missing.test.js.map +1 -0
- package/dist/rules/index.d.ts +12 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +95 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/input-validation-missing.d.ts +5 -0
- package/dist/rules/input-validation-missing.d.ts.map +1 -0
- package/dist/rules/input-validation-missing.js +272 -0
- package/dist/rules/input-validation-missing.js.map +1 -0
- package/dist/rules/input-validation-missing.test.d.ts +2 -0
- package/dist/rules/input-validation-missing.test.d.ts.map +1 -0
- package/dist/rules/input-validation-missing.test.js +449 -0
- package/dist/rules/input-validation-missing.test.js.map +1 -0
- package/dist/rules/rate-limit-missing.d.ts +5 -0
- package/dist/rules/rate-limit-missing.d.ts.map +1 -0
- package/dist/rules/rate-limit-missing.js +316 -0
- package/dist/rules/rate-limit-missing.js.map +1 -0
- package/dist/rules/rate-limit-missing.test.d.ts +2 -0
- package/dist/rules/rate-limit-missing.test.d.ts.map +1 -0
- package/dist/rules/rate-limit-missing.test.js +381 -0
- package/dist/rules/rate-limit-missing.test.js.map +1 -0
- package/dist/rules/tenancy-scope-missing.d.ts +5 -0
- package/dist/rules/tenancy-scope-missing.d.ts.map +1 -0
- package/dist/rules/tenancy-scope-missing.js +149 -0
- package/dist/rules/tenancy-scope-missing.js.map +1 -0
- package/dist/rules/wrapper-unrecognized.d.ts +5 -0
- package/dist/rules/wrapper-unrecognized.d.ts.map +1 -0
- package/dist/rules/wrapper-unrecognized.js +81 -0
- package/dist/rules/wrapper-unrecognized.js.map +1 -0
- package/dist/util/hof.d.ts +22 -0
- package/dist/util/hof.d.ts.map +1 -0
- package/dist/util/hof.js +99 -0
- package/dist/util/hof.js.map +1 -0
- package/dist/util/hof.test.d.ts +2 -0
- package/dist/util/hof.test.d.ts.map +1 -0
- package/dist/util/hof.test.js +79 -0
- package/dist/util/hof.test.js.map +1 -0
- package/dist/util/monorepo.d.ts +6 -0
- package/dist/util/monorepo.d.ts.map +1 -0
- package/dist/util/monorepo.js +29 -0
- package/dist/util/monorepo.js.map +1 -0
- package/dist/util/outbound-fetch.d.ts +14 -0
- package/dist/util/outbound-fetch.d.ts.map +1 -0
- package/dist/util/outbound-fetch.js +59 -0
- package/dist/util/outbound-fetch.js.map +1 -0
- package/dist/util/outbound-fetch.test.d.ts +2 -0
- package/dist/util/outbound-fetch.test.d.ts.map +1 -0
- package/dist/util/outbound-fetch.test.js +83 -0
- package/dist/util/outbound-fetch.test.js.map +1 -0
- package/dist/util/paths.d.ts +6 -0
- package/dist/util/paths.d.ts.map +1 -0
- package/dist/util/paths.js +18 -0
- package/dist/util/paths.js.map +1 -0
- package/dist/util/resolve.d.ts +30 -0
- package/dist/util/resolve.d.ts.map +1 -0
- package/dist/util/resolve.js +306 -0
- package/dist/util/resolve.js.map +1 -0
- package/dist/util/resolve.test.d.ts +2 -0
- package/dist/util/resolve.test.d.ts.map +1 -0
- package/dist/util/resolve.test.js +186 -0
- package/dist/util/resolve.test.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { run, RULE_ID } from "./input-validation-missing.js";
|
|
5
|
+
/* ------------------------------------------------------------------ */
|
|
6
|
+
/* Helpers */
|
|
7
|
+
/* ------------------------------------------------------------------ */
|
|
8
|
+
const DB_WRITE_SIGNALS = {
|
|
9
|
+
hasMutationEvidence: true,
|
|
10
|
+
hasDbWriteEvidence: true,
|
|
11
|
+
hasStripeWriteEvidence: false,
|
|
12
|
+
mutationDetails: ["prisma.create", "reads request body"],
|
|
13
|
+
};
|
|
14
|
+
const STRIPE_WRITE_SIGNALS = {
|
|
15
|
+
hasMutationEvidence: true,
|
|
16
|
+
hasDbWriteEvidence: false,
|
|
17
|
+
hasStripeWriteEvidence: true,
|
|
18
|
+
mutationDetails: ["stripe write operation", "reads request body"],
|
|
19
|
+
};
|
|
20
|
+
const BODY_ONLY_SIGNALS = {
|
|
21
|
+
hasMutationEvidence: true,
|
|
22
|
+
hasDbWriteEvidence: false,
|
|
23
|
+
hasStripeWriteEvidence: false,
|
|
24
|
+
mutationDetails: ["reads request body"],
|
|
25
|
+
};
|
|
26
|
+
function protectionSummary() {
|
|
27
|
+
return {
|
|
28
|
+
auth: { satisfied: false, enforced: false, sources: [], details: [], unverifiedWrappers: [] },
|
|
29
|
+
rateLimit: { satisfied: false, enforced: false, sources: [], details: [], unverifiedWrappers: [] },
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
let tmpDir;
|
|
33
|
+
beforeEach(() => {
|
|
34
|
+
tmpDir = path.join("/tmp", `prodcheck-input-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
35
|
+
mkdirSync(tmpDir, { recursive: true });
|
|
36
|
+
});
|
|
37
|
+
afterEach(() => {
|
|
38
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
39
|
+
});
|
|
40
|
+
function createRoute(relPath, source, signals = DB_WRITE_SIGNALS) {
|
|
41
|
+
const fullPath = path.join(tmpDir, relPath);
|
|
42
|
+
mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
43
|
+
writeFileSync(fullPath, source);
|
|
44
|
+
const pathname = "/" + relPath
|
|
45
|
+
.replace(/\/route\.(ts|tsx|js|jsx)$/, "")
|
|
46
|
+
.replace(/^app\//, "");
|
|
47
|
+
return {
|
|
48
|
+
kind: "route-handler",
|
|
49
|
+
file: relPath,
|
|
50
|
+
isApi: pathname.startsWith("/api/"),
|
|
51
|
+
isPublic: true,
|
|
52
|
+
pathname,
|
|
53
|
+
signals,
|
|
54
|
+
protection: protectionSummary(),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function createAction(relPath, source, signals = DB_WRITE_SIGNALS) {
|
|
58
|
+
const fullPath = path.join(tmpDir, relPath);
|
|
59
|
+
mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
60
|
+
writeFileSync(fullPath, source);
|
|
61
|
+
return {
|
|
62
|
+
kind: "server-action",
|
|
63
|
+
file: relPath,
|
|
64
|
+
signals,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function makeIndex(routes = [], actions = []) {
|
|
68
|
+
return {
|
|
69
|
+
version: 1,
|
|
70
|
+
framework: "next-app-router",
|
|
71
|
+
rootDir: tmpDir,
|
|
72
|
+
deps: {
|
|
73
|
+
hasNextAuth: false, hasClerk: false, hasSupabase: false,
|
|
74
|
+
hasKinde: false, hasWorkOS: false, hasBetterAuth: false,
|
|
75
|
+
hasLucia: false, hasAuth0: false, hasIronSession: false,
|
|
76
|
+
hasFirebaseAuth: false, hasUpstashRatelimit: false, hasArcjet: false,
|
|
77
|
+
hasUnkey: false, hasPrisma: true, hasDrizzle: false, hasTrpc: false,
|
|
78
|
+
},
|
|
79
|
+
hints: {
|
|
80
|
+
auth: { functions: [], middlewareFiles: [], allowlistPaths: [] },
|
|
81
|
+
rateLimit: { wrappers: [], allowlistPaths: [] },
|
|
82
|
+
tenancy: { orgFieldNames: [] },
|
|
83
|
+
},
|
|
84
|
+
middleware: { authLikely: false, rateLimitLikely: false, matcherPatterns: [] },
|
|
85
|
+
wrappers: { wrappers: new Map() },
|
|
86
|
+
routes: { all: routes, mutationRoutes: routes },
|
|
87
|
+
serverActions: { all: actions, mutationActions: actions },
|
|
88
|
+
trpc: { detected: false, procedures: [], mutationProcedures: [] },
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function makeConfig() {
|
|
92
|
+
return {
|
|
93
|
+
framework: "next-app-router",
|
|
94
|
+
include: ["app/**"],
|
|
95
|
+
exclude: [],
|
|
96
|
+
ci: { failOn: "critical", minConfidence: "high", minScore: 70, maxNewCritical: 0 },
|
|
97
|
+
scoring: { start: 100, penalties: { critical: 25, high: 10, med: 3, low: 1 } },
|
|
98
|
+
hints: {
|
|
99
|
+
auth: { functions: [], middlewareFiles: [], allowlistPaths: [] },
|
|
100
|
+
rateLimit: { wrappers: [], allowlistPaths: [] },
|
|
101
|
+
tenancy: { orgFieldNames: [] },
|
|
102
|
+
},
|
|
103
|
+
rules: { "INPUT-VALIDATION-MISSING": { severity: "high" } },
|
|
104
|
+
waiversFile: "prodcheck.waivers.json",
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/* ------------------------------------------------------------------ */
|
|
108
|
+
/* Tests: should flag */
|
|
109
|
+
/* ------------------------------------------------------------------ */
|
|
110
|
+
describe("INPUT-VALIDATION-MISSING", () => {
|
|
111
|
+
describe("flags unvalidated input", () => {
|
|
112
|
+
it("request.json() + prisma.create without validation", () => {
|
|
113
|
+
const route = createRoute("app/api/users/route.ts", `
|
|
114
|
+
export async function POST(request: Request) {
|
|
115
|
+
const body = await request.json();
|
|
116
|
+
await prisma.user.create({ data: body });
|
|
117
|
+
return Response.json({ ok: true });
|
|
118
|
+
}
|
|
119
|
+
`);
|
|
120
|
+
const findings = run(makeIndex([route]), makeConfig());
|
|
121
|
+
expect(findings).toHaveLength(1);
|
|
122
|
+
expect(findings[0].ruleId).toBe(RULE_ID);
|
|
123
|
+
expect(findings[0].confidence).toBe("high");
|
|
124
|
+
});
|
|
125
|
+
it("request.formData() + prisma.update without validation", () => {
|
|
126
|
+
const route = createRoute("app/api/profile/route.ts", `
|
|
127
|
+
export async function POST(request: Request) {
|
|
128
|
+
const data = await request.formData();
|
|
129
|
+
const name = data.get("name");
|
|
130
|
+
await prisma.user.update({ where: { id }, data: { name } });
|
|
131
|
+
return Response.json({ ok: true });
|
|
132
|
+
}
|
|
133
|
+
`);
|
|
134
|
+
const findings = run(makeIndex([route]), makeConfig());
|
|
135
|
+
expect(findings).toHaveLength(1);
|
|
136
|
+
expect(findings[0].ruleId).toBe(RULE_ID);
|
|
137
|
+
});
|
|
138
|
+
it("req.body + prisma.create without validation", () => {
|
|
139
|
+
const route = createRoute("app/api/items/route.ts", `
|
|
140
|
+
export async function POST(req: NextRequest) {
|
|
141
|
+
const data = req.body;
|
|
142
|
+
await prisma.item.create({ data });
|
|
143
|
+
return NextResponse.json({ ok: true });
|
|
144
|
+
}
|
|
145
|
+
`);
|
|
146
|
+
const findings = run(makeIndex([route]), makeConfig());
|
|
147
|
+
expect(findings).toHaveLength(1);
|
|
148
|
+
});
|
|
149
|
+
it("request.json() + Stripe write without validation", () => {
|
|
150
|
+
const route = createRoute("app/api/billing/route.ts", `
|
|
151
|
+
export async function POST(request: Request) {
|
|
152
|
+
const body = await request.json();
|
|
153
|
+
await stripe.subscriptions.create({ customer: body.customerId, items: [{ price: body.priceId }] });
|
|
154
|
+
return Response.json({ ok: true });
|
|
155
|
+
}
|
|
156
|
+
`, STRIPE_WRITE_SIGNALS);
|
|
157
|
+
const findings = run(makeIndex([route]), makeConfig());
|
|
158
|
+
expect(findings).toHaveLength(1);
|
|
159
|
+
});
|
|
160
|
+
it("server action with unvalidated input + DB write", () => {
|
|
161
|
+
const action = createAction("app/actions/create-post.ts", `
|
|
162
|
+
"use server";
|
|
163
|
+
export async function createPost(formData: FormData) {
|
|
164
|
+
const title = formData.get("title");
|
|
165
|
+
const body = await request.json();
|
|
166
|
+
await prisma.post.create({ data: { title } });
|
|
167
|
+
}
|
|
168
|
+
`);
|
|
169
|
+
const findings = run(makeIndex([], [action]), makeConfig());
|
|
170
|
+
expect(findings).toHaveLength(1);
|
|
171
|
+
expect(findings[0].message).toContain("Server action");
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
/* ------------------------------------------------------------------ */
|
|
175
|
+
/* Tests: should NOT flag (validation present) */
|
|
176
|
+
/* ------------------------------------------------------------------ */
|
|
177
|
+
describe("does NOT flag when validation present", () => {
|
|
178
|
+
it("zod z.object() + .parse()", () => {
|
|
179
|
+
const route = createRoute("app/api/users/route.ts", `
|
|
180
|
+
import { z } from "zod";
|
|
181
|
+
const schema = z.object({ name: z.string(), email: z.string().email() });
|
|
182
|
+
export async function POST(request: Request) {
|
|
183
|
+
const body = await request.json();
|
|
184
|
+
const data = schema.parse(body);
|
|
185
|
+
await prisma.user.create({ data });
|
|
186
|
+
return Response.json({ ok: true });
|
|
187
|
+
}
|
|
188
|
+
`);
|
|
189
|
+
const findings = run(makeIndex([route]), makeConfig());
|
|
190
|
+
expect(findings).toHaveLength(0);
|
|
191
|
+
});
|
|
192
|
+
it("zod .safeParse()", () => {
|
|
193
|
+
const route = createRoute("app/api/users/route.ts", `
|
|
194
|
+
import { z } from "zod";
|
|
195
|
+
const schema = z.object({ name: z.string() });
|
|
196
|
+
export async function POST(request: Request) {
|
|
197
|
+
const body = await request.json();
|
|
198
|
+
const result = schema.safeParse(body);
|
|
199
|
+
if (!result.success) return Response.json({ error: result.error }, { status: 400 });
|
|
200
|
+
await prisma.user.create({ data: result.data });
|
|
201
|
+
return Response.json({ ok: true });
|
|
202
|
+
}
|
|
203
|
+
`);
|
|
204
|
+
const findings = run(makeIndex([route]), makeConfig());
|
|
205
|
+
expect(findings).toHaveLength(0);
|
|
206
|
+
});
|
|
207
|
+
it("valibot v.parse()", () => {
|
|
208
|
+
const route = createRoute("app/api/users/route.ts", `
|
|
209
|
+
import * as v from "valibot";
|
|
210
|
+
const schema = v.object({ name: v.string() });
|
|
211
|
+
export async function POST(request: Request) {
|
|
212
|
+
const body = await request.json();
|
|
213
|
+
const data = v.parse(schema, body);
|
|
214
|
+
await prisma.user.create({ data });
|
|
215
|
+
return Response.json({ ok: true });
|
|
216
|
+
}
|
|
217
|
+
`);
|
|
218
|
+
const findings = run(makeIndex([route]), makeConfig());
|
|
219
|
+
expect(findings).toHaveLength(0);
|
|
220
|
+
});
|
|
221
|
+
it("yup .validate()", () => {
|
|
222
|
+
const route = createRoute("app/api/users/route.ts", `
|
|
223
|
+
import * as yup from "yup";
|
|
224
|
+
const schema = yup.object({ name: yup.string().required() });
|
|
225
|
+
export async function POST(request: Request) {
|
|
226
|
+
const body = await request.json();
|
|
227
|
+
const data = await schema.validate(body);
|
|
228
|
+
await prisma.user.create({ data });
|
|
229
|
+
return Response.json({ ok: true });
|
|
230
|
+
}
|
|
231
|
+
`);
|
|
232
|
+
const findings = run(makeIndex([route]), makeConfig());
|
|
233
|
+
expect(findings).toHaveLength(0);
|
|
234
|
+
});
|
|
235
|
+
it("next-safe-action createSafeActionClient", () => {
|
|
236
|
+
const route = createRoute("app/api/users/route.ts", `
|
|
237
|
+
import { createSafeActionClient } from "next-safe-action";
|
|
238
|
+
const action = createSafeActionClient();
|
|
239
|
+
export async function POST(request: Request) {
|
|
240
|
+
const body = await request.json();
|
|
241
|
+
await prisma.user.create({ data: body });
|
|
242
|
+
}
|
|
243
|
+
`);
|
|
244
|
+
const findings = run(makeIndex([route]), makeConfig());
|
|
245
|
+
expect(findings).toHaveLength(0);
|
|
246
|
+
});
|
|
247
|
+
it("tRPC .input(z.object(...))", () => {
|
|
248
|
+
const route = createRoute("app/api/trpc/route.ts", `
|
|
249
|
+
import { z } from "zod";
|
|
250
|
+
const router = t.router({
|
|
251
|
+
create: t.procedure
|
|
252
|
+
.input(z.object({ name: z.string() }))
|
|
253
|
+
.mutation(async ({ input }) => {
|
|
254
|
+
const body = await request.json();
|
|
255
|
+
await prisma.user.create({ data: input });
|
|
256
|
+
}),
|
|
257
|
+
});
|
|
258
|
+
`);
|
|
259
|
+
const findings = run(makeIndex([route]), makeConfig());
|
|
260
|
+
expect(findings).toHaveLength(0);
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
/* ------------------------------------------------------------------ */
|
|
264
|
+
/* Tests: JSON.parse is NOT schema validation */
|
|
265
|
+
/* ------------------------------------------------------------------ */
|
|
266
|
+
describe("JSON.parse does NOT suppress findings", () => {
|
|
267
|
+
it("JSON.parse is not schema validation", () => {
|
|
268
|
+
const route = createRoute("app/api/users/route.ts", `
|
|
269
|
+
export async function POST(request: Request) {
|
|
270
|
+
const text = await request.json();
|
|
271
|
+
const config = JSON.parse(process.env.CONFIG);
|
|
272
|
+
await prisma.user.create({ data: text });
|
|
273
|
+
return Response.json({ ok: true });
|
|
274
|
+
}
|
|
275
|
+
`);
|
|
276
|
+
const findings = run(makeIndex([route]), makeConfig());
|
|
277
|
+
expect(findings).toHaveLength(1);
|
|
278
|
+
});
|
|
279
|
+
it("URL.parse is not schema validation", () => {
|
|
280
|
+
const route = createRoute("app/api/users/route.ts", `
|
|
281
|
+
export async function POST(request: Request) {
|
|
282
|
+
const body = await request.json();
|
|
283
|
+
const parsed = URL.parse(body.url);
|
|
284
|
+
await prisma.user.create({ data: body });
|
|
285
|
+
return Response.json({ ok: true });
|
|
286
|
+
}
|
|
287
|
+
`);
|
|
288
|
+
const findings = run(makeIndex([route]), makeConfig());
|
|
289
|
+
expect(findings).toHaveLength(1);
|
|
290
|
+
});
|
|
291
|
+
it("schema.parse alongside JSON.parse still suppresses", () => {
|
|
292
|
+
const route = createRoute("app/api/users/route.ts", `
|
|
293
|
+
import { z } from "zod";
|
|
294
|
+
const schema = z.object({ name: z.string() });
|
|
295
|
+
export async function POST(request: Request) {
|
|
296
|
+
const raw = await request.json();
|
|
297
|
+
const config = JSON.parse(process.env.CONFIG);
|
|
298
|
+
const data = schema.parse(raw);
|
|
299
|
+
await prisma.user.create({ data });
|
|
300
|
+
return Response.json({ ok: true });
|
|
301
|
+
}
|
|
302
|
+
`);
|
|
303
|
+
const findings = run(makeIndex([route]), makeConfig());
|
|
304
|
+
expect(findings).toHaveLength(0);
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
/* ------------------------------------------------------------------ */
|
|
308
|
+
/* Edge cases */
|
|
309
|
+
/* ------------------------------------------------------------------ */
|
|
310
|
+
describe("edge cases", () => {
|
|
311
|
+
it("chained .parse() like getSchema().parse(body) suppresses finding", () => {
|
|
312
|
+
const route = createRoute("app/api/users/route.ts", `
|
|
313
|
+
export async function POST(request: Request) {
|
|
314
|
+
const body = await request.json();
|
|
315
|
+
const data = getSchema("user").parse(body);
|
|
316
|
+
await prisma.user.create({ data });
|
|
317
|
+
return Response.json({ ok: true });
|
|
318
|
+
}
|
|
319
|
+
`);
|
|
320
|
+
const findings = run(makeIndex([route]), makeConfig());
|
|
321
|
+
expect(findings).toHaveLength(0);
|
|
322
|
+
});
|
|
323
|
+
it("commented-out schema.parse does NOT suppress finding", () => {
|
|
324
|
+
const route = createRoute("app/api/users/route.ts", `
|
|
325
|
+
export async function POST(request: Request) {
|
|
326
|
+
const body = await request.json();
|
|
327
|
+
// TODO: add validation
|
|
328
|
+
// const data = schema.parse(body);
|
|
329
|
+
await prisma.user.create({ data: body });
|
|
330
|
+
return Response.json({ ok: true });
|
|
331
|
+
}
|
|
332
|
+
`);
|
|
333
|
+
const findings = run(makeIndex([route]), makeConfig());
|
|
334
|
+
expect(findings).toHaveLength(1);
|
|
335
|
+
});
|
|
336
|
+
it("block-commented schema.parse does NOT suppress finding", () => {
|
|
337
|
+
const route = createRoute("app/api/users/route.ts", `
|
|
338
|
+
export async function POST(request: Request) {
|
|
339
|
+
const body = await request.json();
|
|
340
|
+
/*
|
|
341
|
+
const data = schema.parse(body);
|
|
342
|
+
*/
|
|
343
|
+
await prisma.user.create({ data: body });
|
|
344
|
+
return Response.json({ ok: true });
|
|
345
|
+
}
|
|
346
|
+
`);
|
|
347
|
+
const findings = run(makeIndex([route]), makeConfig());
|
|
348
|
+
expect(findings).toHaveLength(1);
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
|
+
/* ------------------------------------------------------------------ */
|
|
352
|
+
/* Tests: should NOT flag (no write or no body read) */
|
|
353
|
+
/* ------------------------------------------------------------------ */
|
|
354
|
+
describe("does NOT flag when conditions incomplete", () => {
|
|
355
|
+
it("reads body but no DB/Stripe write", () => {
|
|
356
|
+
const route = createRoute("app/api/echo/route.ts", `
|
|
357
|
+
export async function POST(request: Request) {
|
|
358
|
+
const body = await request.json();
|
|
359
|
+
return Response.json(body);
|
|
360
|
+
}
|
|
361
|
+
`, BODY_ONLY_SIGNALS);
|
|
362
|
+
const findings = run(makeIndex([route]), makeConfig());
|
|
363
|
+
expect(findings).toHaveLength(0);
|
|
364
|
+
});
|
|
365
|
+
it("DB write but no body read", () => {
|
|
366
|
+
const route = createRoute("app/api/cron/route.ts", `
|
|
367
|
+
export async function POST() {
|
|
368
|
+
await prisma.job.create({ data: { ran: new Date() } });
|
|
369
|
+
return Response.json({ ok: true });
|
|
370
|
+
}
|
|
371
|
+
`);
|
|
372
|
+
const findings = run(makeIndex([route]), makeConfig());
|
|
373
|
+
expect(findings).toHaveLength(0);
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
/* ------------------------------------------------------------------ */
|
|
377
|
+
/* public-intent severity bump */
|
|
378
|
+
/* ------------------------------------------------------------------ */
|
|
379
|
+
describe("public-intent severity bump", () => {
|
|
380
|
+
it("bumps severity when public-intent present (med → high)", () => {
|
|
381
|
+
const route = createRoute("app/api/ingest/route.ts", `
|
|
382
|
+
export async function POST(request: Request) {
|
|
383
|
+
const body = await request.json();
|
|
384
|
+
await stripe.subscriptions.create({ items: body.items });
|
|
385
|
+
}
|
|
386
|
+
`, STRIPE_WRITE_SIGNALS);
|
|
387
|
+
route.publicIntent = { reason: "Public ingest endpoint", line: 1 };
|
|
388
|
+
const findings = run(makeIndex([route]), makeConfig());
|
|
389
|
+
expect(findings).toHaveLength(1);
|
|
390
|
+
// Stripe-only would be med confidence → med severity, but public-intent bumps to high
|
|
391
|
+
expect(findings[0].severity).toBe("high");
|
|
392
|
+
expect(findings[0].tags).toContain("public-intent");
|
|
393
|
+
expect(findings[0].evidence).toContain('public-intent: "Public ingest endpoint"');
|
|
394
|
+
});
|
|
395
|
+
it("bumps confidence to high when public-intent present", () => {
|
|
396
|
+
const route = createRoute("app/api/ingest/route.ts", `
|
|
397
|
+
export async function POST(request: Request) {
|
|
398
|
+
const body = await request.json();
|
|
399
|
+
await stripe.subscriptions.create({ items: body.items });
|
|
400
|
+
}
|
|
401
|
+
`, STRIPE_WRITE_SIGNALS);
|
|
402
|
+
route.publicIntent = { reason: "Public endpoint", line: 1 };
|
|
403
|
+
const findings = run(makeIndex([route]), makeConfig());
|
|
404
|
+
expect(findings).toHaveLength(1);
|
|
405
|
+
// Stripe-only would be med confidence, but public-intent bumps to high
|
|
406
|
+
expect(findings[0].confidence).toBe("high");
|
|
407
|
+
});
|
|
408
|
+
it("does NOT bump when publicIntent is absent", () => {
|
|
409
|
+
const route = createRoute("app/api/ingest/route.ts", `
|
|
410
|
+
export async function POST(request: Request) {
|
|
411
|
+
const body = await request.json();
|
|
412
|
+
await stripe.subscriptions.create({ items: body.items });
|
|
413
|
+
}
|
|
414
|
+
`, STRIPE_WRITE_SIGNALS);
|
|
415
|
+
const findings = run(makeIndex([route]), makeConfig());
|
|
416
|
+
expect(findings).toHaveLength(1);
|
|
417
|
+
expect(findings[0].severity).toBe("med");
|
|
418
|
+
expect(findings[0].tags).not.toContain("public-intent");
|
|
419
|
+
});
|
|
420
|
+
});
|
|
421
|
+
/* ------------------------------------------------------------------ */
|
|
422
|
+
/* Confidence levels */
|
|
423
|
+
/* ------------------------------------------------------------------ */
|
|
424
|
+
describe("confidence levels", () => {
|
|
425
|
+
it("high confidence with DB write evidence", () => {
|
|
426
|
+
const route = createRoute("app/api/users/route.ts", `
|
|
427
|
+
export async function POST(request: Request) {
|
|
428
|
+
const body = await request.json();
|
|
429
|
+
await prisma.user.create({ data: body });
|
|
430
|
+
}
|
|
431
|
+
`);
|
|
432
|
+
const findings = run(makeIndex([route]), makeConfig());
|
|
433
|
+
expect(findings[0].confidence).toBe("high");
|
|
434
|
+
expect(findings[0].severity).toBe("high");
|
|
435
|
+
});
|
|
436
|
+
it("med confidence with Stripe write only (no DB)", () => {
|
|
437
|
+
const route = createRoute("app/api/billing/route.ts", `
|
|
438
|
+
export async function POST(request: Request) {
|
|
439
|
+
const body = await request.json();
|
|
440
|
+
await stripe.subscriptions.create({ items: body.items });
|
|
441
|
+
}
|
|
442
|
+
`, STRIPE_WRITE_SIGNALS);
|
|
443
|
+
const findings = run(makeIndex([route]), makeConfig());
|
|
444
|
+
expect(findings[0].confidence).toBe("med");
|
|
445
|
+
expect(findings[0].severity).toBe("med");
|
|
446
|
+
});
|
|
447
|
+
});
|
|
448
|
+
});
|
|
449
|
+
//# sourceMappingURL=input-validation-missing.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-validation-missing.test.js","sourceRoot":"","sources":["../../src/rules/input-validation-missing.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { NextIndex } from "../next/types.js";
|
|
2
|
+
import type { Finding, ProdcheckConfig } from "../engine/types.js";
|
|
3
|
+
export declare const RULE_ID = "RATE-LIMIT-MISSING";
|
|
4
|
+
export declare function run(index: NextIndex, config: ProdcheckConfig): Finding[];
|
|
5
|
+
//# sourceMappingURL=rate-limit-missing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit-missing.d.ts","sourceRoot":"","sources":["../../src/rules/rate-limit-missing.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,kBAAkB,CAAC;AAC7D,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAKnE,eAAO,MAAM,OAAO,uBAAuB,CAAC;AAkD5C,wBAAgB,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,OAAO,EAAE,CA8HxE"}
|