Skip to content

feat: protect against scope column reassignment in updates#17

Merged
benvinegar merged 1 commit into
mainfrom
fix/scoped-updates-reassign-protection
Jun 26, 2026
Merged

feat: protect against scope column reassignment in updates#17
benvinegar merged 1 commit into
mainfrom
fix/scoped-updates-reassign-protection

Conversation

@benvinegar

Copy link
Copy Markdown
Member

Problem

Currently, scoped updates (via createScopedUpdateBuilder) validate and constrain which rows are updated (by injecting the scope predicate into the WHERE clause), but they don't constrain what values can be written to the scope column (e.g., workspaceId / tenantId).

If a caller controls the update payload, they can potentially move a row across tenants/scopes:

await scopedDb
  .update(projects)
  .set({ workspaceId: "workspace-2" }) // Mismatched target scope value!
  .where(eq(projects.id, projectId));
// ↑ Updates the row in workspace-1 and reassigns its owner to workspace-2

Fix

  1. Add to and export it publicly.
  2. Add support for inside .
  3. Update to automatically define using (which falls back to the configured by default for ease of setup).
  4. Update in to execute if present when is called. If the payload attempts to modify the scope column to any value that doesn't match the active , it throws an (or a customized error from ).

Validation

  • Added full unit tests covering:
    • Non-scope column updates (should pass).
    • Scope column updates with the correct, matching scope value (should pass).
    • Scope column updates with a different, mismatched scope value (should throw ).
    • Custom configuration.
    • Custom error factory validation.
  • All checks fully green with 100% statement, branch, function, and line coverage:
pnpm format:check  ✓
pnpm lint          ✓  (0 warnings, 0 errors)
pnpm typecheck     ✓
pnpm test          ✓  (35/35, +3 new regression tests)
pnpm coverage      ✓  (100% across all metrics)
pnpm build         ✓

@benvinegar benvinegar merged commit 2212024 into main Jun 26, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant