Skip to content

Enforce immutability and access restrictions on system type records via the record endpoints #9

Description

@cuibonobo

The general record endpoints (PATCH /records/:id, DELETE /records/:id, PUT /records/:id/permissions, etc.) currently accept requests targeting any record type, including system-defined types. For some of those types, allowing arbitrary edits via the API produces incorrect server behavior or a privilege escalation vector.

_attachment@1 — immutable fields

_attachment@1 records are written once by the server at upload time. Their fields describe physical facts about the stored blob:

  • fileId — content-addressed blob identifier. Changing it severs the link between the metadata record and the stored bytes; GET and DELETE both use this field to locate the blob.
  • size — used as the Content-Length response header. An incorrect value causes some HTTP clients to truncate the response or hang waiting for bytes that never arrive.
  • mimeType — used as the Content-Type response header. An incorrect value causes clients to misinterpret the content; setting it to text/html on an uploaded binary file is a XSS vector if X-Content-Type-Options: nosniff is not set.

filename is the only field with a legitimate reason to change (e.g. a user renaming their upload). fileId, size, and mimeType should be treated as immutable after creation.

Fix: Reject any PATCH /records/:id request that attempts to change fileId, size, or mimeType on an _attachment@1 record.

_grant@1 — privilege escalation

_grant@1 records are the permission system. Each record carries a typeId (which record type the grant covers) and actions (the set of operations permitted). If a non-owner entity holds a grant that includes update-own on _grant@1, they can use PATCH /records/:id to rewrite their own grant record — changing actions to include read-any, update-any, delete-any, etc. — and escalate to arbitrary privileges.

Fix: Reject PATCH /records/:id and DELETE /records/:id requests targeting _grant@1 records from any non-owner entity. Grant management should be owner-only at the API level.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions