VYPR
Medium severity6.0NVD Advisory· Published Apr 21, 2025· Updated Apr 15, 2026

CVE-2025-32955

CVE-2025-32955

Description

Harden-Runner is a CI/CD security agent that works like an EDR for GitHub Actions runners. Versions from 0.12.0 to before 2.12.0 are vulnerable to disable-sudo bypass. Harden-Runner includes a policy option disable-sudo to prevent the GitHub Actions runner user from using sudo. This is implemented by removing the runner user from the sudoers file. However, this control can be bypassed as the runner user, being part of the docker group, can interact with the Docker daemon to launch privileged containers or access the host filesystem. This allows the attacker to regain root access or restore the sudoers file, effectively bypassing the restriction. This issue has been patched in version 2.12.0.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
step-security/harden-runnerGitHub Actions
>= 0.12.0, < 2.12.02.12.0

Patches

1
0634a2670c59

Merge pull request #541 from step-security/rc-20

https://github.com/step-security/harden-runnerVarun SharmaApr 21, 2025via ghsa
13 files changed · +49 17
  • action.yml+5 1 modified
    @@ -17,7 +17,11 @@ inputs:
         required: false
         default: "false"
       disable-sudo:
    -    description: "Disable sudo access for the runner account"
    +    description: "Disable sudo access for the runner account. Note: This parameter will be deprecated in the future. Please use disable-sudo-and-containers instead."
    +    required: false
    +    default: "false"
    +  disable-sudo-and-containers:
    +    description: "Disable sudo and container access for the runner account"
         required: false
         default: "false"
       disable-file-monitoring:
    
  • dist/post/index.js+2 1 modified
    @@ -27947,7 +27947,8 @@ var cleanup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _
             console.log(content);
         }
         var disable_sudo = process.env.STATE_disableSudo;
    -    if (disable_sudo !== "true") {
    +    var disable_sudo_and_containers = process.env.STATE_disableSudoAndContainers;
    +    if (disable_sudo !== "true" && disable_sudo_and_containers !== "true") {
             try {
                 var journalLog = external_child_process_.execSync("sudo journalctl -u agent.service --lines=1000", {
                     encoding: "utf8",
    
  • dist/post/index.js.map+1 1 modified
  • dist/pre/index.js+12 5 modified
    @@ -87890,6 +87890,9 @@ function mergeConfigs(localConfig, remoteConfig) {
         if (remoteConfig.disable_sudo !== undefined) {
             localConfig.disable_sudo = remoteConfig.disable_sudo;
         }
    +    if (remoteConfig.disable_sudo_and_containers !== undefined) {
    +        localConfig.disable_sudo_and_containers = remoteConfig.disable_sudo_and_containers;
    +    }
         if (remoteConfig.disable_file_monitoring !== undefined) {
             localConfig.disable_file_monitoring = remoteConfig.disable_file_monitoring;
         }
    @@ -88004,11 +88007,11 @@ var external_crypto_ = __nccwpck_require__(6417);
     
     const CHECKSUMS = {
         tls: {
    -        amd64: "38e7ed97ced6fe0c1cf0fb5ee3b3d521dfe28d5ddf1cdca72d130c8d1b4a314e",
    -        arm64: "f67c80cc578c996d4f882c14fcdb63df57927d907cd22f1ec65f9fa940c08cf3",
    +        amd64: "e7c0c5f96efbf96806d27dcbf65f71f72ecd34cdd596c556bb2ded0f2037c260",
    +        arm64: "813a4cd40f6740bd9623a40884a78f14960c6bd3794391693a165f2ca71c90e3",
         },
         non_tls: {
    -        amd64: "a9f1842e3d7f3d38c143dbe8ffe1948e6c8173cd04da072d9f9d128bb400844a", // v0.13.7
    +        amd64: "f0a8bb49ce5480744f8c836af2abd5f311e918efef5b36b4cce7521d7b9dffe6", // v0.14.0
         },
     };
     function verifyChecksum(downloadPath, isTLS, variant) {
    @@ -88058,14 +88061,14 @@ function installAgent(isTLS, configStr) {
                 encoding: "utf8",
             });
             if (isTLS) {
    -            downloadPath = yield tool_cache.downloadTool(`https://packages.stepsecurity.io/github-hosted/harden-runner_1.4.2_linux_${variant}.tar.gz`);
    +            downloadPath = yield tool_cache.downloadTool(`https://packages.stepsecurity.io/github-hosted/harden-runner_1.6.3_linux_${variant}.tar.gz`);
             }
             else {
                 if (variant === "arm64") {
                     console.log(ARM64_RUNNER_MESSAGE);
                     return false;
                 }
    -            downloadPath = yield tool_cache.downloadTool("https://github.com/step-security/agent/releases/download/v0.13.7/agent_0.13.7_linux_amd64.tar.gz", undefined, auth);
    +            downloadPath = yield tool_cache.downloadTool("https://github.com/step-security/agent/releases/download/v0.14.0/agent_0.14.0_linux_amd64.tar.gz", undefined, auth);
             }
             verifyChecksum(downloadPath, isTLS, variant);
             const extractPath = yield tool_cache.extractTar(downloadPath);
    @@ -88142,6 +88145,7 @@ var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _ar
                 egress_policy: lib_core.getInput("egress-policy"),
                 disable_telemetry: lib_core.getBooleanInput("disable-telemetry"),
                 disable_sudo: lib_core.getBooleanInput("disable-sudo"),
    +            disable_sudo_and_containers: lib_core.getBooleanInput("disable-sudo-and-containers"),
                 disable_file_monitoring: lib_core.getBooleanInput("disable-file-monitoring"),
                 private: ((_b = (_a = github.context === null || github.context === void 0 ? void 0 : github.context.payload) === null || _a === void 0 ? void 0 : _a.repository) === null || _b === void 0 ? void 0 : _b.private) || false,
                 is_github_hosted: isGithubHosted(),
    @@ -88164,6 +88168,9 @@ var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _ar
             external_fs_.appendFileSync(process.env.GITHUB_STATE, `disableSudo=${confg.disable_sudo}${external_os_.EOL}`, {
                 encoding: "utf8",
             });
    +        external_fs_.appendFileSync(process.env.GITHUB_STATE, `disableSudoAndContainers=${confg.disable_sudo_and_containers}${external_os_.EOL}`, {
    +            encoding: "utf8",
    +        });
             lib_core.info(`[!] Current Configuration: \n${JSON.stringify(confg)}\n`);
             if (confg.egress_policy !== "audit" && confg.egress_policy !== "block") {
                 lib_core.setFailed("egress-policy must be either audit or block");
    
  • dist/pre/index.js.map+1 1 modified
  • README.md+4 2 modified
    @@ -66,7 +66,8 @@ To integrate Harden-Runner, follow these steps:
     - Add the following code as the first step in each job:
        ```yaml
        steps:
    -     - uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
    +     - name: Harden Runner
    +       uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
            with:
              egress-policy: audit
     
    @@ -134,7 +135,7 @@ Explore the full feature set in the [Features Documentation](https://docs.stepse
     
     ## Trusted By and Case Studies
     
    -Harden-Runner is trusted by over 5000 leading open-source projects and enterprises, including Microsoft, Google, Kubernetes, and more.
    +Harden-Runner is trusted by over 6000 leading open-source projects and enterprises, including Microsoft, Google, Kubernetes, and more.
     
     ### Trusted by
     
    @@ -147,6 +148,7 @@ Harden-Runner is trusted by over 5000 leading open-source projects and enterpris
     
     - [How Coveo Strengthened GitHub Actions Security with StepSecurity](https://www.stepsecurity.io/case-studies/coveo)
     - [Hashgraph Achieves Comprehensive CI/CD Security Without Compromising Development Speed](https://www.stepsecurity.io/case-studies/hashgraph)
    +- [Chainguard Secures GitHub Actions with StepSecurity](https://www.stepsecurity.io/case-studies/chainguard)
     - [Kapiche secures their GitHub Actions software supply chain with Harden-Runner](https://www.stepsecurity.io/case-studies/kapiche)
     - [Arcjet Enhances CI/CD Security with Harden-Runner](https://www.stepsecurity.io/case-studies/arcjet)
     
    
  • src/checksum.ts+3 3 modified
    @@ -4,11 +4,11 @@ import * as fs from "fs";
     
     const CHECKSUMS = {
       tls: {
    -    amd64: "38e7ed97ced6fe0c1cf0fb5ee3b3d521dfe28d5ddf1cdca72d130c8d1b4a314e", // v1.4.2
    -    arm64: "f67c80cc578c996d4f882c14fcdb63df57927d907cd22f1ec65f9fa940c08cf3",
    +    amd64: "e7c0c5f96efbf96806d27dcbf65f71f72ecd34cdd596c556bb2ded0f2037c260", // v1.6.3
    +    arm64: "813a4cd40f6740bd9623a40884a78f14960c6bd3794391693a165f2ca71c90e3",
       },
       non_tls: {
    -    amd64: "a9f1842e3d7f3d38c143dbe8ffe1948e6c8173cd04da072d9f9d128bb400844a", // v0.13.7
    +    amd64: "f0a8bb49ce5480744f8c836af2abd5f311e918efef5b36b4cce7521d7b9dffe6", // v0.14.0
       },
     };
     
    
  • src/cleanup.ts+3 1 modified
    @@ -81,7 +81,9 @@ import { isGithubHosted } from "./tls-inspect";
       }
     
       var disable_sudo = process.env.STATE_disableSudo;
    -  if (disable_sudo !== "true") {
    +  var disable_sudo_and_containers = process.env.STATE_disableSudoAndContainers;
    +  
    +  if (disable_sudo !== "true" && disable_sudo_and_containers !== "true") {
         try {
           var journalLog = cp.execSync("sudo journalctl -u agent.service --lines=1000", {
             encoding: "utf8",
    
  • src/install-agent.ts+2 2 modified
    @@ -25,15 +25,15 @@ export async function installAgent(
     
       if (isTLS) {
         downloadPath = await tc.downloadTool(
    -      `https://packages.stepsecurity.io/github-hosted/harden-runner_1.4.2_linux_${variant}.tar.gz`
    +      `https://packages.stepsecurity.io/github-hosted/harden-runner_1.6.3_linux_${variant}.tar.gz`
         );
       } else {
         if (variant === "arm64") {
           console.log(ARM64_RUNNER_MESSAGE);
           return false;
         }
         downloadPath = await tc.downloadTool(
    -      "https://github.com/step-security/agent/releases/download/v0.13.7/agent_0.13.7_linux_amd64.tar.gz",
    +      "https://github.com/step-security/agent/releases/download/v0.14.0/agent_0.14.0_linux_amd64.tar.gz",
           undefined,
           auth
         );
    
  • src/interfaces.ts+2 0 modified
    @@ -8,6 +8,7 @@ export interface Configuration {
       egress_policy: string;
       disable_telemetry: boolean;
       disable_sudo: boolean;
    +  disable_sudo_and_containers: boolean;
       disable_file_monitoring: boolean;
       is_github_hosted: boolean;
       private: string;
    @@ -20,6 +21,7 @@ export interface PolicyResponse {
       policyName?: string;
       allowed_endpoints?: string[];
       disable_sudo?: boolean;
    +  disable_sudo_and_containers?: boolean;
       disable_file_monitoring?: boolean;
       disable_telemetry?: boolean;
       egress_policy?: string;
    
  • src/policy-utils.test.ts+2 0 modified
    @@ -36,6 +36,7 @@ test("merge configs", async () => {
         egress_policy: "audit",
         disable_telemetry: false,
         disable_sudo: false,
    +    disable_sudo_and_containers: false,
         disable_file_monitoring: false,
         private: "true",
         is_github_hosted: true,
    @@ -62,6 +63,7 @@ test("merge configs", async () => {
         egress_policy: "audit",
         disable_telemetry: false,
         disable_sudo: false,
    +    disable_sudo_and_containers: false,
         disable_file_monitoring: false,
         private: "true",
         is_github_hosted: true,
    
  • src/policy-utils.ts+4 0 modified
    @@ -56,6 +56,10 @@ export function mergeConfigs(
         localConfig.disable_sudo = remoteConfig.disable_sudo;
       }
     
    +  if (remoteConfig.disable_sudo_and_containers !== undefined) {
    +    localConfig.disable_sudo_and_containers = remoteConfig.disable_sudo_and_containers;
    +  }
    +
       if (remoteConfig.disable_file_monitoring !== undefined) {
         localConfig.disable_file_monitoring = remoteConfig.disable_file_monitoring;
       }
    
  • src/setup.ts+8 0 modified
    @@ -62,6 +62,7 @@ interface MonitorResponse {
           egress_policy: core.getInput("egress-policy"),
           disable_telemetry: core.getBooleanInput("disable-telemetry"),
           disable_sudo: core.getBooleanInput("disable-sudo"),
    +      disable_sudo_and_containers: core.getBooleanInput("disable-sudo-and-containers"),
           disable_file_monitoring: core.getBooleanInput("disable-file-monitoring"),
           private: context?.payload?.repository?.private || false,
           is_github_hosted: isGithubHosted(),
    @@ -92,6 +93,13 @@ interface MonitorResponse {
             encoding: "utf8",
           }
         );
    +    fs.appendFileSync(
    +      process.env.GITHUB_STATE,
    +      `disableSudoAndContainers=${confg.disable_sudo_and_containers}${EOL}`,
    +      {
    +        encoding: "utf8",
    +      }
    +    );
         core.info(`[!] Current Configuration: \n${JSON.stringify(confg)}\n`);
     
         if (confg.egress_policy !== "audit" && confg.egress_policy !== "block") {
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.