@fourteensystems/shipguard 0.2.4 → 0.2.5

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.
@@ -1 +1 @@
1
- {"version":3,"file":"auth-boundary-missing.d.ts","sourceRoot":"","sources":["../../src/rules/auth-boundary-missing.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAA+B,MAAM,kBAAkB,CAAC;AAC/E,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAInE,eAAO,MAAM,OAAO,0BAA0B,CAAC;AAc/C,wBAAgB,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,OAAO,EAAE,CA8FxE"}
1
+ {"version":3,"file":"auth-boundary-missing.d.ts","sourceRoot":"","sources":["../../src/rules/auth-boundary-missing.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAA+B,MAAM,kBAAkB,CAAC;AAC/E,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAInE,eAAO,MAAM,OAAO,0BAA0B,CAAC;AAc/C,wBAAgB,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,GAAG,OAAO,EAAE,CA4GxE"}
@@ -22,31 +22,45 @@ export function run(index, config) {
22
22
  continue;
23
23
  const result = checkRoute(route, index, config);
24
24
  if (result) {
25
- const isWebhook = /webhook/i.test(route.pathname ?? route.file);
25
+ const pathname = route.pathname ?? route.file;
26
+ const isWebhook = /webhook/i.test(pathname);
27
+ const isCallback = isCallbackPath(pathname);
26
28
  findings.push({
27
29
  ruleId: RULE_ID,
28
30
  severity: severityFromConfidence(result.confidence, maxSeverity),
29
31
  confidence: result.confidence,
30
- message: isWebhook
31
- ? `Webhook endpoint processes payloads without signature verification`
32
- : `Route handler performs mutations without a recognized auth boundary`,
32
+ message: isCallback
33
+ ? `Callback endpoint performs mutations without verified framework validation`
34
+ : isWebhook
35
+ ? `Webhook endpoint processes payloads without signature verification`
36
+ : `Route handler performs mutations without a recognized auth boundary`,
33
37
  file: route.file,
34
38
  line: result.line,
35
39
  snippet: result.snippet,
36
40
  evidence: result.evidence,
37
41
  confidenceRationale: result.confidenceRationale,
38
- remediation: isWebhook
42
+ remediation: isCallback
39
43
  ? [
40
- "Verify the provider's webhook signature before processing the payload",
41
- "Examples: Stripe `constructEvent()`, GitHub HMAC, Google Pub/Sub JWT, Slack `verifyRequest()`",
42
- "Use `crypto.timingSafeEqual()` for HMAC comparisons to prevent timing attacks",
44
+ "Callback endpoints are typically public but should rely on framework validation (state/PKCE)",
45
+ "If using NextAuth/Auth.js, Clerk, or similar the framework handles this; add it to hints.auth.functions",
46
+ "Shipguard couldn't verify that framework validation is in place",
43
47
  ]
44
- : [
45
- "Add an auth check at the top of the handler (e.g., `const session = await auth()`)",
46
- "Ensure middleware.ts protects this route segment",
47
- "If using a custom auth wrapper, add it to hints.auth.functions in shipguard.config.json",
48
- ],
49
- tags: isWebhook ? ["auth", "webhook", "server"] : ["auth", "server"],
48
+ : isWebhook
49
+ ? [
50
+ "Verify the provider's webhook signature before processing the payload",
51
+ "Examples: Stripe `constructEvent()`, GitHub HMAC, Google Pub/Sub JWT, Slack `verifyRequest()`",
52
+ "Use `crypto.timingSafeEqual()` for HMAC comparisons to prevent timing attacks",
53
+ ]
54
+ : [
55
+ "Add an auth check at the top of the handler (e.g., `const session = await auth()`)",
56
+ "Ensure middleware.ts protects this route segment",
57
+ "If using a custom auth wrapper, add it to hints.auth.functions in shipguard.config.json",
58
+ ],
59
+ tags: isCallback
60
+ ? ["auth", "callback", "server"]
61
+ : isWebhook
62
+ ? ["auth", "webhook", "server"]
63
+ : ["auth", "server"],
50
64
  });
51
65
  }
52
66
  }
@@ -134,6 +148,13 @@ function checkRoute(route, index, config) {
134
148
  confidenceRationale = "Medium: mutation evidence present but possible custom auth wrapper detected (not in hints)";
135
149
  evidence.push("possible custom auth wrapper detected (not in hints)");
136
150
  }
151
+ // Downgrade callback/OAuth/OIDC paths — public by protocol design, but still flag them
152
+ const pathname = route.pathname ?? route.file;
153
+ if (isCallbackPath(pathname)) {
154
+ confidence = "med";
155
+ confidenceRationale = "Medium: callback/OAuth/OIDC endpoint — typically public by protocol design";
156
+ evidence.push("callback/OAuth/OIDC path — typically relies on framework state/PKCE validation");
157
+ }
137
158
  // Find the line of the first mutation evidence for precise reporting
138
159
  const line = findFirstMutationLine(src, route.signals);
139
160
  return { confidence, confidenceRationale, line, evidence };
@@ -193,8 +214,188 @@ function hasBuiltInAuthPattern(src) {
193
214
  return true;
194
215
  if (/\.auth\.getSession\s*\(/.test(src))
195
216
  return true;
217
+ // --- Framework wrappers with built-in request signing ---
218
+ // Upstash Workflow serve() — verifies request signatures automatically
219
+ if (hasFrameworkServe(src, "@upstash/workflow"))
220
+ return true;
221
+ // Inngest serve() — verifies signing key on incoming requests
222
+ if (hasFrameworkServe(src, "inngest"))
223
+ return true;
224
+ // --- Webhook verification libraries (import + call) ---
225
+ // Svix webhook verification (used by Clerk, etc.)
226
+ if (hasImportAndCall(src, "svix", /\.verify\s*\(/))
227
+ return true;
228
+ // Octokit/GitHub webhook verification
229
+ if (hasImportAndCall(src, "@octokit/webhooks", /\.verify\s*\(/))
230
+ return true;
231
+ // --- Contextual webhook auth patterns ---
232
+ // timingSafeEqual used with request-derived data + early 401/403
233
+ if (hasWebhookTokenVerification(src))
234
+ return true;
235
+ // --- JWT verification (jose / jsonwebtoken) ---
236
+ // jose: jwtVerify() with token from headers/cookies + early deny
237
+ if (hasImportAndCall(src, "jose", /jwtVerify\s*\(/))
238
+ return true;
239
+ // jsonwebtoken: jwt.verify() / verify() with token from headers/cookies
240
+ if (hasImportAndCall(src, "jsonwebtoken", /\.verify\s*\(/))
241
+ return true;
242
+ // --- DB-backed API token lookup + early deny ---
243
+ if (hasDbTokenLookup(src))
244
+ return true;
245
+ // --- Auth-guard return: header/token/secret check → early 401/403 before mutation ---
246
+ if (hasAuthGuardReturn(src))
247
+ return true;
248
+ return false;
249
+ }
250
+ /**
251
+ * Detect framework `serve()` wrappers that have built-in request signing.
252
+ * Checks both the import source and the serve() call in the source.
253
+ */
254
+ function hasFrameworkServe(src, packagePrefix) {
255
+ const importPattern = new RegExp(`from\\s+["']${escapeRegex(packagePrefix)}[^"']*["']`);
256
+ if (!importPattern.test(src))
257
+ return false;
258
+ return /\bserve\s*[<(]/.test(src);
259
+ }
260
+ /**
261
+ * Detect a known verification library by import source + method call.
262
+ */
263
+ function hasImportAndCall(src, packageName, callPattern) {
264
+ const importPattern = new RegExp(`from\\s+["']${escapeRegex(packageName)}[^"']*["']`);
265
+ if (!importPattern.test(src))
266
+ return false;
267
+ return callPattern.test(src);
268
+ }
269
+ /**
270
+ * Detect webhook token verification: timingSafeEqual used with
271
+ * request-derived data (headers/params/body) and early 401/403 on mismatch.
272
+ *
273
+ * NOT a blanket "any timingSafeEqual = auth" — requires:
274
+ * 1. timingSafeEqual call present
275
+ * 2. Reads from request (headers, searchParams, or body)
276
+ * 3. Returns 401 or 403 on failure
277
+ */
278
+ function hasWebhookTokenVerification(src) {
279
+ if (!/timingSafeEqual\s*\(/.test(src))
280
+ return false;
281
+ const readsRequest = /headers\.get\s*\(/.test(src)
282
+ || /searchParams\.get\s*\(/.test(src)
283
+ || /request\.json\s*\(/.test(src)
284
+ || /req\.json\s*\(/.test(src);
285
+ if (!readsRequest)
286
+ return false;
287
+ return /status:\s*40[13]\b/.test(src) || /\(\s*40[13]\s*\)/.test(src);
288
+ }
289
+ /**
290
+ * Detect DB-backed API token lookup with early deny.
291
+ *
292
+ * Pattern: reads token from header → looks it up in DB → returns 401/403 if missing.
293
+ * Common in B2B SaaS for API key authentication.
294
+ *
295
+ * Requires all three:
296
+ * 1. Reads from request headers
297
+ * 2. DB lookup on a token/key-like table (prisma.apiToken, prisma.apiKey, etc.)
298
+ * 3. Returns 401 or 403
299
+ */
300
+ function hasDbTokenLookup(src) {
301
+ if (!/headers\.get\s*\(/.test(src))
302
+ return false;
303
+ const hasTokenLookup = /\.(apiToken|apiKey|token|accessToken|api_key|access_token)\.(findUnique|findFirst|findMany)\s*\(/i.test(src);
304
+ if (!hasTokenLookup)
305
+ return false;
306
+ return /status:\s*40[13]\b/.test(src) || /\(\s*40[13]\s*\)/.test(src);
307
+ }
308
+ /**
309
+ * Detect auth-guard return patterns: an early 401/403 return whose guarding
310
+ * condition references an auth signal, occurring BEFORE mutation evidence.
311
+ *
312
+ * We require ALL of:
313
+ * 1. A return/throw producing 401 or 403
314
+ * 2. The surrounding context references an auth-related signal
315
+ * 3. The guard occurs before the first mutation evidence in the file
316
+ *
317
+ * Auth signals (the condition must reference at least one):
318
+ * - headers.get(...) with auth-related header names
319
+ * - Variables named token, apiKey, signature, secret, session, user, auth
320
+ * - Comparison against process.env.* or config values
321
+ *
322
+ * This intentionally does NOT match:
323
+ * - Feature flag checks (if (!enabled) return 403)
324
+ * - Plan gating (if (!isPro) return 403)
325
+ * - CSRF/bot checks without auth signals
326
+ * - 401/403 returns AFTER mutation code (error handling, not guards)
327
+ */
328
+ function hasAuthGuardReturn(src) {
329
+ // Must have a 401 or 403 status somewhere
330
+ if (!/status:\s*40[13]\b/.test(src) && !/\(\s*40[13]\s*\)/.test(src))
331
+ return false;
332
+ const lines = src.split("\n");
333
+ // Find the first mutation evidence line
334
+ const firstMutationLine = findFirstMutationLineIndex(lines);
335
+ // Find lines with 401/403 returns and check nearby context for auth signals
336
+ for (let i = 0; i < lines.length; i++) {
337
+ const line = lines[i];
338
+ if (!/40[13]/.test(line))
339
+ continue;
340
+ if (!/status|Response|NextResponse|return|throw/i.test(line))
341
+ continue;
342
+ // Guard must occur before mutation evidence (or if no mutation found, accept it)
343
+ if (firstMutationLine !== undefined && i >= firstMutationLine)
344
+ continue;
345
+ // Look at the surrounding context (up to 10 lines before the 401/403)
346
+ const contextStart = Math.max(0, i - 10);
347
+ const context = lines.slice(contextStart, i + 1).join("\n");
348
+ if (hasAuthSignalInContext(context))
349
+ return true;
350
+ }
196
351
  return false;
197
352
  }
353
+ /** Find the 0-based line index of the first mutation evidence in source lines. */
354
+ function findFirstMutationLineIndex(lines) {
355
+ for (let i = 0; i < lines.length; i++) {
356
+ if (/\.(create|update|delete|upsert|createMany|updateMany|deleteMany)\s*\(/.test(lines[i])) {
357
+ return i;
358
+ }
359
+ if (/stripe\.\w+\.(create|update|del)\s*\(/.test(lines[i])) {
360
+ return i;
361
+ }
362
+ }
363
+ return undefined;
364
+ }
365
+ /**
366
+ * Auth signals that distinguish real auth guards from feature flags / plan gating.
367
+ */
368
+ const AUTH_SIGNAL_PATTERNS = [
369
+ // Header reads with auth-related names
370
+ /headers\.get\s*\(\s*["'](?:authorization|x-api-key|x-webhook-secret|x-signature|x-hub-signature)/i,
371
+ // Any custom header read + secret/token/key comparison
372
+ /headers\.get\s*\([^)]+\)[\s\S]{0,100}(?:secret|token|key|signature)\b/i,
373
+ // Variable names that imply auth context
374
+ /\b(?:const|let|var)\s+(?:token|apiKey|api_key|signature|webhookSecret|webhook_secret|headerValue)\b/i,
375
+ // Comparison against env vars (secret/key/token)
376
+ /process\.env\.\w*(?:SECRET|TOKEN|KEY|API_KEY|WEBHOOK)\w*/i,
377
+ // Authorization / Bearer token patterns
378
+ /\bauthorization\b/i,
379
+ /\bbearer\b/i,
380
+ // Known verification function names in the condition
381
+ /\b(?:verify|validate|check)\w*(?:Token|Signature|Auth|Secret|Key)\s*\(/i,
382
+ ];
383
+ /**
384
+ * Check if a code context (a few lines around a 401/403 return)
385
+ * contains at least one auth signal, distinguishing it from
386
+ * feature-flag / plan-gating returns.
387
+ */
388
+ function hasAuthSignalInContext(context) {
389
+ return AUTH_SIGNAL_PATTERNS.some((pattern) => pattern.test(context));
390
+ }
391
+ /**
392
+ * Detect callback/OAuth/OIDC paths that are typically public by protocol design.
393
+ * These get downgraded (not allowlisted) — they should still rely on
394
+ * framework validation (state/PKCE) but are not auth-boundary issues.
395
+ */
396
+ function isCallbackPath(pathname) {
397
+ return /\/(callback|oauth|oidc)(\/|$)/i.test(pathname);
398
+ }
198
399
  function hasPossibleCustomAuth(src) {
199
400
  if (/\b(verify|check|require|validate|ensure|guard|protect)\w*(Token|Auth|Session|User|Access|Secret|Signature|Permission)\s*\(/i.test(src)) {
200
401
  return true;
@@ -1 +1 @@
1
- {"version":3,"file":"auth-boundary-missing.js","sourceRoot":"","sources":["../../src/rules/auth-boundary-missing.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth-boundary-missing.js","sourceRoot":"","sources":["../../src/rules/auth-boundary-missing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=auth-boundary-missing.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-boundary-missing.test.d.ts","sourceRoot":"","sources":["../../src/rules/auth-boundary-missing.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,468 @@
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 } from "./auth-boundary-missing.js";
5
+ /* ------------------------------------------------------------------ */
6
+ /* Helpers */
7
+ /* ------------------------------------------------------------------ */
8
+ const MUTATION_SIGNALS = {
9
+ hasMutationEvidence: true,
10
+ hasDbWriteEvidence: true,
11
+ hasStripeWriteEvidence: false,
12
+ mutationDetails: ["prisma.create"],
13
+ };
14
+ function protectionSummary(opts) {
15
+ return {
16
+ auth: {
17
+ satisfied: opts.authSatisfied ?? false,
18
+ enforced: false,
19
+ sources: opts.authSatisfied ? ["direct"] : [],
20
+ details: [],
21
+ unverifiedWrappers: opts.unverifiedWrappers ?? [],
22
+ },
23
+ rateLimit: {
24
+ satisfied: false,
25
+ enforced: false,
26
+ sources: [],
27
+ details: [],
28
+ unverifiedWrappers: [],
29
+ },
30
+ };
31
+ }
32
+ let tmpDir;
33
+ beforeEach(() => {
34
+ tmpDir = path.join("/tmp", `shipguard-auth-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, overrides = {}) {
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/") || pathname === "/api",
51
+ isPublic: true,
52
+ pathname,
53
+ signals: MUTATION_SIGNALS,
54
+ protection: protectionSummary({}),
55
+ ...overrides,
56
+ };
57
+ }
58
+ function makeIndex(routes) {
59
+ return {
60
+ version: 1,
61
+ framework: "next-app-router",
62
+ rootDir: tmpDir,
63
+ deps: {
64
+ hasNextAuth: false, hasClerk: false, hasSupabase: false,
65
+ hasKinde: false, hasWorkOS: false, hasBetterAuth: false,
66
+ hasLucia: false, hasAuth0: false, hasIronSession: false,
67
+ hasFirebaseAuth: false, hasUpstashRatelimit: false, hasArcjet: false,
68
+ hasUnkey: false, hasPrisma: false, hasDrizzle: false, hasTrpc: false,
69
+ },
70
+ hints: {
71
+ auth: { functions: ["auth", "getServerSession"], middlewareFiles: [], allowlistPaths: [] },
72
+ rateLimit: { wrappers: ["rateLimit"], allowlistPaths: [] },
73
+ tenancy: { orgFieldNames: [] },
74
+ },
75
+ middleware: { authLikely: false, rateLimitLikely: false, matcherPatterns: [] },
76
+ wrappers: { wrappers: new Map() },
77
+ routes: { all: routes, mutationRoutes: routes },
78
+ serverActions: { all: [], mutationActions: [] },
79
+ trpc: { detected: false, procedures: [], mutationProcedures: [] },
80
+ };
81
+ }
82
+ function makeConfig(overrides = {}) {
83
+ return {
84
+ framework: "next-app-router",
85
+ include: ["app/**"],
86
+ exclude: [],
87
+ ci: { failOn: "critical", minConfidence: "high", minScore: 70, maxNewCritical: 0 },
88
+ scoring: { start: 100, penalties: { critical: 25, high: 10, med: 3, low: 1 } },
89
+ hints: {
90
+ auth: { functions: ["auth", "getServerSession"], middlewareFiles: [], allowlistPaths: [] },
91
+ rateLimit: { wrappers: ["rateLimit"], allowlistPaths: [] },
92
+ tenancy: { orgFieldNames: [] },
93
+ },
94
+ rules: { "AUTH-BOUNDARY-MISSING": { severity: "critical" } },
95
+ waiversFile: "shipguard.waivers.json",
96
+ ...overrides,
97
+ };
98
+ }
99
+ const config = makeConfig();
100
+ /* ------------------------------------------------------------------ */
101
+ /* 1. Upstash Workflow serve() — should suppress finding */
102
+ /* ------------------------------------------------------------------ */
103
+ describe("Upstash Workflow serve() recognition", () => {
104
+ it("suppresses finding for @upstash/workflow serve()", () => {
105
+ const route = createRoute("app/api/workflows/process/route.ts", `
106
+ import { serve } from "@upstash/workflow/nextjs";
107
+ import { MemoryExtractionExecutor } from "@/server/services/memory";
108
+
109
+ export const { POST } = serve(async (context) => {
110
+ const executor = await MemoryExtractionExecutor.create();
111
+ await prisma.memory.create({ data: { userId: "test" } });
112
+ return { done: true };
113
+ });
114
+ `);
115
+ expect(run(makeIndex([route]), config)).toHaveLength(0);
116
+ });
117
+ it("suppresses finding for serve with generic type param", () => {
118
+ const route = createRoute("app/api/workflows/extract/route.ts", `
119
+ import { serve } from "@upstash/workflow/nextjs";
120
+
121
+ export const { POST } = serve<PayloadInput>(async (context) => {
122
+ await prisma.topic.create({ data: context.requestPayload });
123
+ });
124
+ `);
125
+ expect(run(makeIndex([route]), config)).toHaveLength(0);
126
+ });
127
+ it("does NOT suppress for serve() from unknown package", () => {
128
+ const route = createRoute("app/api/unknown/route.ts", `
129
+ import { serve } from "some-other-package";
130
+
131
+ export const { POST } = serve(async (context) => {
132
+ await prisma.user.create({ data: { name: "test" } });
133
+ });
134
+ `);
135
+ expect(run(makeIndex([route]), config)).toHaveLength(1);
136
+ });
137
+ });
138
+ /* ------------------------------------------------------------------ */
139
+ /* 1b. Inngest serve() — should suppress finding */
140
+ /* ------------------------------------------------------------------ */
141
+ describe("Inngest serve() recognition", () => {
142
+ it("suppresses finding for inngest/next serve()", () => {
143
+ const route = createRoute("app/api/inngest/route.ts", `
144
+ import { serve } from "inngest/next";
145
+ import { inngest } from "@/inngest/client";
146
+
147
+ export const { GET, POST, PUT } = serve({ client: inngest, functions: [myFn] });
148
+ `);
149
+ // No mutation signals in this source, override to force mutation
150
+ const routeWithMutation = createRoute("app/api/inngest/route.ts", `
151
+ import { serve } from "inngest/next";
152
+ import { inngest } from "@/inngest/client";
153
+
154
+ export const { POST } = serve({ client: inngest, functions: [myFn] });
155
+ // hypothetical mutation
156
+ await prisma.job.create({ data: {} });
157
+ `);
158
+ expect(run(makeIndex([routeWithMutation]), config)).toHaveLength(0);
159
+ });
160
+ });
161
+ /* ------------------------------------------------------------------ */
162
+ /* 2. Svix webhook verification — should suppress finding */
163
+ /* ------------------------------------------------------------------ */
164
+ describe("Svix webhook verification", () => {
165
+ it("suppresses finding for svix Webhook.verify()", () => {
166
+ const route = createRoute("app/api/webhooks/clerk/route.ts", `
167
+ import { Webhook } from "svix";
168
+
169
+ export async function POST(req: Request) {
170
+ const body = await req.text();
171
+ const wh = new Webhook(process.env.CLERK_WEBHOOK_SECRET!);
172
+ const payload = wh.verify(body, Object.fromEntries(req.headers));
173
+ await prisma.user.create({ data: payload });
174
+ return Response.json({ ok: true });
175
+ }
176
+ `);
177
+ expect(run(makeIndex([route]), config)).toHaveLength(0);
178
+ });
179
+ });
180
+ /* ------------------------------------------------------------------ */
181
+ /* 3. timingSafeEqual — contextual webhook verification */
182
+ /* ------------------------------------------------------------------ */
183
+ describe("timingSafeEqual webhook verification", () => {
184
+ it("suppresses when timingSafeEqual + headers.get + 401", () => {
185
+ const route = createRoute("app/api/webhooks/video/route.ts", `
186
+ import { timingSafeEqual } from "node:crypto";
187
+
188
+ export const POST = async (req: Request) => {
189
+ const url = new URL(req.url);
190
+ const token = url.searchParams.get("token");
191
+ const expected = metadata?.webhookToken;
192
+ if (!expected || !token || !timingSafeEqual(Buffer.from(token), Buffer.from(expected))) {
193
+ return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
194
+ }
195
+ await prisma.asyncTask.update({ where: { id }, data: { status: "success" } });
196
+ return NextResponse.json({ success: true });
197
+ };
198
+ `);
199
+ expect(run(makeIndex([route]), config)).toHaveLength(0);
200
+ });
201
+ it("does NOT suppress timingSafeEqual without request-derived data", () => {
202
+ const route = createRoute("app/api/compare/route.ts", `
203
+ import { timingSafeEqual } from "node:crypto";
204
+
205
+ export const POST = async (req: Request) => {
206
+ // timingSafeEqual used for non-auth comparison
207
+ const match = timingSafeEqual(Buffer.from("a"), Buffer.from("b"));
208
+ await prisma.user.create({ data: { name: "test" } });
209
+ return Response.json({ match });
210
+ };
211
+ `);
212
+ expect(run(makeIndex([route]), config)).toHaveLength(1);
213
+ });
214
+ });
215
+ /* ------------------------------------------------------------------ */
216
+ /* 4. Auth-guard return detection (safe version) */
217
+ /* ------------------------------------------------------------------ */
218
+ describe("auth-guard return detection", () => {
219
+ it("suppresses for x-api-key header check + env comparison + 401 before mutation", () => {
220
+ const route = createRoute("app/api/internal/route.ts", `
221
+ export async function POST(req: Request) {
222
+ const apiKey = req.headers.get("x-api-key");
223
+ if (apiKey !== process.env.API_KEY) {
224
+ return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
225
+ }
226
+ await prisma.job.create({ data: { type: "sync" } });
227
+ return NextResponse.json({ ok: true });
228
+ }
229
+ `);
230
+ expect(run(makeIndex([route]), config)).toHaveLength(0);
231
+ });
232
+ it("suppresses for authorization header + Bearer token check + 403", () => {
233
+ const route = createRoute("app/api/protected/route.ts", `
234
+ export async function POST(req: Request) {
235
+ const authorization = req.headers.get("authorization");
236
+ if (!authorization?.startsWith("Bearer ")) {
237
+ return new Response("Forbidden", { status: 403 });
238
+ }
239
+ await prisma.user.update({ where: { id }, data: body });
240
+ return Response.json({ ok: true });
241
+ }
242
+ `);
243
+ expect(run(makeIndex([route]), config)).toHaveLength(0);
244
+ });
245
+ it("does NOT suppress for feature flag check + 403", () => {
246
+ const route = createRoute("app/api/gated/route.ts", `
247
+ export async function POST(req: Request) {
248
+ const enabled = await isFeatureEnabled("new-flow");
249
+ if (!enabled) {
250
+ return NextResponse.json({ error: "Not available" }, { status: 403 });
251
+ }
252
+ await prisma.user.create({ data: { name: "test" } });
253
+ return Response.json({ ok: true });
254
+ }
255
+ `);
256
+ expect(run(makeIndex([route]), config)).toHaveLength(1);
257
+ });
258
+ it("does NOT suppress for plan gating + 403", () => {
259
+ const route = createRoute("app/api/billing/route.ts", `
260
+ export async function POST(req: Request) {
261
+ const isPro = await checkPlan(userId);
262
+ if (!isPro) {
263
+ return NextResponse.json({ error: "Upgrade required" }, { status: 403 });
264
+ }
265
+ await prisma.subscription.create({ data: { userId } });
266
+ return Response.json({ ok: true });
267
+ }
268
+ `);
269
+ expect(run(makeIndex([route]), config)).toHaveLength(1);
270
+ });
271
+ it("does NOT suppress for 401/403 AFTER mutation (error handling, not guard)", () => {
272
+ const route = createRoute("app/api/late-check/route.ts", `
273
+ export async function POST(req: Request) {
274
+ await prisma.audit.create({ data: { action: "attempt" } });
275
+ const token = req.headers.get("authorization");
276
+ if (!token) {
277
+ return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
278
+ }
279
+ return Response.json({ ok: true });
280
+ }
281
+ `);
282
+ expect(run(makeIndex([route]), config)).toHaveLength(1);
283
+ });
284
+ it("suppresses for webhook header secret verification + 403", () => {
285
+ const route = createRoute("app/api/webhooks/memory/route.ts", `
286
+ export const POST = async (req: Request) => {
287
+ const { webhook } = parseConfig();
288
+ if (webhook.headers && Object.keys(webhook.headers).length > 0) {
289
+ for (const [key, value] of Object.entries(webhook.headers)) {
290
+ const headerValue = req.headers.get(key);
291
+ if (headerValue !== value) {
292
+ return NextResponse.json(
293
+ { error: "Unauthorized" },
294
+ { status: 403 },
295
+ );
296
+ }
297
+ }
298
+ }
299
+ const executor = await MemoryExtractionExecutor.create();
300
+ const result = await executor.runDirect(params);
301
+ return NextResponse.json({ result }, { status: 200 });
302
+ };
303
+ `);
304
+ expect(run(makeIndex([route]), config)).toHaveLength(0);
305
+ });
306
+ });
307
+ /* ------------------------------------------------------------------ */
308
+ /* 5. JWT verification (jose / jsonwebtoken) */
309
+ /* ------------------------------------------------------------------ */
310
+ describe("JWT verification", () => {
311
+ it("suppresses for jose jwtVerify()", () => {
312
+ const route = createRoute("app/api/secure/route.ts", `
313
+ import { jwtVerify } from "jose";
314
+
315
+ export async function POST(req: Request) {
316
+ const token = req.headers.get("authorization")?.split(" ")[1];
317
+ const { payload } = await jwtVerify(token, secret);
318
+ await prisma.action.create({ data: { userId: payload.sub } });
319
+ return Response.json({ ok: true });
320
+ }
321
+ `);
322
+ expect(run(makeIndex([route]), config)).toHaveLength(0);
323
+ });
324
+ it("suppresses for jsonwebtoken verify()", () => {
325
+ const route = createRoute("app/api/jwt/route.ts", `
326
+ import jwt from "jsonwebtoken";
327
+
328
+ export async function POST(req: Request) {
329
+ const token = req.headers.get("authorization")?.split(" ")[1];
330
+ const decoded = jwt.verify(token, process.env.JWT_SECRET!);
331
+ await prisma.user.update({ where: { id: decoded.sub }, data: { lastSeen: new Date() } });
332
+ return Response.json({ ok: true });
333
+ }
334
+ `);
335
+ expect(run(makeIndex([route]), config)).toHaveLength(0);
336
+ });
337
+ it("does NOT suppress for verify() without jsonwebtoken import", () => {
338
+ const route = createRoute("app/api/fake-verify/route.ts", `
339
+ import { verify } from "./my-utils";
340
+
341
+ export async function POST(req: Request) {
342
+ verify(someData);
343
+ await prisma.user.create({ data: { name: "test" } });
344
+ return Response.json({ ok: true });
345
+ }
346
+ `);
347
+ expect(run(makeIndex([route]), config)).toHaveLength(1);
348
+ });
349
+ });
350
+ /* ------------------------------------------------------------------ */
351
+ /* 6. DB-backed API token lookup */
352
+ /* ------------------------------------------------------------------ */
353
+ describe("DB-backed API token lookup", () => {
354
+ it("suppresses for header + prisma.apiKey.findUnique + 401", () => {
355
+ const route = createRoute("app/api/external/route.ts", `
356
+ export async function POST(req: Request) {
357
+ const key = req.headers.get("x-api-key");
358
+ if (!key) return NextResponse.json({ error: "Missing key" }, { status: 401 });
359
+ const apiKey = await prisma.apiKey.findUnique({ where: { key } });
360
+ if (!apiKey) return NextResponse.json({ error: "Invalid key" }, { status: 403 });
361
+ await prisma.event.create({ data: { source: "api", keyId: apiKey.id } });
362
+ return Response.json({ ok: true });
363
+ }
364
+ `);
365
+ expect(run(makeIndex([route]), config)).toHaveLength(0);
366
+ });
367
+ it("suppresses for header + prisma.apiToken.findFirst + 403", () => {
368
+ const route = createRoute("app/api/integration/route.ts", `
369
+ export async function POST(req: Request) {
370
+ const token = req.headers.get("authorization")?.replace("Bearer ", "");
371
+ const apiToken = await prisma.apiToken.findFirst({ where: { token, active: true } });
372
+ if (!apiToken) {
373
+ return new Response("Forbidden", { status: 403 });
374
+ }
375
+ await prisma.webhook.create({ data: { tokenId: apiToken.id } });
376
+ return Response.json({ ok: true });
377
+ }
378
+ `);
379
+ expect(run(makeIndex([route]), config)).toHaveLength(0);
380
+ });
381
+ });
382
+ /* ------------------------------------------------------------------ */
383
+ /* 7. Callback path downgrade */
384
+ /* ------------------------------------------------------------------ */
385
+ describe("callback path downgrade", () => {
386
+ it("downgrades /oidc/callback to med confidence (not suppressed)", () => {
387
+ const route = createRoute("app/oidc/callback/desktop/route.ts", `
388
+ export const GET = async (req: Request) => {
389
+ const code = new URL(req.url).searchParams.get("code");
390
+ const state = new URL(req.url).searchParams.get("state");
391
+ await prisma.oauthHandoff.create({ client: "desktop", id: state, payload: { code } });
392
+ return NextResponse.redirect(successUrl);
393
+ };
394
+ `, { pathname: "/oidc/callback/desktop" });
395
+ const findings = run(makeIndex([route]), config);
396
+ expect(findings).toHaveLength(1);
397
+ expect(findings[0].confidence).toBe("med");
398
+ expect(findings[0].tags).toContain("callback");
399
+ expect(findings[0].message).toContain("Callback");
400
+ expect(findings[0].remediation?.[0]).toContain("framework validation");
401
+ });
402
+ it("downgrades /oauth/callback path to med confidence", () => {
403
+ const route = createRoute("app/api/oauth/callback/route.ts", `
404
+ export async function GET(req: Request) {
405
+ const code = new URL(req.url).searchParams.get("code");
406
+ await prisma.session.create({ data: { code } });
407
+ return Response.redirect("/dashboard");
408
+ }
409
+ `, { pathname: "/api/oauth/callback" });
410
+ const findings = run(makeIndex([route]), config);
411
+ expect(findings).toHaveLength(1);
412
+ expect(findings[0].confidence).toBe("med");
413
+ });
414
+ it("does NOT downgrade regular API routes", () => {
415
+ const route = createRoute("app/api/users/route.ts", `
416
+ export async function POST(req: Request) {
417
+ const body = await req.json();
418
+ await prisma.user.create({ data: body });
419
+ return Response.json({ ok: true });
420
+ }
421
+ `);
422
+ const findings = run(makeIndex([route]), config);
423
+ expect(findings).toHaveLength(1);
424
+ expect(findings[0].confidence).toBe("high");
425
+ });
426
+ });
427
+ /* ------------------------------------------------------------------ */
428
+ /* 8. Existing patterns still work */
429
+ /* ------------------------------------------------------------------ */
430
+ describe("existing patterns still work", () => {
431
+ it("suppresses for Stripe constructEvent", () => {
432
+ const route = createRoute("app/api/webhooks/stripe/route.ts", `
433
+ export async function POST(req: Request) {
434
+ const sig = req.headers.get("stripe-signature");
435
+ const event = stripe.webhooks.constructEvent(body, sig, secret);
436
+ await prisma.payment.create({ data: event.data });
437
+ return Response.json({ ok: true });
438
+ }
439
+ `);
440
+ expect(run(makeIndex([route]), config)).toHaveLength(0);
441
+ });
442
+ it("suppresses for Supabase .auth.getUser()", () => {
443
+ const route = createRoute("app/api/posts/route.ts", `
444
+ export async function POST(req: Request) {
445
+ const { data: { user } } = await supabase.auth.getUser();
446
+ if (!user) return Response.json({ error: "Unauthorized" }, { status: 401 });
447
+ await supabase.from("posts").insert({ title: "test", author: user.id });
448
+ return Response.json({ ok: true });
449
+ }
450
+ `);
451
+ expect(run(makeIndex([route]), config)).toHaveLength(0);
452
+ });
453
+ it("flags unprotected mutation route", () => {
454
+ const route = createRoute("app/api/unprotected/route.ts", `
455
+ export async function POST(req: Request) {
456
+ const body = await req.json();
457
+ await prisma.user.create({ data: body });
458
+ return Response.json({ ok: true });
459
+ }
460
+ `);
461
+ const findings = run(makeIndex([route]), config);
462
+ expect(findings).toHaveLength(1);
463
+ expect(findings[0].ruleId).toBe("AUTH-BOUNDARY-MISSING");
464
+ expect(findings[0].severity).toBe("critical");
465
+ expect(findings[0].confidence).toBe("high");
466
+ });
467
+ });
468
+ //# sourceMappingURL=auth-boundary-missing.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-boundary-missing.test.js","sourceRoot":"","sources":["../../src/rules/auth-boundary-missing.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fourteensystems/shipguard",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "CI guardrail that blocks unprotected mutation routes in Next.js SaaS",
5
5
  "type": "module",
6
6
  "bin": {