Skip to content

Commit eb69b26

Browse files
authored
Block vulnerable nextjs versions. (#442)
* Block vulnerable nextjs versions. * test * some cleanup * lint * more tests
1 parent c85f251 commit eb69b26

File tree

7 files changed

+133
-46
lines changed

7 files changed

+133
-46
lines changed

package-lock.json

Lines changed: 14 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/@apphosting/adapter-nextjs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
"@types/tmp": "*",
6262
"mocha": "*",
6363
"next": "~14.0.0",
64-
"semver": "*",
64+
"semver": "^7.7.3",
6565
"tmp": "*",
6666
"ts-mocha": "*",
6767
"ts-node": "*",

packages/@apphosting/adapter-nextjs/src/bin/build.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
validateOutputDirectory,
77
getAdapterMetadata,
88
exists,
9+
checkNextJSVersion,
910
} from "../utils.js";
1011
import { join } from "path";
1112
import { getBuildOptions, runBuild } from "@apphosting/common";
@@ -24,6 +25,7 @@ process.env.NEXT_PRIVATE_STANDALONE = "true";
2425
// Opt-out sending telemetry to Vercel
2526
process.env.NEXT_TELEMETRY_DISABLED = "1";
2627

28+
checkNextJSVersion(process.env.FRAMEWORK_VERSION);
2729
const nextConfig = await loadConfig(root, opts.projectDirectory);
2830

2931
/**

packages/@apphosting/adapter-nextjs/src/utils.spec.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,52 @@ import path from "path";
66
import os from "os";
77
import { RoutesManifest, MiddlewareManifest } from "../src/interfaces.js";
88

9+
describe("block vulnerable nextjs versions", () => {
10+
it("check for vulnerable versions", async () => {
11+
const { checkNextJSVersion } = await importUtils;
12+
13+
assert.throws(() => {
14+
checkNextJSVersion("15.0.0");
15+
});
16+
17+
assert.doesNotThrow(() => {
18+
checkNextJSVersion(undefined);
19+
});
20+
21+
assert.doesNotThrow(() => {
22+
checkNextJSVersion("15.0.5");
23+
});
24+
25+
assert.doesNotThrow(() => {
26+
checkNextJSVersion("14.0.12");
27+
});
28+
29+
assert.throws(() => {
30+
checkNextJSVersion("14.3.0-canary.77");
31+
});
32+
33+
assert.throws(() => {
34+
checkNextJSVersion("14.3.0-canary.78");
35+
});
36+
37+
assert.doesNotThrow(() => {
38+
checkNextJSVersion("14.3.0-canary.76");
39+
});
40+
41+
assert.throws(() => {
42+
checkNextJSVersion("15.0.0-canary.2");
43+
});
44+
45+
assert.throws(() => {
46+
checkNextJSVersion("16.0.6");
47+
});
48+
49+
assert.doesNotThrow(() => {
50+
checkNextJSVersion("16.0.7");
51+
});
52+
});
53+
});
54+
955
describe("manifest utils", () => {
1056
let tmpDir: string;
1157
let distDir: string;

packages/@apphosting/adapter-nextjs/src/utils.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import fsExtra from "fs-extra";
2+
import semVer from "semver";
23
import { createRequire } from "node:module";
34
import { join, dirname, relative, normalize } from "path";
45
import { fileURLToPath } from "url";
@@ -17,6 +18,21 @@ import { OutputBundleConfig, updateOrCreateGitignore } from "@apphosting/common"
1718
// fs-extra is CJS, readJson can't be imported using shorthand
1819
export const { copy, exists, writeFile, readJson, readdir, readFileSync, existsSync, ensureDir } =
1920
fsExtra;
21+
export const { satisfies } = semVer;
22+
23+
const SAFE_NEXTJS_VERSIONS =
24+
">=16.1.0 || ^16.0.7 || ^v15.5.7 || ^v15.4.8 || ^v15.3.6 || ^v15.2.6 || ^v15.1.9 || ^v15.0.5 || <14.3.0-canary.77";
25+
26+
export function checkNextJSVersion(version: string | undefined) {
27+
if (!version) {
28+
return;
29+
}
30+
if (!satisfies(version, SAFE_NEXTJS_VERSIONS)) {
31+
throw new Error(
32+
`CVE-2025-55182: Vulnerable Next version ${version} detected. Deployment blocked. Update your app's dependencies to a patched Next.js version and redeploy:https://nextjs.org/blog/CVE-2025-66478#fixed-versions`,
33+
);
34+
}
35+
}
2036

2137
// Loads the user's next.config.js file.
2238
export async function loadConfig(root: string, projectRoot: string): Promise<NextConfigComplete> {

starters/nextjs/basic/package-lock.json

Lines changed: 53 additions & 43 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

starters/nextjs/basic/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"lint": "next lint"
1010
},
1111
"dependencies": {
12-
"next": "15.0.0",
12+
"next": "15.0.5",
1313
"react": "^18",
1414
"react-dom": "^18"
1515
},

0 commit comments

Comments
 (0)