Skip to content

feat: run-script AWS role, SSH key and uv cache, and fix its pre-commit cache - #7

Merged
albertodonato merged 3 commits into
mainfrom
ack/feat/run-script-aws-ssh
Oct 28, 2026
Merged

albertodonato merged 3 commits into
mainfrom
ack/feat/run-script-aws-ssh

Conversation

@albertodonato

@albertodonato albertodonato commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

what

Add four optional parameters to the run-script workflow:

  • aws-role (input): an AWS role to assume through GitHub OIDC with
    aws-actions/configure-aws-credentials before the script runs.
    aws-region (input, default us-east-1) sets its region.
  • SSH_PRIVATE_KEY (secret): an SSH key for the script, written to
    ~/.ssh/run-script-key and named in ~/.ssh/config, for example a deploy
    key pre-commit needs to clone a private hook repository.
  • uv-cache (input, default false): restores uv's cache, falling back to the
    newest one when uv.lock moved, and prunes it with uv cache prune --ci
    and saves it off pull requests.

Neither cache is restored for pull requests from forks of a public
repository. A trusted run may have filled them with private packages or
clones of private hook repositories, which the fork's script could read.
Forks of a private repository belong to people who can already read it, so
those still restore.

It also fixes the pre-commit cache. The key now covers the mise config and
lockfiles and the selected mise-env as well as .pre-commit-config.yaml,
and PREK_HOME is exported from $HOME in the script instead of set in the
step's env:.

The workflow no longer sets permissions of its own, so its job runs with
exactly what the caller grants. OIDC needs id-token: write, and a called
workflow can't be granted more than its caller has, so requesting it here
would likely fail every caller that doesn't grant it. Existing callers
already grant contents: read, so they run as before. The caller's grant
is now the only cap on the token github-token exposes, so the input no
longer calls it read-only, and the README says to grant nothing beyond
contents: read (plus id-token: write for aws-role).

why

Jobs that install a project's dependencies from a private registry, or
whose pre-commit hooks come from a private repository, can't use
run-script today. Platform's Lint job needs both: AWS credentials for
CodeArtifact and the pre-commit deploy key. Installing its dependencies
on every run is also slow without uv's cache.

Hook environments are built with the toolchains mise installs, so a Python
bump restored environments built against the old interpreter. PREK_HOME
was the literal string ~/.cache/pre-commit, since env: values don't
expand ~, so prek wrote its environments to a ~ directory in the
checkout and the cache step saved an empty one.

testing

actionlint, zizmor, ruff and codespell pass (prek run --all-files).
zizmor accepts the job without a permissions block. This repository's own
CI runs on run-script with pre-commit-cache, so it exercises the
permissions change, the new pre-commit key and PREK_HOME. The AWS, SSH and
uv cache steps run only once a caller passes them, and the fork check only
on a fork's pull request.

docs

The README's run-script section covers the new parameters, both caches
and when they're skipped, the permissions a caller must grant, and an
example caller.

🤖 Generated with Claude Code

albertodonato and others added 2 commits October 27, 2026 14:47
### what

Add three optional parameters to the `run-script` workflow:

- `aws-role` (input): an AWS role to assume through GitHub OIDC with
  `aws-actions/configure-aws-credentials` before the script runs.
  `aws-region` (input, default `us-east-1`) sets its region.
- `SSH_PRIVATE_KEY` (secret): an SSH key for the script, written to
  `~/.ssh/run-script-key` and named in `~/.ssh/config`, for example a deploy
  key pre-commit needs to clone a private hook repository.

The workflow no longer sets permissions of its own, so its job runs with
exactly what the caller grants. OIDC needs `id-token: write`, and a called
workflow can't be granted more than its caller has, so requesting it here
would likely fail every caller that doesn't grant it. Existing callers
already grant `contents: read`, so they run as before.

### why

Jobs that install a project's dependencies from a private registry, or
whose pre-commit hooks come from a private repository, can't use
`run-script` today. Platform's Lint job needs both: AWS credentials for
CodeArtifact and the pre-commit deploy key.

### testing

actionlint, zizmor, ruff and codespell pass (`prek run --all-files`).
zizmor accepts the job without a permissions block. This repository's own
CI runs on `run-script`, so it exercises the permissions change; the AWS
and SSH steps run only once a caller passes them.

### docs

The README's `run-script` section covers both new parameters, the
permissions a caller must grant, and an example caller.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ache

### what

- Add a `uv-cache` input (default false) that restores uv's cache on every
  run, falling back to the newest one when `uv.lock` moved, and prunes it
  with `uv cache prune --ci` and saves it off pull requests.
- Key the pre-commit cache on the mise config and lockfiles and the selected
  `mise-env` as well as `.pre-commit-config.yaml`.
- Export `PREK_HOME` from `$HOME` in the script instead of setting it in the
  step's `env:`.

### why

Hook environments are built with the toolchains mise installs, so a Python
bump restored environments built against the old interpreter. `PREK_HOME`
was the literal string `~/.cache/pre-commit`, since `env:` values don't
expand `~`, so prek wrote its environments to a `~` directory in the
checkout and the cache step saved an empty one.

### testing

