Summary

  • GitHub Actions can start a workflow_run workflow when another workflow is requested or completed, and GitHub documents that the downstream workflow can have secrets and write tokens unavailable to the prior workflow.
  • The downstream run does not inherit an artifact-trust verdict: its conclusion conditions, branch filters, checkout, artifact selection, handling context and effective permissions remain separate decisions and records.
  • A defensible statement joins the upstream run and revision, downstream trigger configuration and evaluated conditions, exact artifact and checkout evidence, privilege context, downstream decision, and a time-bounded target observation.

“The publish workflow ran after validation” sounds like a complete chain of custody. It is not. GitHub Actions permits a workflow to listen for the workflow_run event of another workflow, on request or completion. GitHub also states that the downstream workflow can access secrets and write tokens even if the preceding workflow could not. That design can make sense: untrusted or lower-privilege work may produce a candidate result, while a separate workflow performs a tightly governed next step. But it also means that the event boundary is a privilege boundary. It deserves more evidence than an upstream run label.

The first distinction is between completion and acceptance. GitHub says a workflow_run run executes regardless of the prior workflow's conclusion unless the downstream workflow has an explicit condition, such as a test for github.event.workflow_run.conclusion == 'success'. A completed upstream run therefore proves neither successful checks nor that a downstream job evaluated the intended conclusion condition. A workflow name in an event is not the same thing as the workflow-file revision that listened for it, the event payload it received, or the condition expression that actually controlled the privileged step.

Branch filtering is similarly bounded. GitHub documents that workflow_run branch filters apply to the branch of the triggering workflow, with ordered include and exclusion patterns. A declared branches value can be useful evidence of policy intent. It is not proof that a particular artifact came from the expected commit, that the downstream checkout resolved to the same revision, or that an operator's informal phrase—“the release branch passed”—accurately identifies the evaluated ref. The upstream run ID, event action, head branch and head SHA, workflow identity and rerun context need to be retained together if that claim will later matter.

Then comes the artifact. GitHub's event documentation shows a downstream workflow retrieving artifacts associated with the triggering run. That is an access path, not a quality certificate. An artifact can be correctly associated with a run while still being the wrong logical input for a later action. A downstream workflow may choose a different artifact name, download a set rather than one object, unpack it in a different environment, use a different checkout, or feed an artifact into a command that was not contemplated by the upstream validation.

The relevant record is not merely “artifact available.” It is the upstream run identity; artifact name and identifier; content hash and size where available; retrieval time; downstream checkout ref and resolved revision; the command or parser that consumed it; and the isolation or non-execution conditions under which it was handled.

GitHub's secure-use reference gives the reason for this precision. It warns that workflow_run becomes dangerous where privileged workflows check out untrusted pull-request content, and cautions that artifacts should be treated carefully. The warning does not make every artifact unsafe, nor does it diagnose a specific repository. It states the structural problem: a downstream workflow's stronger token, secrets, or shared-cache context can amplify whatever it accepts from upstream. “The upstream workflow passed” is not a substitute for showing what the downstream workflow accepted and what it was permitted to do with it.

This is also why a workflow_run event is not a target-effect receipt. Even a correctly selected artifact may be handled only for inspection. A properly guarded downstream command may be denied by another permission boundary, may exit before calling a target, may act on a different resource, or may complete while a later target observation tells a different operational story. Conversely, an upstream failure may still be recorded in the event stream while a downstream condition prevents any privileged action. The event, the condition, the artifact handling, the command decision and the observed target state are separate points on the map.

The practical answer is a bounded downstream receipt. Preserve the upstream workflow name and run identifier, event action, head branch and SHA, conclusion, attempt or rerun information, and a stable reference to the workflow definition. Preserve the downstream workflow definition revision, the workflow_run selector, branch filters and the condition result that enabled or blocked the consequential job. Preserve exact checkout specifications and resolved SHAs. For every used artifact, preserve the upstream association, identifier or name, cryptographic digest when available, retrieval context and the handling path. Preserve the effective GITHUB_TOKEN permissions, secret availability and any relevant cache or environment boundary without publishing secret values. Finally, preserve the downstream operation result and a separately timed observation of the intended target. Sensitive values can be withheld; the joins cannot be reconstructed after the fact if they were never recorded.

That receipt is deliberately narrower than a blanket claim that the pipeline is “trusted.” It says what the event linked, what the downstream workflow decided, what it consumed, what privilege it held and what was observed. A workflow_run trigger can be a useful control boundary. It should not be asked to certify an artifact, a privileged decision and an operational effect that it did not itself record.

Sources

  1. GitHub Docs — Events that trigger workflows
  2. GitHub Docs — Secure use reference
  3. GitHub Docs — Triggering a workflow