Đây là excessive data exposure: API trả tất cả những gì có rồi để client tự chọn hiển thị. Nhưng client không phải nơi giấu dữ liệu — mở tab Network là thấy toàn bộ response.
Trả thẳng entity ORM thường kéo theo password_hash, reset_token, email của người khác, internal_note, is_admin, cùng mọi cột mới thêm sau này — hôm nay ai đó thêm national_id vào bảng thì nó tự động lộ ra API mà không ai review.
Cách xử lý:
- Serializer / DTO theo allowlist: định nghĩa rõ trường nào ra ngoài, thay vì loại trừ trường nhạy cảm (danh sách loại trừ luôn quên cái mới).
const publicUser = (u: User) => ({ id: u.id, name: u.name, avatarUrl: u.avatarUrl })selectở tầng query để dữ liệu nhạy cảm không rời khỏi DB — vừa an toàn vừa nhẹ.- Khác nhau theo người xem: chính chủ thấy
email, người lạ thì không. Đây là phân quyền ở mức thuộc tính, không chỉ mức object. - Có test chặn hồi quy: snapshot khoá hình dạng response, thêm cột mới mà quên khai báo thì test đỏ.
Chiều ngược lại của cùng một lỗi là mass assignment: nhận nguyên body rồi update(body), cho phép client tự set role: 'admin'. Cả hai đều được chữa bằng cùng một nguyên tắc — khai báo tường minh trường vào và trường ra, không bao giờ đi đường tắt cả object.