firebase / firebase/apphosting-adapters
checkNextJSVersion blocks Next.js preview/prerelease tags (e.g. next@preview)
- Dominant language
- TypeScript
- Stars
- 478
- Forks
- 1.5k
- Avg merge
- 3d 22h
- Merged PRs (30d)
- 2
Description
## Summary
`checkNextJSVersion` wrongly flags safe Next.js **preview/prerelease** builds as vulnerable and blocks deployment with the `CVE-2025-55182` error.
Next.js now publishes builds under a `preview` tag (`next@preview`), which resolves to prerelease versions like `16.3.0-preview`. These should pass the safe-version check (since `16.3.0` ≥ `16.1.0`), but they are blocked.
Reference: https://nextjs.org/blog/next-16-3-instant-navigations
## Root cause
In `packages/@apphosting/adapter-nextjs/src/utils.ts`:
```ts
if (!satisfies(version, SAFE_NEXTJS_VERSIONS)) {
throw new Error(`CVE-2025-55182: Vulnerable Next version ${version} detected. ...`);
}
```
By default, semver's `satisfies()` **excludes prerelease versions** from matching a range unless the range already contains a prerelease comparator for the same `[major, minor, patch]` tuple. `SAFE_NEXTJS_VERSIONS` only has one prerelease comparator (`<14.3.0-canary.77`), so a build like `16.3.0-preview` does not satisfy `>=16.1.0` and is treated as vulnerable.
## Reproduction
With `semver@7.7.3` and the current range:
```js
const RANGE = ">=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";
semver.satisfies("16.3.0-preview", RANGE); // => false (wrongly blocked)
semver.satisfies("16.3.0-preview", RANGE, { includePrerelease: true }); // => true
```
In practice, deploying an app that depends on `next@preview` fails with:
```
CVE-2025-55182: Vulnerable Next version 16.3.0-preview detected. Deployment blocked. ...
```
## Expected behavior
Safe preview/prerelease builds (e.g. `16.3.0-preview`) should pass the check, while genuinely vulnerable versions — including the canary boundary (`14.3.0-canary.77+`, `15.0.0-canary.x`, `16.0.6`, `15.4.7`, etc.) — remain blocked.
## Suggested fix
Pass `{ includePrerelease: true }` to `satisfies`. Verified against `semver@7.7.3` that this only unblocks safe prereleases and leaves all existing canary/vulnerable-version checks unchanged.
| version | before | after | safe? |
|---|---|---|---|
| `16.3.0-preview` | ❌ blocked | ✅ allowed | safe |
| `14.3.0-canary.76` | ✅ allowed | ✅ allowed | safe |
| `14.3.0-canary.77` / `.78` | 🚫 blocked | 🚫 blocked | vulnerable |
| `15.0.0-canary.2` | 🚫 blocked | 🚫 blocked | vulnerable |
| `16.0.6` | 🚫 blocked | 🚫 blocked | vulnerable |
Fix submitted in #660.
Contributor guide
Research direction
Start in packages/@apphosting/adapter-nextjs/src/utils.ts at the checkNextJSVersion semver.satisfies call and review the SAFE_NEXTJS_VERSIONS range. Verify the listed preview, canary, and vulnerable versions against the expected results; the issue notes that a fix was submitted in #660.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- next.js, typescript
- Domain
- devops
- Issue type
- Bug
- Difficulty
- 1/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 25/100