← All security checksNext.js data exposure

What is Next.js's _next/data route, and can it leak data?

Next.js's Pages Router serves the exact data a page needs to render (the return value of getStaticProps or getServerSideProps) as JSON at a predictable URL: /_next/data/<buildId>/<route>.json. This is by design and normally harmless; it's how client-side navigation avoids a full page reload. It becomes a real finding when that JSON includes fields a page never actually displays, or when a route meant to require authentication serves its data JSON to anonymous requests exactly like a public one would.

Why this happens in AI-generated apps

It's common, and often reasonable, to fetch a full record from a database and pass the whole object into `pageProps` rather than picking out only the two or three fields the page renders: it's less code, and during fast, prompt-driven iteration nobody stops to trim the object down. The page itself looks correct: it shows exactly the fields it's supposed to. The full underlying object is still sitting in the props payload, and that payload is exactly what /_next/data serves as raw JSON.

The same gap shows up around authentication: if a page checks the user's session client-side (in the component) rather than inside getServerSideProps itself, the HTML the browser renders may correctly redirect an anonymous visitor away, but the /_next/data JSON for that route was already computed and returned before any client-side check ran.

What this can expose

Anything present in a page's props but not rendered on screen: internal IDs, other users' data included for a comparison or admin view, feature flags, or fields kept "just in case" a future UI change needs them. For an authenticated route with a client-side-only session check, it can mean the full page data for a logged-in-only view being served to a request carrying no session at all.

How to fix it

Treat everything returned from getStaticProps/getServerSideProps as something that will be readable as raw JSON by anyone who knows or guesses the route, because it already is.

  • Return only the specific fields a page actually renders from getStaticProps/getServerSideProps, never the full database record.
  • Do authentication and authorization checks inside getServerSideProps itself (redirecting or returning notFound there), not only in the rendered component. A client-side-only check doesn't stop the data endpoint from returning props to an unauthenticated request.
  • If you're on the App Router instead of Pages Router, this specific route doesn't apply the same way, but the underlying principle does: never pass more into props/server components than the client is meant to see.
  • Re-scan after deploying to confirm the route data no longer includes trimmed fields or serves for a request with no session.

Frequently asked

Is /_next/data itself a bug in Next.js?

No. It's documented, intentional behavior that makes client-side page transitions fast without a full reload. The finding isn't that the route exists; it's when the specific data returned for a specific route is broader than what the page shows, or is served to requests that shouldn't be able to see it.

Does this affect apps built with the App Router instead of Pages Router?

The /_next/data route specifically is a Pages Router mechanism. The App Router streams server-rendered content differently, so this exact check doesn't apply, but the same underlying mistake (passing more data into a server component or fetch than the client is meant to receive, or checking auth only in client code) is just as possible there, it just isn't reachable at this particular URL.

//Get started//

Ready to make it unbreachable?

Point us at your app and get a full breakdown of what's exposed in about two minutes. Every finding comes with the fix.

Shipping with an AI builder? See how verification works