Fix guide · low · exposed_nextjs_build_manifest
Next.js _buildManifest.js exposed
Your _next/static/chunks/_buildManifest.js is reachable. The file lists every route in your Next.js build, including admin routes and dynamic-segment routes attackers can probe for IDOR.
Why it matters
Next.js writes a build manifest to _next/static/chunks/_buildManifest.js that lists every route the build produced. It looks like:
self.__BUILD_MANIFEST = (function() {
return {
"/": ["static/chunks/pages/index-abc.js"],
"/admin/dashboard": ["static/chunks/pages/admin/dashboard-def.js"],
"/admin/users/[id]": ["static/chunks/pages/admin/users/[id]-ghi.js"],
"/api/internal/health": [],
...
};
}());
The file is loaded by the browser at runtime to enable client-side route prefetching — it's INTENDED to be public. But the route list is also a complete map of:
- Admin and internal routes that aren't linked from the user-facing UI.
- Dynamic-segment patterns like
/admin/users/[id]that tell an attacker exactly which IDs they should try to probe for IDOR vulnerabilities. - API routes including any
/api/internal/*paths.
Next.js makes this file public by design. The risk it surfaces is route-level authorisation — for every route in this list, does your app authenticate the user and check their permissions? If a route is in the manifest, an unauthenticated attacker can hit it and watch for behavioural differences.
How to fix it
- Audit the route list. Open
_buildManifest.js(in your build output or via the public URL) and treat every listed route as a target. For each:
- Does it require authentication? Verify by hitting it without a session cookie.
- Does it check authorisation? Verify by hitting it with a low-privilege session.
- Does it accept dynamic IDs? Verify it doesn't return resources the user shouldn't see (IDOR).
- You can't hide the manifest. It's required for Next.js client-side routing. The defence is making sure every listed route is itself secure.
- For routes that ARE admin-only, ensure they redirect unauthenticated users to login and authenticated-but-unauthorised users to a 403. Don't return 404 — leaking presence is exactly the reconnaissance you're trying to avoid.
- Consider hash-based admin paths for routes that should be discoverable only by team members (e.g.
/admin-abc123def/) — but treat this as defence-in-depth, NOT as the only protection.
Did vibecheck flag this on your app?
If you reached this page from a vibecheck inspection report, the redacted match in your scan output is the exact string we found in your bundle. After applying the fix above, run the inspection again — the finding should clear.
Run another inspection