actionlint, zizmor, ruff and codespell pass (`prek run --all-files`). This
repository's CI uses `pre-commit-cache`, so it exercises the new key and
`PREK_HOME`.

### docs

The README's `run-script` section describes both caches.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@albertodonato albertodonato changed the title feat: let run-script assume an AWS role and install an SSH key feat: run-script AWS role, SSH key and uv cache, and fix its pre-commit cache Oct 27, 2026
@albertodonato
albertodonato marked this pull request as ready for review October 27, 2026 16:37
@albertodonato
albertodonato requested a review from a team as a code owner October 27, 2026 16:37

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files

Confidence score: 3/5

  • In .github/workflows/run-script.yml, removing the permission cap can expose a write-scoped token as GH_TOKEN when github-token is enabled. Keep the cap or otherwise ensure the exposed token is limited to read access.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".github/workflows/run-script.yml">

<violation number="1" location=".github/workflows/run-script.yml:32">
P2: Custom agent: **Flag Security Vulnerabilities**

Removing this cap lets a caller with write-enabled defaults expose a write-scoped token as `GH_TOKEN` when `github-token` is enabled, despite the input describing it as read-only. Keep the script’s token read-only, including when adding optional OIDC permissions.</violation>
</file>
Architecture diagram
sequenceDiagram
    participant Caller as Caller Workflow
    participant RS as run-script Workflow
    participant GH as GitHub Actions Runtime
    participant AWS as AWS (CodeArtifact)
    participant SSH as SSH Deploy Key
    participant Mise as mise-action
    participant PreCache as pre-commit Cache
    participant UvCache as uv Cache
    participant Script as User Script (prek)

    Note over Caller,RS: Caller grants permissions (contents:read, optional id-token:write)

    Caller->>RS: Trigger workflow with inputs & secrets
    Note over RS: No permissions block - inherits caller's grants

    RS->>GH: Checkout repository (fetch-depth based on full-git-history)

    alt aws-role provided
        RS->>AWS: configure-aws-credentials via OIDC
        Note over RS,AWS: Assumes role in aws-region (default us-east-1)
        AWS-->>RS: Temporary credentials
    end

    alt SSH_PRIVATE_KEY secret provided
        RS->>RS: Install SSH key to ~/.ssh/run-script-key
        RS->>RS: Configure ~/.ssh/config with IdentityFile
    end

    RS->>Mise: Install toolchains (mise-action with cache)
    Mise-->>RS: Toolchains ready

    opt pre-commit-cache enabled
        RS->>PreCache: Restore cache
        Note over RS,PreCache: Key includes .pre-commit-config.yaml, mise config files, mise-env, runner OS/arch
        PreCache-->>RS: Cache hit or miss
    end

    opt uv-cache enabled
        RS->>UvCache: Restore cache
        Note over RS,UvCache: Key based on uv.lock, falls back to newest by runner OS/arch
        UvCache-->>RS: Cache hit or miss
    end

    RS->>Script: Run user script
    Note over Script: PREK_HOME exported as $HOME/.cache/pre-commit
    Note over Script: GH_TOKEN unset if empty

    alt post-run on non-PR event with cache miss
        opt pre-commit-cache enabled
            RS->>PreCache: Save cache (pruned/updated hook environments)
        end
        opt uv-cache enabled
            RS->>RS: Run "uv cache prune --ci" (drop pre-built wheels)
            RS->>UvCache: Save pruned cache
        end
    end

    Note over RS: Cache saves gated off pull requests to prevent cache poisoning
Loading

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread .github/workflows/run-script.yml Resolved
jobs:
run:
runs-on: ubuntu-latest
permissions:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Custom agent: Flag Security Vulnerabilities

Removing this cap lets a caller with write-enabled defaults expose a write-scoped token as GH_TOKEN when github-token is enabled, despite the input describing it as read-only. Keep the script’s token read-only, including when adding optional OIDC permissions.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At .github/workflows/run-script.yml, line 32:

<comment>Removing this cap lets a caller with write-enabled defaults expose a write-scoped token as `GH_TOKEN` when `github-token` is enabled, despite the input describing it as read-only. Keep the script’s token read-only, including when adding optional OIDC permissions.</comment>

<file context>
@@ -22,17 +26,30 @@ on:
+      aws-role:
+        type: string
+        description: "ARN of an AWS role to assume through GitHub OIDC before the script runs. The caller must grant id-token: write"
+        default: ""
+      aws-region:
+        type: string
</file context>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing this is required for callers to be able to pass the required permissions (based on which features are enabled).

This is only an issue in case where a third party component (script, library, pre-commit hook) are compromised in a way that they extract secrets (like the GH token).

A third-party PR from a fork on a public repo won't run into this issue.

A trusted run can fill the pre-commit and uv caches with private packages
or clones of private hook repositories, which a fork's script could read.
Skip restoring them for pull requests from forks of a public repository.

Also stop calling the github-token token read-only: the job takes the
caller's permissions, so the caller's grant is the only cap on it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@Ahmore Ahmore left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks @albertodonato

@albertodonato
albertodonato merged commit a1be6a1 into main Oct 28, 2026
4 checks passed
@albertodonato
albertodonato deleted the ack/feat/run-script-aws-ssh branch October 28, 2026 10:43
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.

2 participants