@fourteensystems/shipguard 0.2.4 → 0.2.6
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/dist/cli/commands/scan.d.ts.map +1 -1
- package/dist/cli/commands/scan.js +11 -1
- package/dist/cli/commands/scan.js.map +1 -1
- package/dist/engine/report.d.ts.map +1 -1
- package/dist/engine/report.js +16 -1
- package/dist/engine/report.js.map +1 -1
- package/dist/engine/run.d.ts +2 -0
- package/dist/engine/run.d.ts.map +1 -1
- package/dist/engine/run.js +5 -1
- package/dist/engine/run.js.map +1 -1
- package/dist/engine/version.d.ts +1 -1
- package/dist/engine/version.js +1 -1
- package/dist/next/index.d.ts +1 -1
- package/dist/next/index.d.ts.map +1 -1
- package/dist/next/index.js +8 -1
- package/dist/next/index.js.map +1 -1
- package/dist/rules/auth-boundary-missing.d.ts.map +1 -1
- package/dist/rules/auth-boundary-missing.js +215 -14
- package/dist/rules/auth-boundary-missing.js.map +1 -1
- 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 +468 -0
- package/dist/rules/auth-boundary-missing.test.js.map +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/scan.ts"],"names":[],"mappings":"AASA,UAAU,WAAW;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/scan.ts"],"names":[],"mappings":"AASA,UAAU,WAAW;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAiE9D"}
|
|
@@ -20,7 +20,17 @@ export async function cmdScan(opts) {
|
|
|
20
20
|
const additionalExclude = opts.exclude
|
|
21
21
|
? opts.exclude.split(",").map((g) => g.trim())
|
|
22
22
|
: undefined;
|
|
23
|
-
|
|
23
|
+
// Progress indicator for interactive terminals
|
|
24
|
+
const isTTY = process.stderr.isTTY;
|
|
25
|
+
const onProgress = isTTY
|
|
26
|
+
? (step) => {
|
|
27
|
+
process.stderr.write(`\r ${pc.dim("⏳")} ${pc.dim(step)}${"".padEnd(20)}\r`);
|
|
28
|
+
}
|
|
29
|
+
: undefined;
|
|
30
|
+
const result = await runScan({ rootDir, configOverrides, additionalExclude, onProgress });
|
|
31
|
+
// Clear progress line
|
|
32
|
+
if (isTTY)
|
|
33
|
+
process.stderr.write("\r".padEnd(60) + "\r");
|
|
24
34
|
// Filter by confidence if specified, recalculate score and summary
|
|
25
35
|
if (opts.minConfidence) {
|
|
26
36
|
const minConf = parseConfidence(opts.minConfidence);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scan.js","sourceRoot":"","sources":["../../../src/cli/commands/scan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAY1G,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAiB;IAC7C,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAE9B,wCAAwC;QACxC,MAAM,eAAe,GAA6B,EAAE,CAAC;QAErD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;YAC1E,MAAM,KAAK,GAA2C,EAAE,CAAC;YACzD,KAAK,MAAM,MAAM,IAAI,SAAS,EAAE,CAAC;gBAC/B,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;YAC3C,CAAC;YACD,eAAe,CAAC,KAAK,GAAG,KAAK,CAAC;QAChC,CAAC;QAED,MAAM,iBAAiB,GAAG,IAAI,CAAC,OAAO;YACpC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC9C,CAAC,CAAC,SAAS,CAAC;QAEd,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"scan.js","sourceRoot":"","sources":["../../../src/cli/commands/scan.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/engine/report.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAW,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAGlD,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,YAAY,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/engine/report.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAW,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAGlD,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,YAAY,GAAG,MAAM,CAoG5E;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAErD"}
|
package/dist/engine/report.js
CHANGED
|
@@ -10,7 +10,22 @@ export function formatPretty(result, diff) {
|
|
|
10
10
|
lines.push("");
|
|
11
11
|
lines.push(` ${pc.bold("Shipguard")} ${pc.dim(result.shipguardVersion)}`);
|
|
12
12
|
lines.push(` ${pc.dim("Detected:")} ${detected.join(" · ")}`);
|
|
13
|
-
|
|
13
|
+
// Score line with inline severity counts
|
|
14
|
+
if (findings.length === 0) {
|
|
15
|
+
lines.push(` ${pc.dim("Score:")} ${scoreColor(String(score))} ${scoreColor(status)}`);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
const parts = [];
|
|
19
|
+
if (summary.critical > 0)
|
|
20
|
+
parts.push(pc.red(`${summary.critical} critical`));
|
|
21
|
+
if (summary.high > 0)
|
|
22
|
+
parts.push(pc.yellow(`${summary.high} high`));
|
|
23
|
+
if (summary.med > 0)
|
|
24
|
+
parts.push(`${summary.med} med`);
|
|
25
|
+
if (summary.low > 0)
|
|
26
|
+
parts.push(pc.dim(`${summary.low} low`));
|
|
27
|
+
lines.push(` ${pc.dim("Score:")} ${scoreColor(String(score))} ${scoreColor(status)} ${pc.dim("·")} ${parts.join(pc.dim(" · "))}`);
|
|
28
|
+
}
|
|
14
29
|
// Banner: no auth provider detected
|
|
15
30
|
const d = result.detected.deps;
|
|
16
31
|
const hasAnyAuth = d.hasNextAuth || d.hasClerk || d.hasSupabase || d.hasKinde ||
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/engine/report.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAG5B,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE5D,MAAM,UAAU,YAAY,CAAC,MAAkB,EAAE,IAAmB;IAClE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IAE5D,6BAA6B;IAC7B,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAClC,MAAM,UAAU,GAAG,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC;IACzF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC;IAC3E,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC/D,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/engine/report.ts"],"names":[],"mappings":"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"}
|
package/dist/engine/run.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ export interface RunOptions {
|
|
|
4
4
|
configOverrides?: Partial<ShipguardConfig>;
|
|
5
5
|
/** Additional exclude globs appended to config excludes (not replacing) */
|
|
6
6
|
additionalExclude?: string[];
|
|
7
|
+
/** Called with a short status string at each scan phase */
|
|
8
|
+
onProgress?: (step: string) => void;
|
|
7
9
|
}
|
|
8
10
|
export declare function runScan(opts: RunOptions): Promise<ScanResult>;
|
|
9
11
|
//# sourceMappingURL=run.d.ts.map
|
package/dist/engine/run.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/engine/run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAW,MAAM,YAAY,CAAC;AAQvE,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAC3C,2EAA2E;IAC3E,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/engine/run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAW,MAAM,YAAY,CAAC;AAQvE,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAC3C,2EAA2E;IAC3E,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,2DAA2D;IAC3D,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAyFnE"}
|
package/dist/engine/run.js
CHANGED
|
@@ -48,13 +48,17 @@ export async function runScan(opts) {
|
|
|
48
48
|
if (opts.additionalExclude?.length) {
|
|
49
49
|
config.exclude = [...config.exclude, ...opts.additionalExclude];
|
|
50
50
|
}
|
|
51
|
+
const progress = opts.onProgress ?? (() => { });
|
|
51
52
|
// Build Next.js index
|
|
52
|
-
|
|
53
|
+
progress("Indexing routes and server actions");
|
|
54
|
+
const index = await buildNextIndex(opts.rootDir, config.exclude, opts.onProgress);
|
|
53
55
|
// Merge auto-detected hints with user config
|
|
54
56
|
const mergedHints = mergeHints(config.hints, index.hints);
|
|
55
57
|
// Run rules
|
|
58
|
+
progress("Running rules");
|
|
56
59
|
const rawFindings = runAllRules(index, { ...config, hints: mergedHints });
|
|
57
60
|
// Apply waivers
|
|
61
|
+
progress("Applying waivers");
|
|
58
62
|
const waivers = loadWaivers(opts.rootDir, config.waiversFile);
|
|
59
63
|
const { active, waived } = applyWaivers(rawFindings, waivers);
|
|
60
64
|
// Score
|
package/dist/engine/run.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/engine/run.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/engine/run.ts"],"names":[],"mappings":"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"}
|
package/dist/engine/version.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ShipguardConfig } from "./types.js";
|
|
2
|
-
export declare const SHIPGUARD_VERSION = "0.2.
|
|
2
|
+
export declare const SHIPGUARD_VERSION = "0.2.6";
|
|
3
3
|
export declare const INDEX_VERSION = 1;
|
|
4
4
|
export declare function hashConfig(config: ShipguardConfig): string;
|
|
5
5
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/engine/version.js
CHANGED
package/dist/next/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { NextIndex } from "./types.js";
|
|
2
2
|
export type { NextIndex } from "./types.js";
|
|
3
3
|
export { detectNextAppRouter } from "./detect.js";
|
|
4
|
-
export declare function buildNextIndex(rootDir: string, exclude: string[]): Promise<NextIndex>;
|
|
4
|
+
export declare function buildNextIndex(rootDir: string, exclude: string[], onProgress?: (step: string) => void): Promise<NextIndex>;
|
|
5
5
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/next/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAU5C,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAU5C,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EAAE,EACjB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAClC,OAAO,CAAC,SAAS,CAAC,CA6DpB"}
|
package/dist/next/index.js
CHANGED
|
@@ -9,12 +9,14 @@ import { buildTrpcIndex } from "./trpc.js";
|
|
|
9
9
|
import { buildWrapperIndex, computeProtection } from "./wrappers.js";
|
|
10
10
|
import { loadTsconfigPaths } from "../util/resolve.js";
|
|
11
11
|
export { detectNextAppRouter } from "./detect.js";
|
|
12
|
-
export async function buildNextIndex(rootDir, exclude) {
|
|
12
|
+
export async function buildNextIndex(rootDir, exclude, onProgress) {
|
|
13
|
+
const progress = onProgress ?? (() => { });
|
|
13
14
|
const det = detectNextAppRouter(rootDir);
|
|
14
15
|
if (!det.ok) {
|
|
15
16
|
throw new Error(`Shipguard v1 supports Next.js App Router only: ${det.reason ?? "unknown reason"}`);
|
|
16
17
|
}
|
|
17
18
|
const { appDir } = det;
|
|
19
|
+
progress("Reading dependencies");
|
|
18
20
|
const deps = readDeps(rootDir);
|
|
19
21
|
// Check for middleware in standard locations
|
|
20
22
|
const hasMiddlewareTs = existsSync(path.join(rootDir, "middleware.ts"))
|
|
@@ -22,13 +24,18 @@ export async function buildNextIndex(rootDir, exclude) {
|
|
|
22
24
|
|| existsSync(path.join(rootDir, "src/middleware.ts"))
|
|
23
25
|
|| existsSync(path.join(rootDir, "src/middleware.js"));
|
|
24
26
|
const hints = defaultHintsFromDeps(deps, hasMiddlewareTs);
|
|
27
|
+
progress("Analyzing middleware");
|
|
25
28
|
const middleware = analyzeMiddleware(rootDir);
|
|
29
|
+
progress("Discovering routes");
|
|
26
30
|
const allRoutes = await findRouteHandlers(rootDir, exclude, appDir);
|
|
27
31
|
const mutationRoutes = classifyMutationRoutes(allRoutes);
|
|
32
|
+
progress("Discovering server actions");
|
|
28
33
|
const allActions = await findServerActions(rootDir, exclude, appDir);
|
|
29
34
|
const mutationActions = classifyMutationActions(allActions);
|
|
35
|
+
progress("Analyzing tRPC procedures");
|
|
30
36
|
const trpc = await buildTrpcIndex(rootDir, appDir, exclude);
|
|
31
37
|
// Wrapper introspection: resolve, analyze, compute protection
|
|
38
|
+
progress("Resolving wrappers");
|
|
32
39
|
const tsconfigPaths = loadTsconfigPaths(rootDir);
|
|
33
40
|
const resolveOpts = { rootDir, tsconfigPaths };
|
|
34
41
|
const wrappers = buildWrapperIndex(allRoutes, rootDir, resolveOpts, hints.auth.functions, hints.rateLimit.wrappers);
|
package/dist/next/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAGvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAe,EACf,OAAiB;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -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,
|
|
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
|
|
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:
|
|
31
|
-
? `
|
|
32
|
-
:
|
|
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:
|
|
42
|
+
remediation: isCallback
|
|
39
43
|
? [
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
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
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAI7B,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,MAAM,CAAC,MAAM,OAAO,GAAG,uBAAuB,CAAC;AAE/C,MAAM,aAAa,GAA2B,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;AAEvF,SAAS,sBAAsB,CAAC,UAAsB,EAAE,WAAmB;IACzE,MAAM,GAAG,GAAG,WAAuB,CAAC;IACpC,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACxC,0DAA0D;IAC1D,+BAA+B;IAC/B,MAAM,QAAQ,GAAa,UAAU,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;IAChE,MAAM,YAAY,GAAG,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAClD,OAAO,YAAY,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,KAAgB,EAAE,MAAuB;IAC3D,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,QAAQ,IAAI,UAAU,CAAC;IAElE,MAAM,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC;IAEvD,gCAAgC;IAChC,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;QAChD,IAAI,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,aAAa,CAAC;YAAE,SAAS;QACvD,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QAChD,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC;YAChE,QAAQ,CAAC,IAAI,CAAC;gBACZ,MAAM,EAAE,OAAO;gBACf,QAAQ,EAAE,sBAAsB,CAAC,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC;gBAChE,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,OAAO,EAAE,SAAS;oBAChB,CAAC,CAAC,oEAAoE;oBACtE,CAAC,CAAC,qEAAqE;gBACzE,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,mBAAmB,EAAE,MAAM,CAAC,mBAAmB;gBAC/C,WAAW,EAAE,SAAS;oBACpB,CAAC,CAAC;wBACE,uEAAuE;wBACvE,+FAA+F;wBAC/F,+EAA+E;qBAChF;oBACH,CAAC,CAAC;wBACE,oFAAoF;wBACpF,kDAAkD;wBAClD,yFAAyF;qBAC1F;gBACL,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC;aACrE,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,qFAAqF;IACrF,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAC;IAC1C,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,eAAe,EAAE,CAAC;QACzD,IAAI,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;YAAE,SAAS;QAC/C,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,aAAa,CAAC,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC;YAAE,SAAS;QACxD,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QACxD,IAAI,MAAM,EAAE,CAAC;YACX,QAAQ,CAAC,IAAI,CAAC;gBACZ,MAAM,EAAE,OAAO;gBACf,QAAQ,EAAE,sBAAsB,CAAC,MAAM,CAAC,UAAU,EAAE,WAAW,CAAC;gBAChE,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,OAAO,EAAE,qEAAqE;gBAC9E,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,mBAAmB,EAAE,MAAM,CAAC,mBAAmB;gBAC/C,WAAW,EAAE;oBACX,mDAAmD;oBACnD,yFAAyF;iBAC1F;gBACD,IAAI,EAAE,CAAC,MAAM,EAAE,eAAe,CAAC;aAChC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,iCAAiC;IACjC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACjD,IAAI,IAAI,CAAC,aAAa,KAAK,WAAW;YAAE,SAAS;QACjD,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC;YAAE,SAAS;QAEtD,MAAM,UAAU,GAAe,IAAI,CAAC,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;QAChF,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,OAAO;YACf,QAAQ,EAAE,sBAAsB,CAAC,UAAU,EAAE,WAAW,CAAC;YACzD,UAAU;YACV,OAAO,EAAE,kBAAkB,IAAI,CAAC,IAAI,UAAU,IAAI,CAAC,aAAa,iCAAiC;YACjG,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAC,aAAa,sBAAsB,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC;YACxF,mBAAmB,EAAE,IAAI,CAAC,aAAa,KAAK,QAAQ;gBAClD,CAAC,CAAC,kDAAkD;gBACpD,CAAC,CAAC,gEAAgE;YACpE,WAAW,EAAE;gBACX,iEAAiE;gBACjE,+FAA+F;gBAC/F,oEAAoE;aACrE;YACD,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;SACvB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAUD,SAAS,UAAU,CACjB,KAAgB,EAChB,KAAgB,EAChB,MAAuB;IAEvB,sEAAsE;IACtE,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;QACrB,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,CAAC;QAEjD,+FAA+F;QAC/F,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,kBAAkB,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;IACvE,CAAC;IAED,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAClD,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IAEtB,yEAAyE;IACzE,2DAA2D;IAC3D,IAAI,qBAAqB,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAE5C,uCAAuC;IACvC,MAAM,QAAQ,GAAa,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IAC9D,QAAQ,CAAC,IAAI,CAAC,mCAAmC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3F,QAAQ,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;IACxD,IAAI,UAAU,GAAe,MAAM,CAAC;IACpC,IAAI,mBAAmB,GAAG,kEAAkE,CAAC;IAE7F,mEAAmE;IACnE,IAAI,qBAAqB,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/B,UAAU,GAAG,KAAK,CAAC;QACnB,mBAAmB,GAAG,4FAA4F,CAAC;QACnH,QAAQ,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC;IACxE,CAAC;IAED,qEAAqE;IACrE,MAAM,IAAI,GAAG,qBAAqB,CAAC,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAEvD,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AAC7D,CAAC;AAED,SAAS,iBAAiB,CACxB,MAAwB,EACxB,KAAgB,EAChB,MAAuB;IAEvB,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IACnD,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IAEtB,IAAI,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/D,IAAI,qBAAqB,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAE5C,MAAM,QAAQ,GAAa,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IAC/D,QAAQ,CAAC,IAAI,CAAC,mCAAmC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3F,IAAI,UAAU,GAAe,MAAM,CAAC;IACpC,IAAI,mBAAmB,GAAG,4DAA4D,CAAC;IAEvF,IAAI,qBAAqB,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/B,UAAU,GAAG,KAAK,CAAC;QACnB,mBAAmB,GAAG,4FAA4F,CAAC;QACnH,QAAQ,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC;IACxE,CAAC;IAED,MAAM,IAAI,GAAG,qBAAqB,CAAC,GAAG,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAExD,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AAC7D,CAAC;AAED,SAAS,WAAW,CAAC,GAAW,EAAE,aAAuB;IACvD,KAAK,MAAM,EAAE,IAAI,aAAa,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,MAAM,WAAW,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAChE,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;IACrC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,SAAS,qBAAqB,CAAC,GAAW;IACxC,wCAAwC;IACxC,IAAI,wCAAwC,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAEpE,4CAA4C;IAC5C,IAAI,6BAA6B,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACzD,IAAI,6BAA6B,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAEzD,uEAAuE;IACvE,IAAI,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAEvE,sCAAsC;IACtC,IAAI,wCAAwC,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAEpE,6DAA6D;IAC7D,IAAI,2BAA2B,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAEzF,yDAAyD;IACzD,IAAI,sBAAsB,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAClD,IAAI,yBAAyB,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAErD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,qBAAqB,CAAC,GAAW;IACxC,IAAI,6HAA6H,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5I,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,qDAAqD,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACpE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,qBAAqB,CAAC,GAAW,EAAE,OAAsC;IAChF,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,uEAAuE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3F,OAAO,CAAC,GAAG,CAAC,CAAC;QACf,CAAC;QACD,IAAI,uCAAuC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3D,OAAO,CAAC,GAAG,CAAC,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,UAAU,CAAC,OAAe,EAAE,IAAY;IAC/C,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,GAAW;IAC9B,OAAO,GAAG,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AACpD,CAAC"}
|
|
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 @@
|
|
|
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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"}
|