Skip to content

Commit 714b0e6

Browse files
authored
Block builds on vulnerable nextjs versions (#447)
* Revert "Revert call to check nextjs version (#446)" This reverts commit 71a239c. * npm install
1 parent 71a239c commit 714b0e6

File tree

5 files changed

+77
-3
lines changed

5 files changed

+77
-3
lines changed

package-lock.json

Lines changed: 2 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: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@apphosting/adapter-nextjs",
3-
"version": "14.0.20",
3+
"version": "14.0.21",
44
"main": "dist/index.js",
55
"description": "Experimental addon to the Firebase CLI to add web framework support",
66
"repository": {
@@ -45,7 +45,8 @@
4545
"dependencies": {
4646
"@apphosting/common": "*",
4747
"fs-extra": "^11.1.1",
48-
"yaml": "^2.3.4"
48+
"yaml": "^2.3.4",
49+
"semver": "^7.7.3"
4950
},
5051
"peerDependencies": {
5152
"next": "*"

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: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,60 @@ 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.throws(() => {
26+
checkNextJSVersion("15.4.7");
27+
});
28+
29+
assert.doesNotThrow(() => {
30+
checkNextJSVersion("15.4.8");
31+
});
32+
33+
assert.doesNotThrow(() => {
34+
checkNextJSVersion("14.0.12");
35+
});
36+
37+
assert.throws(() => {
38+
checkNextJSVersion("14.3.0-canary.77");
39+
});
40+
41+
assert.throws(() => {
42+
checkNextJSVersion("14.3.0-canary.78");
43+
});
44+
45+
assert.doesNotThrow(() => {
46+
checkNextJSVersion("14.3.0-canary.76");
47+
});
48+
49+
assert.throws(() => {
50+
checkNextJSVersion("15.0.0-canary.2");
51+
});
52+
53+
assert.throws(() => {
54+
checkNextJSVersion("16.0.6");
55+
});
56+
57+
assert.doesNotThrow(() => {
58+
checkNextJSVersion("16.0.7");
59+
});
60+
});
61+
});
62+
963
describe("manifest utils", () => {
1064
let tmpDir: string;
1165
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> {

0 commit comments

Comments
 (0)