Artifact cross-repo isolation must be enforced store-side, not in the action #19

Open
opened 2026-07-05 20:57:27 +00:00 by stephen · 0 comments
Owner

Requirement

Artifact cross-repo isolation must be enforced by the artifact store or broker, not by JavaScript running inside the workflow job.

The store component that fronts S3 must scope artifact reads and writes by a credential/token the CI job can never mint, widen, or replace. The trusted runner/forge/broker should validate the real run identity out of band and issue a repo-scoped, short-lived artifact credential/token for that run. This should mirror the Fjord repo-scoped token model used for flux runner registration: the job can at most present the token to the store; it cannot choose the repository scope or provide the trust anchor.

Concretely:

  • Stop exposing one shared long-lived RASTER_ARTIFACTS_S3_* credential to arbitrary jobs.
  • Broker/store validates the run's actual repository from Forgejo/runner-side state, not from job env.
  • Broker/store issues credentials or an access token restricted to that repository's artifact prefix for reads/writes.
  • Store rejects access outside the token's repository prefix regardless of GITHUB_REPOSITORY, action inputs, or other job-controlled env.
  • The download/upload actions may pass the broker-issued token, but must not be considered an enforcement point.

Evidence

Two action-side fixes were bypassed because the action runs inside the attacker's job and all env-based trust anchors are attacker-controlled:

  • #16 CHANGES reproduction: GITHUB_REPOSITORY was set to the victim repo and the shared credential read rasterstate/paragon artifacts, extracting VICTIM-SECRET: #16 (comment)
  • #18 CHANGES reproduction: the signed-claim approach was bypassed because RASTER_ARTIFACTS_SCOPE_PUBLIC_KEY was also job-controlled; the attacker self-signed a victim-scope claim and again extracted VICTIM-SECRET: #18 (comment)

Even a pinned in-action verifier would not be sufficient while the shared S3 credential is present in the job, because an attacker can bypass the action entirely and call S3 directly.

Coordination

This likely needs a coordinated change in the artifact-store/broker component and matching upload/download action wiring. The action repos should not claim #15 is closed until the store-side boundary is deployed and tests prove a job from repo A cannot read or write repo B's artifact prefix using any job-controlled env or direct S3 calls.

## Requirement Artifact cross-repo isolation must be enforced by the artifact store or broker, not by JavaScript running inside the workflow job. The store component that fronts S3 must scope artifact reads and writes by a credential/token the CI job can never mint, widen, or replace. The trusted runner/forge/broker should validate the real run identity out of band and issue a repo-scoped, short-lived artifact credential/token for that run. This should mirror the Fjord repo-scoped token model used for flux runner registration: the job can at most present the token to the store; it cannot choose the repository scope or provide the trust anchor. Concretely: - Stop exposing one shared long-lived `RASTER_ARTIFACTS_S3_*` credential to arbitrary jobs. - Broker/store validates the run's actual repository from Forgejo/runner-side state, not from job env. - Broker/store issues credentials or an access token restricted to that repository's artifact prefix for reads/writes. - Store rejects access outside the token's repository prefix regardless of `GITHUB_REPOSITORY`, action inputs, or other job-controlled env. - The download/upload actions may pass the broker-issued token, but must not be considered an enforcement point. ## Evidence Two action-side fixes were bypassed because the action runs inside the attacker's job and all env-based trust anchors are attacker-controlled: - #16 CHANGES reproduction: `GITHUB_REPOSITORY` was set to the victim repo and the shared credential read `rasterstate/paragon` artifacts, extracting `VICTIM-SECRET`: https://rasterhub.com/rasterstate/download-artifact-action/pulls/16#issuecomment-22042 - #18 CHANGES reproduction: the signed-claim approach was bypassed because `RASTER_ARTIFACTS_SCOPE_PUBLIC_KEY` was also job-controlled; the attacker self-signed a victim-scope claim and again extracted `VICTIM-SECRET`: https://rasterhub.com/rasterstate/download-artifact-action/pulls/18#issuecomment-22087 Even a pinned in-action verifier would not be sufficient while the shared S3 credential is present in the job, because an attacker can bypass the action entirely and call S3 directly. ## Coordination This likely needs a coordinated change in the artifact-store/broker component and matching upload/download action wiring. The action repos should not claim #15 is closed until the store-side boundary is deployed and tests prove a job from repo A cannot read or write repo B's artifact prefix using any job-controlled env or direct S3 calls.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
rasterstate/download-artifact-action#19
No description provided.