Bulk operations that accept an array of IDs and apply WHERE id IN (ids) without scoping to the authenticated user allow cross-user interference: user A includes IDs belonging to user B in their batch and the operation succeeds. CWE-639 (Authorization Bypass Through User-Controlled Key) applies directly — the user controls the ID set. CWE-284 covers the broader access control failure. OWASP A01 flags this as a broken access control pattern. A single bulk-delete endpoint without ownership scoping can allow an authenticated attacker to delete data belonging to any other user in the system.
Medium because the attacker must be authenticated and supply valid IDs, but the ability to affect other users' data at bulk scale is a meaningful authorization failure.
Include the user ownership constraint in the bulk operation's WHERE clause — not as a pre-validation step, but atomically with the operation itself.
// app/api/tasks/bulk-delete/route.ts
const { ids } = await req.json();
// Ownership filter is part of the query — not a pre-check
const result = await db.task.deleteMany({
where: {
id: { in: ids },
userId: session.user.id, // Only affects records the user owns
},
});
// result.count < ids.length means some IDs didn't belong to the user — silently ignored
This pattern is safer than a pre-validation loop because it cannot be bypassed by a race condition between the check and the operation.
ID: saas-authorization.resource-auth.bulk-operations-check-each
Severity: medium
What to look for: Count all relevant instances and enumerate each. Find API endpoints or Server Actions that accept arrays of resource IDs — bulk delete, bulk update, bulk export, multi-select operations. Check how the bulk operation is implemented: does it apply a WHERE clause that includes both the array of IDs AND the user's ID, or does it iterate over IDs without scoping to the current user?
Pass criteria: Bulk database operations include the authenticated user's ID (or equivalent ownership constraint) alongside the array of requested IDs, so the operation only affects resources the user actually owns. At least 1 implementation must be verified.
Fail criteria: A bulk operation accepts an array of IDs and operates on all of them using IN (ids) without adding the user's ownership constraint, allowing a user to affect resources owned by others by including those IDs in the array.
Skip (N/A) when: No bulk operation endpoints detected — the application only supports single-resource operations.
Detail on fail: "Bulk operation at [route] does not scope operation to the authenticated user. An attacker can include arbitrary IDs in the batch." (Note the specific endpoint.)
Remediation: Include the user ownership constraint in the bulk operation's WHERE clause, not as a pre-check. This ensures atomicity — you cannot accidentally operate on resources that sneak past a pre-validation step.
// app/api/tasks/bulk-delete/route.ts
const { ids } = await req.json();
// This single query safely handles both authorization and deletion atomically
const result = await db.task.deleteMany({
where: {
id: { in: ids },
userId: session.user.id, // Only deletes tasks the user actually owns
},
});
// result.count tells you how many were deleted — if it's less than ids.length,
// some IDs didn't belong to the user and were silently ignored.
Cross-reference: For related patterns and deeper analysis, see the corresponding checks in other AuditBuffet audits covering this domain.