@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,316 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { isAllowlisted } from "../util/paths.js";
|
|
4
|
+
import { detectOutboundFetcher } from "../util/outbound-fetch.js";
|
|
5
|
+
export const RULE_ID = "RATE-LIMIT-MISSING";
|
|
6
|
+
/**
|
|
7
|
+
* Paths commonly excluded from rate limiting.
|
|
8
|
+
* Health checks, static assets, internal probes, cron/task routes.
|
|
9
|
+
*/
|
|
10
|
+
const EXEMPT_PATH_PATTERNS = [
|
|
11
|
+
/\/health$/,
|
|
12
|
+
/\/ping$/,
|
|
13
|
+
/\/ready$/,
|
|
14
|
+
/\/live$/,
|
|
15
|
+
/\/_next\//,
|
|
16
|
+
/\/cron\//, // Cron routes are server-to-server
|
|
17
|
+
/\/tasks\//, // Task/job routes are server-to-server
|
|
18
|
+
];
|
|
19
|
+
/**
|
|
20
|
+
* Webhook path patterns — rate limiting is inappropriate for inbound webhooks.
|
|
21
|
+
* Matches any path containing "webhook" (e.g., /stripe-webhook, /webhooks/stripe).
|
|
22
|
+
*/
|
|
23
|
+
const WEBHOOK_PATH_PATTERNS = [
|
|
24
|
+
/webhook/i,
|
|
25
|
+
];
|
|
26
|
+
/**
|
|
27
|
+
* Login/signin paths — prime brute-force targets.
|
|
28
|
+
* Missing rate limiting on these is always critical.
|
|
29
|
+
*/
|
|
30
|
+
const LOGIN_PATH_PATTERNS = [
|
|
31
|
+
/\/login(\/|$)/i,
|
|
32
|
+
/\/signin(\/|$)/i,
|
|
33
|
+
/\/sign-in(\/|$)/i,
|
|
34
|
+
/\/auth\/login(\/|$)/i,
|
|
35
|
+
/\/auth\/signin(\/|$)/i,
|
|
36
|
+
];
|
|
37
|
+
/**
|
|
38
|
+
* Framework-managed routes where rate limiting is handled by the framework
|
|
39
|
+
* or is inappropriate (auth protocol flows, external callbacks, OG images).
|
|
40
|
+
*/
|
|
41
|
+
const FRAMEWORK_MANAGED_PATTERNS = [
|
|
42
|
+
/\/auth\/\[\.{3}[^\]]*\]/, // NextAuth catch-all: auth/[...nextauth], auth/[...params]
|
|
43
|
+
/\/callback\//, // Inbound callbacks from external services (OAuth, Stripe, Slack)
|
|
44
|
+
/\/callback$/, // Terminal callback path
|
|
45
|
+
/\/oauth\//, // OAuth protocol endpoints (token, userinfo, authorize)
|
|
46
|
+
/\/saml\//, // SAML SSO endpoints
|
|
47
|
+
/\/og\//, // OG image generation routes (stateless, CDN-cached)
|
|
48
|
+
/\/og$/, // Terminal OG path
|
|
49
|
+
];
|
|
50
|
+
export function run(index, config) {
|
|
51
|
+
const findings = [];
|
|
52
|
+
const maxSeverity = config.rules[RULE_ID]?.severity ?? "critical";
|
|
53
|
+
for (const route of index.routes.all) {
|
|
54
|
+
// Only check API routes
|
|
55
|
+
if (!route.isApi)
|
|
56
|
+
continue;
|
|
57
|
+
// Skip exempt paths and user allowlisted paths
|
|
58
|
+
if (isExemptPath(route.pathname))
|
|
59
|
+
continue;
|
|
60
|
+
if (isAllowlisted(route.file, config.hints.rateLimit.allowlistPaths))
|
|
61
|
+
continue;
|
|
62
|
+
// Skip tRPC proxy routes — rate limiting is checked at the procedure level
|
|
63
|
+
if (index.trpc.detected && route.file === index.trpc.proxyFile)
|
|
64
|
+
continue;
|
|
65
|
+
// Skip framework-managed routes (NextAuth, OAuth, SAML, callbacks, OG images)
|
|
66
|
+
if (isFrameworkManaged(route.pathname))
|
|
67
|
+
continue;
|
|
68
|
+
const result = checkRoute(route, index, config);
|
|
69
|
+
if (result) {
|
|
70
|
+
// Severity bumps for high-value targets
|
|
71
|
+
let severity = result.severity;
|
|
72
|
+
let { confidence, confidenceRationale } = result;
|
|
73
|
+
if (isLoginPath(route.pathname)) {
|
|
74
|
+
severity = "critical";
|
|
75
|
+
confidence = "high";
|
|
76
|
+
confidenceRationale = "High: login/signin endpoint without rate limiting — prime brute-force target";
|
|
77
|
+
result.evidence.push("login/signin endpoint — brute-force risk");
|
|
78
|
+
}
|
|
79
|
+
else if (hasFormDataUpload(route, index)) {
|
|
80
|
+
severity = "critical";
|
|
81
|
+
confidence = "high";
|
|
82
|
+
confidenceRationale = "High: public file upload endpoint without rate limiting — storage abuse risk";
|
|
83
|
+
result.evidence.push("public formData upload — storage abuse risk");
|
|
84
|
+
}
|
|
85
|
+
// public-intent: severity floor at HIGH + SSRF escalation
|
|
86
|
+
let tags = ["rate-limit", "server"];
|
|
87
|
+
if (route.publicIntent) {
|
|
88
|
+
result.evidence.push(`public-intent: "${route.publicIntent.reason}"`);
|
|
89
|
+
tags = ["rate-limit", "server", "public-intent"];
|
|
90
|
+
// Floor severity at HIGH — public by design means RL is mandatory
|
|
91
|
+
if (SEVERITY_RANK[severity] < SEVERITY_RANK["high"]) {
|
|
92
|
+
severity = "high";
|
|
93
|
+
confidence = "high";
|
|
94
|
+
confidenceRationale = "High: developer declared endpoint intentionally public (prodcheck:public-intent) — rate limiting is mandatory";
|
|
95
|
+
}
|
|
96
|
+
// SSRF escalation: public endpoint with outbound fetch = critical
|
|
97
|
+
const src = readSource(index.rootDir, route.file);
|
|
98
|
+
if (src) {
|
|
99
|
+
const fetcher = detectOutboundFetcher(src);
|
|
100
|
+
if (fetcher.isRisky) {
|
|
101
|
+
severity = "critical";
|
|
102
|
+
confidence = "high";
|
|
103
|
+
confidenceRationale = "Critical: public-intent endpoint performs outbound fetch with user-influenced URL — SSRF surface";
|
|
104
|
+
result.evidence.push(...fetcher.evidence);
|
|
105
|
+
tags = ["rate-limit", "server", "public-intent", "outbound-fetch", "ssrf-surface"];
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
findings.push({
|
|
110
|
+
ruleId: RULE_ID,
|
|
111
|
+
severity: capSeverity(severity, maxSeverity),
|
|
112
|
+
confidence,
|
|
113
|
+
message: route.publicIntent
|
|
114
|
+
? `Intentionally public API route has no recognized rate limiting`
|
|
115
|
+
: `Public API route has no recognized rate limiting`,
|
|
116
|
+
file: route.file,
|
|
117
|
+
line: result.line,
|
|
118
|
+
snippet: result.snippet,
|
|
119
|
+
evidence: result.evidence,
|
|
120
|
+
confidenceRationale,
|
|
121
|
+
remediation: route.publicIntent
|
|
122
|
+
? [
|
|
123
|
+
"Rate limiting is mandatory for endpoints declared as public-intent",
|
|
124
|
+
"Add rate limiting middleware or wrapper to this route",
|
|
125
|
+
"If using @upstash/ratelimit, wrap the handler with a rate limit check",
|
|
126
|
+
"If rate limiting is at the edge (Cloudflare, Vercel), add a waiver with reason",
|
|
127
|
+
]
|
|
128
|
+
: [
|
|
129
|
+
"Add rate limiting middleware or wrapper to this route",
|
|
130
|
+
"If using @upstash/ratelimit, wrap the handler with a rate limit check",
|
|
131
|
+
"If rate limiting is handled at the edge (Cloudflare, Vercel), add a waiver with reason",
|
|
132
|
+
"Add custom wrapper names to hints.rateLimit.wrappers in config",
|
|
133
|
+
],
|
|
134
|
+
tags,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// Check tRPC mutation procedures (both public and protected)
|
|
139
|
+
for (const proc of index.trpc.mutationProcedures) {
|
|
140
|
+
if (isAllowlisted(proc.file, config.hints.rateLimit.allowlistPaths))
|
|
141
|
+
continue;
|
|
142
|
+
// Check if the procedure's file has rate limit calls
|
|
143
|
+
const src = readSource(index.rootDir, proc.file);
|
|
144
|
+
if (src && hasRateLimitCall(src, config.hints.rateLimit.wrappers))
|
|
145
|
+
continue;
|
|
146
|
+
const isProtected = proc.procedureType === "protected";
|
|
147
|
+
findings.push({
|
|
148
|
+
ruleId: RULE_ID,
|
|
149
|
+
severity: capSeverity(isProtected ? "high" : "med", maxSeverity),
|
|
150
|
+
confidence: "med",
|
|
151
|
+
message: `tRPC ${proc.procedureType} mutation "${proc.name}" has no recognized rate limiting`,
|
|
152
|
+
file: proc.file,
|
|
153
|
+
line: proc.line,
|
|
154
|
+
evidence: [
|
|
155
|
+
`${proc.procedureType}Procedure.mutation() without rate limit wrapper`,
|
|
156
|
+
...(isProtected ? ["authenticated but still susceptible to abuse (cost, spam)"] : []),
|
|
157
|
+
],
|
|
158
|
+
confidenceRationale: isProtected
|
|
159
|
+
? "Medium: authenticated mutation still needs rate limiting to prevent abuse"
|
|
160
|
+
: "Medium: tRPC rate limiting may be handled at middleware or procedure level (not detected)",
|
|
161
|
+
remediation: [
|
|
162
|
+
"Add rate limiting middleware to the procedure chain",
|
|
163
|
+
"If rate limiting is handled at the tRPC middleware level, add a waiver with reason",
|
|
164
|
+
"If rate limiting is at the edge (Cloudflare, Vercel), add a waiver",
|
|
165
|
+
],
|
|
166
|
+
tags: ["rate-limit", "trpc"],
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
return findings;
|
|
170
|
+
}
|
|
171
|
+
const SEVERITY_RANK = { critical: 4, high: 3, med: 2, low: 1 };
|
|
172
|
+
function capSeverity(computed, max) {
|
|
173
|
+
const maxRank = SEVERITY_RANK[max] ?? 4;
|
|
174
|
+
const computedRank = SEVERITY_RANK[computed] ?? 2;
|
|
175
|
+
return computedRank > maxRank ? max : computed;
|
|
176
|
+
}
|
|
177
|
+
function checkRoute(route, index, config) {
|
|
178
|
+
// Use ProtectionSummary if available (computed during index building)
|
|
179
|
+
if (route.protection) {
|
|
180
|
+
if (route.protection.rateLimit.satisfied)
|
|
181
|
+
return null;
|
|
182
|
+
// If wrapper introspection deferred this to WRAPPER-UNRECOGNIZED, don't emit per-route finding
|
|
183
|
+
if (route.protection.rateLimit.unverifiedWrappers.length > 0)
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
const src = readSource(index.rootDir, route.file);
|
|
187
|
+
if (!src)
|
|
188
|
+
return null;
|
|
189
|
+
// Routes with webhook signature verification don't need rate limiting
|
|
190
|
+
if (hasWebhookSignatureAuth(src))
|
|
191
|
+
return null;
|
|
192
|
+
if (isWebhookPath(route.pathname))
|
|
193
|
+
return null;
|
|
194
|
+
// Routes with cron key auth are server-to-server (no rate limiting needed)
|
|
195
|
+
if (hasCronKeyAuth(src))
|
|
196
|
+
return null;
|
|
197
|
+
// Only suppress RL findings when auth is strongly enforced (proven throw/return on failure).
|
|
198
|
+
// Weak/optional auth (satisfied but not enforced) is treated as unauthenticated for RL purposes.
|
|
199
|
+
const authStrong = route.protection?.auth.satisfied && route.protection?.auth.enforced;
|
|
200
|
+
if (authStrong)
|
|
201
|
+
return null;
|
|
202
|
+
const evidence = [];
|
|
203
|
+
let severity;
|
|
204
|
+
let confidence;
|
|
205
|
+
let confidenceRationale;
|
|
206
|
+
const isMutation = route.signals.hasMutationEvidence || route.signals.hasDbWriteEvidence;
|
|
207
|
+
if (isMutation) {
|
|
208
|
+
severity = "critical";
|
|
209
|
+
confidence = "high";
|
|
210
|
+
confidenceRationale = "High: public mutation route without rate limiting (higher abuse risk)";
|
|
211
|
+
evidence.push("route performs mutations (higher abuse risk)");
|
|
212
|
+
evidence.push(...route.signals.mutationDetails);
|
|
213
|
+
}
|
|
214
|
+
else if (hasBodyParsing(src)) {
|
|
215
|
+
severity = "high";
|
|
216
|
+
confidence = "high";
|
|
217
|
+
confidenceRationale = "High: public route reads request body without rate limiting";
|
|
218
|
+
evidence.push("route reads request body");
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
severity = "med";
|
|
222
|
+
confidence = "med";
|
|
223
|
+
confidenceRationale = "Medium: public API route without rate limiting (GET-only, lower risk)";
|
|
224
|
+
evidence.push("public API route without rate limiting");
|
|
225
|
+
}
|
|
226
|
+
return { severity, confidence, confidenceRationale, evidence };
|
|
227
|
+
}
|
|
228
|
+
function hasRateLimitCall(src, wrappers) {
|
|
229
|
+
for (const wrapper of wrappers) {
|
|
230
|
+
const pattern = new RegExp(`\\b${escapeRegex(wrapper)}\\s*[.(]`, "m");
|
|
231
|
+
if (pattern.test(src))
|
|
232
|
+
return true;
|
|
233
|
+
}
|
|
234
|
+
// Also check for common rate limit import patterns
|
|
235
|
+
if (/@upstash\/ratelimit/.test(src))
|
|
236
|
+
return true;
|
|
237
|
+
if (/rate-limiter-flexible/.test(src))
|
|
238
|
+
return true;
|
|
239
|
+
if (/@arcjet\/next/.test(src))
|
|
240
|
+
return true;
|
|
241
|
+
if (/@unkey\/ratelimit/.test(src))
|
|
242
|
+
return true;
|
|
243
|
+
// Upstash-style: ratelimit.limit(identifier) in route source
|
|
244
|
+
if (/(?:ratelimit|rateLimit|rl|limiter|rateLimiter)\.limit\s*\(/i.test(src))
|
|
245
|
+
return true;
|
|
246
|
+
// General pattern: any function name containing "ratelimit" or "rate_limit"
|
|
247
|
+
// Catches: ratelimit(), ratelimitOrThrow(), checkRateLimit(), rateLimitMiddleware(), etc.
|
|
248
|
+
if (/\b\w*(?:rateLimit|ratelimit|rate_limit)\w*\s*\(/i.test(src))
|
|
249
|
+
return true;
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Webhook signature verification — these routes don't need rate limiting.
|
|
254
|
+
*/
|
|
255
|
+
function hasWebhookSignatureAuth(src) {
|
|
256
|
+
if (/stripe\.webhooks\.constructEvent\s*\(/m.test(src))
|
|
257
|
+
return true;
|
|
258
|
+
if (/verifyQstashSignature\s*\(/m.test(src))
|
|
259
|
+
return true;
|
|
260
|
+
if (/createHmac\s*\(/.test(src) && /signature/i.test(src))
|
|
261
|
+
return true;
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Cron routes protected by API key are server-to-server.
|
|
266
|
+
*/
|
|
267
|
+
function hasCronKeyAuth(src) {
|
|
268
|
+
if (/process\.env\.CRON_(?:API_KEY|SECRET)/m.test(src))
|
|
269
|
+
return true;
|
|
270
|
+
if (/verifyVercelSignature\s*\(/m.test(src))
|
|
271
|
+
return true;
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
function isWebhookPath(pathname) {
|
|
275
|
+
if (!pathname)
|
|
276
|
+
return false;
|
|
277
|
+
return WEBHOOK_PATH_PATTERNS.some((p) => p.test(pathname));
|
|
278
|
+
}
|
|
279
|
+
function isFrameworkManaged(pathname) {
|
|
280
|
+
if (!pathname)
|
|
281
|
+
return false;
|
|
282
|
+
return FRAMEWORK_MANAGED_PATTERNS.some((p) => p.test(pathname));
|
|
283
|
+
}
|
|
284
|
+
function hasBodyParsing(src) {
|
|
285
|
+
return /request\.json\s*\(|request\.formData\s*\(|request\.body\b|req\.body/.test(src);
|
|
286
|
+
}
|
|
287
|
+
function isExemptPath(pathname) {
|
|
288
|
+
if (!pathname)
|
|
289
|
+
return false;
|
|
290
|
+
return EXEMPT_PATH_PATTERNS.some((p) => p.test(pathname));
|
|
291
|
+
}
|
|
292
|
+
function isLoginPath(pathname) {
|
|
293
|
+
if (!pathname)
|
|
294
|
+
return false;
|
|
295
|
+
return LOGIN_PATH_PATTERNS.some((p) => p.test(pathname));
|
|
296
|
+
}
|
|
297
|
+
function hasFormDataUpload(route, index) {
|
|
298
|
+
const src = readSource(index.rootDir, route.file);
|
|
299
|
+
if (!src)
|
|
300
|
+
return false;
|
|
301
|
+
// FormData upload or raw body stream to blob/object storage
|
|
302
|
+
return /request\.formData\s*\(|req\.formData\s*\(/.test(src)
|
|
303
|
+
|| (/request\.body\b/.test(src) && /\bput\s*\(/.test(src));
|
|
304
|
+
}
|
|
305
|
+
function readSource(rootDir, file) {
|
|
306
|
+
try {
|
|
307
|
+
return readFileSync(path.join(rootDir, file), "utf8");
|
|
308
|
+
}
|
|
309
|
+
catch {
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
function escapeRegex(str) {
|
|
314
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
315
|
+
}
|
|
316
|
+
//# sourceMappingURL=rate-limit-missing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit-missing.js","sourceRoot":"","sources":["../../src/rules/rate-limit-missing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit-missing.test.d.ts","sourceRoot":"","sources":["../../src/rules/rate-limit-missing.test.ts"],"names":[],"mappings":""}
|