OIDC Configured but GitHub Actions Still Vulnerable: Megalodon and actions-cool Attacks Expose Runner Risks

Even after widespread adoption of OIDC for temporary cloud credentials in GitHub Actions, two major attacks in May 2026 demonstrated that the approach remains insufficient on its own. Attackers compromised actions-cool/issues-helper by substituting action tags to execute malicious commits that read Runner.Worker memory. The Megalodon campaign injected malicious workflows into 5,561 public repositories, harvesting environment variables, credential files, kubeconfig, SSH keys, and OIDC tokens. OIDC eliminates long-lived AWS_ACCESS_KEY_ID secrets but leaves short-lived tokens exposed inside the runner during job execution. Four mandatory protection layers are now required: strict cloud trust policies using StringEquals on the sub claim, job-level id-token: write permissions, outbound traffic controls such as Harden-Runner, and CODEOWNERS enforcement on .github/workflows/. GitHub Environments with mandatory reviewers add an essential human-approval gate that would have disrupted the Megalodon attack path.

HabrTranslated from Russian

Read at source

Two years of advising teams to replace static AWS_ACCESS_KEY_ID secrets with OIDC in GitHub Actions remains valid advice, yet recent incidents show that OIDC alone is no longer enough. After the May 2026 attacks on actions-cool/issues-helper and the Megalodon campaign targeting 5,561 repositories, the recommendation must be expanded to include multiple defensive layers around OIDC.

The core problem is that temporary credentials issued via OIDC become usable data inside the runner for the duration of the job. These credentials can appear as environment variables exported by aws-actions/configure-aws-credentials, as files on disk, or as tokens requested by individual steps. Any code running on the same runner—malicious third-party actions, compromised post-install scripts, or direct memory reads from /proc—can extract them.

Megalodon directly injected malicious workflows that collected environment variables, credential files, kubeconfig files, SSH keys, and OIDC tokens. A 15-to-60-minute token lifetime proved sufficient for automated exfiltration and reuse before expiration. The actions-cool/issues-helper attack instead substituted action tags to run a malicious commit capable of reading Runner.Worker process memory.

Four protection layers are now considered mandatory. First, cloud trust policies must use StringEquals on the exact sub claim, for example limiting access to repo:my-org/my-repo:environment:production. Second, the id-token: write permission must be granted only at the job level, never at the workflow level. Third, outbound traffic from runners must be restricted using Harden-Runner in block mode or equivalent firewall rules on self-hosted runners. Fourth, the .github/workflows directory must be treated as production code with CODEOWNERS requiring security-team review and all third-party actions pinned by SHA.

GitHub Environments provide an additional control often overlooked: mandatory reviewers, deployment timers, and branch restrictions. When a trust policy also requires the environment claim, an attacker who can push to main still cannot obtain a production token without passing human approval.

The updated checklist after Megalodon includes moving id-token: write to job scope, binding production jobs to protected environments, tightening trust policies, adding CODEOWNERS, and controlling runner egress. Workflows named SysDiag or Optimize-Build should be treated as indicators of compromise.

Meridian digestThe week's most consequential security stories, distilled into one briefing.See the digest

More in Supply Chain & Open Source

Passwordless Kubernetes Image Pulling with Artifact Keeper via ServiceAccount Tokens
Malicious Code Injected into LiteLLM Open Source AI Package via Supply Chain Attack
GhostAction Campaign Compromises 790 GitHub Repositories via Malicious Workflows