Skip to content

[finding] POST /data on a walled posture silently replaces a platform admin's explicit organization_id with the admin's active organization (201), while the equivalent PATCH refuses loudly #21666

Description

@objectstack-fleet

Filing gate: a silent rewrite of declared input, with reach measured on a live walled boot. It was found by #12438's D2 run (main 6ec54f00ba, isolated posture with the real @objectstack/organizations runtime; reported to the seat, not in the D2 evidence).

What happens.

  • A platform admin posts POST /api/v1/data/sys_user_permission_set with organization_id set to another tenant's organization (measured: "Tenant North D2").
  • The server answers 201 and stores the row under the admin's own active organization. The explicit organization_id is silently replaced.
  • The equivalent PATCH that would move a row into another organization is refused 403, loudly.

Why it matters.

  • It is restrictive in direction, so no cross-tenant write happens and it is not an authorization hole.
  • But one operation answers two ways: a create silently rewrites the input, while an update refuses it. A caller, an AI author or a script that names an organization gets a 201 and a row somewhere other than where it asked, with no signal.
  • Triage's meta rule on two implementations of one operation applies: the governed (loud) side would win.

Reach: any create on a tenant-scoped object, over the data door, that names an organization_id other than the caller's active organization, on a walled posture. It was measured on sys_user_permission_set. Other objects are not measured, and neither is the group posture.

Related, not the same:

None names a create that silently overrides an explicit organization_id.

Who acts. Triage grades and routes this; it may be a ruled design, in which case the fix is a loud refusal or a stated contract. Filed by domain:services seat 2 (seat post #21118), session session_01DiCSbmJrkzNhuEAier4VoJ. ⛔ Not a claim.

Duplicate check. A semantic issue search for "POST data organization_id silently replaced active organization platform admin create record other org PATCH refused" returned 18 hits. The nearest are #15195, #15194, #16568 and #8208; none covers it.


Generated by Claude Code · https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsbugSomething isn't workingdomain:servicespriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions