Antra
How it worksStar1Get Started
Star1
Antra
How it worksStar1Get Started
Star1
Documentation
  • Introduction
  • Installation
  • Quick start
  • Configuration basics
  • Monorepos
  • Trust boundaries
  • Findings and severity
  • Schema providers
  • Suppressions and baselines
  • antra init
  • antra scan
  • antra sync
  • antra doctor
  • antra baseline
  • antra trace
  • antra watch
  • antra fix
  • antra query
  • antra studio
  • Studio
  • Launching Studio
  • Reading the graph
  • Configuration reference
  • BG-001: Server-to-client leak
  • BG-002: Unvalidated input
  • BG-003: Opaque object pass
  • BG-004: Secret in markup
  • GitHub Actions
  • Introduction
  • Installation
  • Quick start
  • Configuration basics
  • Monorepos
  • Trust boundaries
  • Findings and severity
  • Schema providers
  • Suppressions and baselines
  • antra init
  • antra scan
  • antra sync
  • antra doctor
  • antra baseline
  • antra trace
  • antra watch
  • antra fix
  • antra query
  • antra studio
  • Studio
  • Launching Studio
  • Reading the graph
  • Configuration reference
  • BG-001: Server-to-client leak
  • BG-002: Unvalidated input
  • BG-003: Opaque object pass
  • BG-004: Secret in markup
  • GitHub Actions

BG-001: Server-to-client leak

A sensitive value leaves the server through a Client Component prop, a Server Action return, or a route response.

Severity: error

A concrete sensitive value leaves the server where the browser can read it:

  • as a prop, a spread, or children of a Client Component rendered by a Server Component
  • as the return value of a Server Action
  • in the body of a route handler response (Response.json, NextResponse.json, new Response(...))

Why it fires

That value crosses the React Flight boundary as serialized data the browser can read. The rule looks at Server Components specifically, finds JSX sinks whose target file is classified as a client boundary, and checks the attributes being passed.

What counts as sensitive

The analysis treats a value as sensitive when it is:

  • a field named by your schema, through a configured provider
  • a field name matching a configured keyword
  • a process.env value, including one read through a variable (const { KEY } = process.env) or a t3-env object (env.KEY)

Public variables are skipped: NEXT_PUBLIC_*, NODE_ENV, NEXT_RUNTIME, VERCEL_ENV, and anything declared under t3-env's client or shared.

process.env is in that list because a server-side environment variable read into a prop is a leak regardless of what your schema says. The schema was never asked about it.

How far it follows a value

Through assignments, destructuring, object literals, function returns (including wrappers such as cache() and unstable_cache), up to three imports, and one hop into a component's props, even when that component lives in another file. next/dynamic and React.lazy components resolve to the file they import.

What the client itself sent is never reported: a request body, a Server Action argument, or a page's params and searchParams.

The mistake to avoid

Serializing the value is not the same as needing it on the client. An object crossing into client props is well-typed either way; the question is whether those fields were meant to travel.

Fixing it

Project the fields the client actually needs into a new object before the crossing. When the crossing is intentional and the value is safe, record the decision at the line:

// antra-disable-next-line
return <AccountCard account={account} />;

For a whole report at once, antra baseline records the current violations instead.

Previous
Configuration reference
Next
BG-002: Unvalidated input
On this page
  • Why it fires
  • What counts as sensitive
  • How far it follows a value
  • The mistake to avoid
  • Fixing it