Skip to content

Results Service mutation handlers are not consistently bound to the caller's job identity #159

Description

@Bnjoroge1

Severity

P2 / medium cross-job integrity

Review baseline

0bd0e314696e520aa47620cbe8f008d010e01e57

Summary

Some Results/Twirp handlers correctly bind the caller's Actions.Results:{plan}:{job} token to the exact plan/job in the request, but several mutation handlers only rely on the outer generic Results-token check or trust body identifiers directly.

Examples include workflow step updates and log/summary metadata creation. These handlers can accept plan/job/step identifiers without proving that they belong to the token's job.

Why this matters

The signed blob URL minting handlers already use results_token_binds_job(...), demonstrating the intended capability model. The same binding should be enforced for all Results mutations.

Impact

If a job learns another job's backend identifiers, it may be able to alter that job's displayed step state, log metadata, or summary metadata. In a multi-tenant deployment this becomes a cross-job integrity boundary.

Recommended remediation

  • Have the Results auth extractor parse and return a typed JobRuntimeIdentity { plan_id, job_id }.
  • Require that identity in every Results mutation handler.
  • Reject any request body/path whose workflow plan/job ids differ from the authenticated identity.
  • Resolve step ids through the authenticated job rather than treating them as globally writable identifiers.
  • Add negative tests where job A attempts every Results mutation using job B's ids.

Acceptance criteria

  • Every Results mutation is bound to the exact authenticated plan/job.
  • Job A cannot update steps, summaries or log metadata for job B.
  • Signed URL minting and metadata/status mutation use the same typed identity model.
  • Tests cover both JSON and Twirp/protobuf route variants where applicable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions