Skip to content

    Back to articles

    6 min read

    Plan GitHub Actions investigations around evidence

    Start with the questions, not the stream

    A security investigation is only as good as the evidence it can still retrieve. Before I adopt a new feed from a CI platform, I would write down what an investigator must be able to establish after a workflow incident: which workflow ran, what code and dependencies it used, what it changed, and which identity or event started it. Then I would ask whether the record answers those questions after ordinary run logs have been changed or removed.

    That distinction matters in the GitHub Actions roadmap discussion. GitHub describes the forthcoming Actions Data Stream as near-real-time execution telemetry delivered centrally to destinations such as Amazon S3 and Azure Event Hub or Data Explorer in its 2026 Actions security roadmap. In a GitHub community discussion about the roadmap, a GitHub representative describes the intended stream as an immutable source of truth for workflow activity and a replacement for run logs in security investigations.

    That is a promising direction, not an investigation plan. “Immutable” does not tell me which events are recorded, what fields they contain, how I correlate them, how long they remain available, or which roles can change the record or its destination. I would not treat the label as proof that the evidence is complete or durable. I would use it to ask sharper questions of the proposed feature and of my own operating model.

    Write the investigation contract

    I would begin with a small set of investigation questions, phrased so that someone who did not build the workflow can answer them. For example: Which workflow and job ran? What revision and dependency references did the run resolve? Which actor, trigger and repository initiated it? What runner executed it? Which steps completed, failed or were skipped? What artifact was produced, and where did it go?

    Those are questions, not a claim that the stream records every answer. The roadmap describes execution telemetry, but the published description is not a field-by-field event contract. I would compare the documented event types and schema with the questions before promising responders that the stream supports them. If an answer depends on a separate source, such as a deployment record or artifact registry, I would name that source and test the correlation rather than silently assume the stream contains it.

    I would capture the contract in a short table that belongs with the incident-response runbook:

    Investigation questionEvidence sourceCorrelation keyRequired retentionOwner
    Which workflow execution is under review?Actions Data Stream, if the event schema supports itRun identifier and repositorySet by incident policyPlatform team
    What revision and dependencies did it use?Stream fields, plus any necessary repository evidenceRun identifier and resolved referenceSet by incident policyWorkflow owners
    What artifact did it publish, and where?Stream plus artifact or deployment recordRun identifier and artifact digestSet by incident policyRelease owners

    This is a proposed working template, not a description of GitHub’s schema. I would replace each tentative source with a verified event or system, and leave a question marked unsupported if no reliable evidence answers it. That gap is useful: it exposes where a workflow needs better provenance, where a separate system needs to retain a record, or where responders must accept uncertainty.

    Treat retention and integrity as design requirements

    Evidence has to outlast the period in which someone might need it. A team should decide that period from its own incident-response and compliance requirements, rather than inherit a retention default without discussion. GitHub’s documentation says the configured retention policy applies to checks, workflow runs, commit statuses, artifacts and logs from October 1, 2026; it also explains how to configure the organization’s retention period in GitHub’s retention-period documentation. That makes it especially important to review what the organization’s current setting covers and whether it meets the investigation contract.

    A centralized stream could help separate retained investigation evidence from the lifecycle of an individual run log. But I would verify the mechanics before relying on that separation. Does the destination retain events for the required period? Can an administrator or compromised credential delete or alter them? Are failed deliveries visible and recoverable? Can the team show that records arrived intact, and identify gaps in collection? “Immutable” at one point in the path does not automatically make every copy, export, or downstream system immutable.

    I would assign an owner to each part of the chain: configuring the source, operating the destination, monitoring delivery, controlling access, and restoring evidence for an investigation. I would also define what happens when the stream is unavailable. If the answer is “we will look at run logs,” then logs are still a dependency and their own retention and permissions belong in the plan. If there is no fallback, responders need to know that a telemetry gap may leave a question unanswered.

    Prove the workflow before an incident

    I would test the evidence path using a controlled workflow change, not wait for a real incident to find out what arrives. Start a run, make a harmless change that can be recognized in the output, and follow the evidence from its source into the destination. Confirm that the records can be searched by the identifiers responders will have, that timestamps and repository context are interpretable, and that the record answers the questions in the contract. Then test the less comfortable cases: a failed run, a cancelled run, a run that produces no artifact, and a missing or delayed event.

    For reusable pipelines, I would include the distinction between the shared workflow and the calling repository in those checks. A useful investigation needs to identify both where the execution logic came from and which repository invoked it. I would not assume that one run identifier or one repository name is enough to reconstruct the relationship; I would verify the actual fields and joins available in the stream and any linked records.

    Finally, I would have someone follow the runbook without relying on the person who designed the pipeline. Can they find a run, reconstruct the relevant execution path, explain any missing evidence, and state how long the records remain available? If not, the problem is not solved by adding another data feed. It is solved when the evidence contract, retention policy, permissions and responder procedure work together.

    I would adopt Actions Data Stream when its verified records answer the investigation questions the team has chosen, and when the organization can preserve and retrieve them under its own requirements. Until then, I would treat it as a capability to evaluate—not as a substitute for deciding what an investigation must prove.

    Drafted with AI assistance, reviewed and edited by Ali.