Skip to content

Changed behavior for runner registration breaks re-usable workflows #4202

@brandshaide

Description

@brandshaide

Checks

Controller Version

0.12.1

Deployment Method

Helm

Checks

  • This isn't a question or user support case (For Q&A and community support, go to Discussions).
  • I've read the Changelog before submitting this issue and I'm sure it's not due to any recently-introduced backward-incompatible changes

To Reproduce

1. Deploy most recent version of arc 
2. Utilize a GHA re-usable workflow with a secret being passed to callee (see below)
3. Run fails because it’s been stripped by GH before landing on runner in the first place
4. Do you exactly the same on legacy arc 
5. Works on legacy arc

Describe the bug

Recently we've migrated from the legacy mode of the ARC, resources tied to actions.summerwind.net, to the official supported ARC. We're using our custom runner image and everythings works fine just like it did with the legacy mode except when using a GithUb action workflow like this:

uses: ./.github/workflows/child.yml
secrets:
  platform: ${{ secrets.MY_SP }}

If I'm not mistaken GitHub does not just hand that secret to the callee. It first runs a server-side check:
“Is this job context trusted enough to forward this specific secret into a new workflow run?”

If anything about the context looks less-trusted (event type, cross-repo call without secrets: inherit, etc.), GitHub drops the secret before the job is queued. Our runner never sees those secret(s).

Normal jobs in the same workflow file don’t go through that extra forwarding check; they just get the secret directly.

Can you verify/confirm the observations about different behaviour regarding registration of runners legacy ARC vs. modern ARC:

The legacy ARC (summerwind) — “org-level” but repo-bound at scale-out time

We do configure a RunnerDeployment with organization: <some_of_our_orgs>.

When a job arrives, the autoscaler path (Webhook/HRA) sees the workflow_job webhook, which includes the target repository.

The controller then requests a repo-scoped registration token (POST /repos/{org}/{repo}/actions/runners/registration-token) and starts an ephemeral runner registered against that repo (config.sh --url https://github.com/org/repo), even though our logical config is “org”.

⚠️ Result: for the lifetime of that job, GitHub treats the runner as repo-bound → the callee run in workflow_call is considered a trusted, same-repo context → explicitly mapped secrets pass. ⚠️

As opposed to the new ARC where everyting is strictly organization scoped and GitHub stripping the secrets

New ARC (gha-runner-scale-set) — truly org-only

We register our gha-runner-scale-sets at the respective org levels.

GitHub does the job matching and hands jobs to the pool.

The controller asks for scale-set org tokens (POST /orgs/{org}/actions/runner-scale-sets/{id}/runners/registration-token) and runners register with the org URL (config.sh --url https://github.com/org).

There is no per-job repo registration step. The job payload the runner gets is clearly org-scoped, multi-repo capable.

‼️ GitHub’s backend applies stricter forwarding rules for workflow_call in this context, so explicitly mapped secrets can be stripped between caller → callee. ‼️

Describe the expected behavior

I'd expect the new, official version of the arc to act the exact same way as the legacy solution, especially if this change of behavior is not being mentioned in your docs.

Additional Context

Not required

Controller Logs

Not required

Runner Pod Logs

Not required

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinggha-runner-scale-setRelated to the gha-runner-scale-set modeneeds triageRequires review from the maintainers

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions