Q73: What is the Server-Side Data Exposure anti-pattern in Server Components and how do Data Transfer Objects (DTOs) resolve it?

When a Server Component queries a database record (SELECT * FROM users), the resulting database object may contain private hash fields (password_hash, two_factor_secret). Passing this raw object to a Client Component prop serializes all object keys into the RSC Flight stream exposed in browser devtools. Using Data Transfer Objects (DTOs) strips non-public keys before passing props.

DTO Mapping Anti-Pattern vs Fix
// ❌ DANGEROUS: Exposes password_hash in browser devtools Flight payload!
export default async function Page() {
  const user = await db.user.findUnique({ id: 1 });
  return <UserProfile user={user} />; // Client Component
}

// ✅ SAFE DTO PATTERN: Explicitly pick public fields
export default async function Page() {
  const user = await db.user.findUnique({ id: 1 });
  const userDTO = { id: user.id, name: user.name, avatar: user.avatar }; // Strips password_hash
  return <UserProfile user={userDTO} />;
}
💡 Explicitly selecting public properties in a DTO prevents secret database column keys from leaking into client network payloads.
Key Takeaways
  • Never pass raw database model objects containing private fields directly into Client Component props.
  • Map database models to explicit public Data Transfer Objects (DTOs) before returning data.
Knowledge Check

Why is passing raw database records (e.g., Prisma model outputs) directly into Client Component props considered a security anti-pattern?