6 min read
Make secret access explicit in reusable workflows
A reusable workflow is a contract
A shared pipeline makes a promise to its callers: provide the inputs it needs, and it will perform a defined job. Secret access belongs in that promise. If a workflow can use credentials merely because they happen to be available in the calling repository, the contract is incomplete.
I have helped design and roll out CI/CD pipelines reused across hundreds of repositories. That experience makes me wary of treating a workflow as a convenient YAML fragment. A shared workflow is also a security boundary, and its callers need to know what crosses that boundary.
GitHub’s 2026 Actions security roadmap proposes scoped secrets for reusable workflows, alongside near-real-time execution telemetry. The roadmap describes a shift toward binding secrets to trusted execution contexts rather than broadly inheriting them. These are proposed capabilities, not controls I would assume are already available. But the direction is useful now: it asks platform teams to make credential access deliberate and verifiable.
Today, GitHub supports explicitly passing named secrets to a reusable workflow, as well as using secrets: inherit in supported cases. The workflow syntax documentation describes both patterns and the workflow_call secret declarations. In my view, explicit passing is the better default for shared workflows because it makes the caller’s grant visible where the call is made. Inheritance can be convenient, but convenience should not silently define the trust boundary.
Inventory access before changing YAML
The first rollout task is not to edit every caller. It is to learn what credentials the workflows actually need.
I would start with an inventory of reusable workflows and the secrets each one reads. For each credential, record its purpose, which workflow uses it, which execution paths need it, and what authority it carries. A workflow that builds and tests code may need no long-lived deployment credential at all. A publishing workflow might need a package registry token; a deployment workflow might need access to a target environment. Those are different jobs with different trust requirements, even if they currently sit in one shared pipeline.
The inventory should distinguish direct use from accidental availability. A secret being present in a repository does not prove that every reusable workflow called from that repository needs it. Ask workflow owners to confirm each dependency, and treat an unexplained credential as a reason to investigate rather than as a reason to preserve broad access.
Then define the contract at both ends. The reusable workflow should declare the secrets it expects, with names that communicate purpose. The caller should pass only those secrets, using the names the reusable workflow declares. GitHub documents this named-secret pattern, including a validation error when a caller passes a secret that the called workflow has not specified. See the workflow syntax reference.
That contract is not just a list. It should also say which jobs or steps consume a credential, and why. If a secret is only needed during deployment, keeping it out of build and test paths is a better design than making the entire reusable workflow depend on it. If one reusable workflow performs unrelated tasks with different credentials, split it or separate the jobs so the access boundary matches the work.
Make trust boundaries visible
Explicit passing improves the caller’s view of access, but it is not a complete security model. A grant only makes sense in the context of the code that receives it, the event that starts it, and the permissions available to the workflow. A narrowly named secret passed to an overly broad workflow is still a broad trust decision.
I would review callers by trust level, not just by repository. Which events can invoke the workflow? Can untrusted contributions reach a job that handles credentials? Is the reusable workflow pinned and reviewed according to the organization’s policy? Does the job’s GITHUB_TOKEN permission set match its work? GitHub’s secure use guidance covers risks in workflows and reused code; secret scoping should sit alongside those controls, not stand in for them.
The practical test is whether a reviewer can follow the path from caller to credential without guessing. The caller shows what it grants; the reusable workflow declares what it accepts; the job shows where it is used. If a credential appears only through implicit inheritance, that path is harder to see in review. I would migrate away from inheritance where possible, and document any exception with the reason it remains necessary.
This is also why I would resist a single organization-wide “pipeline secret” available to every shared workflow. One reusable workflow may need to publish an artifact while another deploys it. Giving both the same powerful credential erases the distinction between those responsibilities. Separate credentials by purpose and limit which caller-workflow combinations can receive them. Where a platform offers a short-lived identity mechanism that meets the use case, prefer evaluating that over adding another long-lived secret; do not assume it eliminates the need to define who is trusted to request it.
Roll out in stages, then measure
A fleet-wide change should begin with a small pilot, not a mass edit. Choose representative workflows: one that needs no secret, one that needs a narrowly scoped credential, and one with a more complex call chain. Make the intended contracts explicit, run them through normal changes, and ask maintainers to identify where the new model is unclear. The pilot should expose naming problems and hidden dependencies before they are multiplied across repositories.
Next, migrate by workflow family. Publish the new contract and a short migration guide, then update callers in manageable batches. For each batch, track which callers have been migrated, which still rely on inheritance, and why any exception remains. Keep a rollback path while teams verify the behavior. Avoid turning a temporary compatibility measure into a permanent permission model simply because it was convenient during rollout.
Telemetry can make that process more than a checklist. The roadmap’s proposed Actions Data Stream points toward centralized, near-real-time execution data. If the eventual data includes useful workflow and secret-access context, I would use it to answer operational questions: which workflows are still using the old pattern, whether a migrated caller runs as expected, and whether unexpected execution paths are reaching sensitive jobs. The roadmap describes the direction; teams should verify the actual fields and availability before designing controls around them.
I would define those questions before the telemetry arrives. Decide what evidence proves migration, who reviews exceptions, and how a team will investigate an unexpected execution. Then connect the evidence to the workflow inventory and ownership model. Telemetry without an owner or a response process is just another stream of events. Conversely, a dashboard that only counts successful runs cannot establish that secret access is appropriately scoped.
The goal is not to make every reusable workflow complicated. It is to make the important boundary legible: a caller grants a particular workflow the credentials required for a particular job, and the organization can verify that the grant is being used as intended. Scoped secrets could make that contract enforceable at the platform level. The work of deciding what should be trusted still belongs to the teams designing the pipeline.
Drafted with AI assistance, reviewed and edited by Ali.