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-004: Secret in markup

A sensitive value is rendered directly into markup.

Severity: error

A concrete sensitive value is interpolated into an intrinsic element, as text content or as an attribute value.

<p>{user.password_hash}</p>
<div data-key={process.env.INTERNAL_KEY} />

Why it fires

No boundary crossing is needed. The value ends up in the HTML response as visible text or as an attribute, which is exactly the leak. Unlike BG-001, which is about structured prop data travelling through the Flight payload, this is a value written straight into the document.

What it checks

Intrinsic elements only: the tags that render to actual HTML. It looks at both child content and attribute values, since an attribute is as readable as the text next to it.

A condition is not a rendered value, so {process.env.NODE_ENV === "development" && <pre />} does not fire. In "use client" files, environment variables are ignored (a non-public one is undefined in the browser), and a field only counts when its value traces back to a fetch or database call, so form state such as values.password stays quiet.

Fixing it

Almost always by removing the render rather than sanitizing it. A sensitive value being printed is a mistake about what the page is for, not a validation gap. There is rarely a legitimate reason for a password hash to be in a .tsx file's output.

If the value genuinely belongs in the response, render the field the user is allowed to see instead:

<p>{user.maskedEmail}</p>

Related

  • BG-001: the same class of value, crossing through props into client components.
  • Trust boundaries: why markup counts as a boundary.
Previous
BG-003: Opaque object pass
Next
GitHub Actions
On this page
  • Why it fires
  • What it checks
  • Fixing it
  • Related