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.