- Next.js
- Security & Authentication Architecture
- Preventing Data Leaks with server-only & React Taint APIs
Preventing Data Leaks with server-only & React Taint APIs
Data leaks in React Server Components occur when sensitive server-side secrets or raw database records are accidentally imported by Client Components or passed across component boundaries. Next.js prevents code leaks using the "server-only" package (build-time error). React further provides experimental Taint APIs (experimental_taintUniqueValue and experimental_taintObjectReference) to block sensitive runtime data values from being passed to client components.
Learning Objectives
Prevent server code from being bundled into client assets using the "server-only" package.
Explain the mechanism of React Taint APIs (taintUniqueValue and taintObjectReference).
Implement Data Access Layers (DAL) with explicit Data Transfer Objects (DTO) to strip secrets.
Audit bundles to ensure database connection strings and API keys never cross the wire.
Prerequisites & Background Knowledge
Why Interviewers Care
A critical interview topic for enterprise frontend engineering. Demonstrates security vigilance against accidental credential leaks.
The Challenge
How do you prevent private backend code and sensitive data fields from leaking into client JavaScript bundles? Demonstrate using server-only and React Taint APIs alongside a Data Transfer Object (DTO) pattern.
Code Architecture & Implementation
1// lib/secrets.ts2import 'server-only'; // Throws a BUILD ERROR if imported by any Client Component!34export const STRIPE_SECRET_KEY = process.env.STRIPE_SECRET_KEY!;5export const INTERNAL_API_TOKEN = process.env.INTERNAL_API_TOKEN!;67export async function processStripePayment(amount: number) {8 // Safe server logic...9}
Architectural Explanation
Because Server Components and Client Components share the same TypeScript codebase, a developer might accidentally import a database utility or pass an entire user record { id, name, email, passwordHash, stripeCustomerId } as a prop to a Client Component. The server-only package halts the build if any client code imports the module. For runtime safety, React's Taint APIs register specific object references or strings with the React serializer; if that value is included in the Flight payload, React throws an error immediately.
Common Mistakes & Anti-Patterns
Passing raw database models directly to Client Components instead of projecting them into sanitized DTOs.
Assuming environment variables without NEXT_PUBLIC_ are always safe from client leaks (they are safe from inlining, but their values can still be passed as props!).
Forgetting that React Taint APIs are an additional defense layer and do not replace proper backend authorization.
Interview Follow-Up Traps
The interviewer asks: "If an environment variable does not have NEXT_PUBLIC_, can it ever reach the browser?" Yes! If a Server Component reads `process.env.SECRET` and passes it as `<ClientWidget secret={process.env.SECRET} />`, it will be sent to the browser in the RSC Flight JSON.
Frequently Asked Questions
Does server-only have a runtime performance overhead?
No. `server-only` is an empty package resolved at build time; it introduces zero runtime overhead.
Are React Taint APIs stable in production?
They are available as experimental features in React 19 / Next.js and are recommended as defense-in-depth in security-sensitive applications.
