Excessive Data Exposure in Express with Cockroachdb
Excessive Data Exposure in Express with Cockroachdb
Excessive Data Exposure occurs when an API returns more data than the client needs, often including sensitive fields such as internal identifiers, administrative flags, or personally identifiable information (PII). In an Express application using Cockroachdb, this risk arises from the combination of broad query selection, missing field-level authorization, and improper serialization of database rows.
With Cockroachdb, which provides a PostgreSQL-compatible wire protocol, developers commonly use SELECT * or map rows directly to JSON responses. If a user profile endpoint executes SELECT * FROM users WHERE id = $1 and returns the row as-is, fields like password_hash, role, email_verified, or internal_api_key may be exposed to the client. This becomes more pronounced when joins are used across tables (e.g., user preferences or audit logs) without explicitly selecting only required columns.
Another common pattern in Express with Cockroachdb is using an ORM or query builder that returns full table models. For example, an endpoint like /api/users/:id might call UserModel.findByPk(id) and send the instance data directly via res.json(user). If the model includes timestamps, UUIDs, or internal state, those values are transmitted even when not needed by the client or UI. Without explicit field filtering or schema-aware serialization, the API surface grows and increases the impact of any additional vulnerability such as IDOR.
The risk is compounded when responses include nested objects or arrays from related tables. A query joining users and profiles might return profile data that contains sensitive preferences or location details. Even if the endpoint requires authentication, missing field-level controls can expose data that should be restricted by role or consent settings. In a Cockroachdb-backed Express service, this often traces back to unparameterized queries or unchecked assumptions about which columns are safe to return.
To illustrate, consider an Express route that queries Cockroachdb without column restrictions:
app.get('/api/users/:id', async (req, res) => {
const result = await pool.query('SELECT * FROM users WHERE id = $1', [req.params.id]);
res.json(result.rows[0]);
});
This pattern returns every column in the users table, including sensitive fields. An attacker who gains access to this endpoint (e.g., via IDOR) can harvest password hashes, email addresses, or internal flags. The same issue occurs with ORMs when relations are eagerly loaded without scoping.
Effective mitigation requires explicit column selection and consistent serialization that omits sensitive fields. In Cockroachdb, you should list only required columns in queries and transform the result before sending it to the client. For Express, this means avoiding generic row-to-JSON helpers and instead defining a projection that matches the client contract. Security checks in middleBrick validate whether responses include unnecessary fields and whether queries reference broad selections, helping teams identify and reduce exposure in services backed by Cockroachdb.
Cockroachdb-Specific Remediation in Express
Remediation focuses on strict column selection, avoiding raw SELECT *, and ensuring serialized output excludes sensitive fields. When working with Cockroachdb in Express, define explicit queries that return only the fields required for the operation. This reduces the data footprint and limits the impact of IDOR or broken access control issues.
For example, instead of selecting all columns, specify the columns you need:
app.get('/api/users/:id', async (req, res) => {
const result = await pool.query(
'SELECT id, username, email, created_at FROM users WHERE id = $1',
[req.params.id]
);
res.json(result.rows[0]);
});
This approach ensures that password hashes, role flags, or internal metadata are not returned. Combine this with a serialization layer if you need to rename or shape fields for the client without changing the database schema.
When using an ORM, configure models to exclude sensitive fields from JSON output. For instance, if you use an ORM that maps table columns to properties, override toJSON or use a DTO (data transfer object) to control what is serialized:
const userData = {
id: user.id,
username: user.username,
email: user.email,
createdAt: user.created_at
};
res.json(userData);
For complex queries involving joins, explicitly list joined columns and avoid returning entire related rows. With Cockroachdb, you can alias joined fields to keep the response clean:
app.get('/api/users/:id/profile', async (req, res) => {
const result = await pool.query(`
SELECT
u.id,
u.username,
p.bio,
p.locale
FROM users u
JOIN profiles p ON u.id = p.user_id
WHERE u.id = $1
`, [req.params.id]);
res.json(result.rows[0]);
});
This prevents accidental exposure of columns from the profiles table that might include sensitive preferences or internal flags. It also aligns with the principle of least privilege for data exposure.
Where feasible, implement field-level filtering based on roles or scopes. For example, an admin endpoint might include additional fields, while a public endpoint omits them. Use middleware to transform responses consistently rather than relying on ad-hoc queries across the codebase.
middleBrick scans help identify endpoints that use SELECT * or return full model instances without field filtering. By integrating the CLI (middlebrick scan <url>) or the GitHub Action into your CI/CD pipeline, you can fail builds when findings indicate excessive data exposure. The dashboard lets you track progress as you refine queries and reduce the sensitive data returned by your Express services backed by Cockroachdb.
Related CWEs: propertyAuthorization
| CWE ID | Name | Severity |
|---|---|---|
| CWE-915 | Mass Assignment | HIGH |