Skip to main content

Free 30-min security demo  — We'll scan your real code and show live findings, no commitment Book Now

Offensive360
ZeroDays CVE-2024-21623
Critical CVE-2024-21623 CVSS 9.8 OTClient YAML

GitHub Actions Expression Injection in OTClient CI/CD Pipeline

CVE-2024-21623 exposes critical expression injection vulnerability in OTClient's SonarCloud workflow, enabling remote command execution and secret exfiltration.

Offensive360 Research Team
Affects: Prior to commit db560de0b56476c87a2f967466407939196dd254
Source Code

Overview

CVE-2024-21623 represents a critical vulnerability in the OTClient project’s GitHub Actions CI/CD pipeline, specifically within the SonarCloud analysis workflow. The vulnerability stems from unsafe use of untrusted input within GitHub Actions expressions, a common but often overlooked attack surface in modern software development pipelines. This flaw allows attackers to inject arbitrary code that executes with the privileges of the GitHub Actions runner, potentially compromising the entire repository, exfiltrating secrets, and modifying source code.

The affected workflow processes data from pull requests without proper sanitization before passing it to expression evaluators. GitHub Actions expressions have access to the runner environment, secrets, and repository context, making expression injection functionally equivalent to arbitrary code execution. The vulnerability affects all versions of OTClient prior to the security patch, with a CVSS score of 9.8 reflecting its severity and exploitability.

Technical Analysis

The vulnerability exists in the analysis-sonarcloud.yml workflow file, specifically in lines 91-104 where pull request event data is used directly within conditional expressions or step outputs without escaping. GitHub Actions workflows use double-curly-brace syntax (${{ }}) to evaluate expressions, and when untrusted input from pull requests is concatenated into these expressions, attackers can break out of intended string contexts and execute arbitrary code.

Vulnerable Code Pattern:

name: Analysis - SonarCloud
on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  sonarcloud:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Vulnerable Step
        run: |
          echo "PR Title: ${{ github.event.pull_request.title }}"
          # OR in a conditional
      
      - name: Build and Analyze
        if: ${{ contains(github.event.pull_request.title, 'SECURITY') }}
        run: |
          # This step's execution depends on untrusted PR title
          sonar-scanner \
            -Dsonar.projectKey=${{ github.event.pull_request.head.repo.name }} \
            -Dsonar.sources=.

When an attacker opens a pull request with a title like ' && echo ${{ secrets.SONAR_TOKEN }} && ', the expression evaluator interprets this as legitimate code, bypassing the intended string context. The runner then executes arbitrary commands with full access to:

  • All repository secrets (SONAR_TOKEN, API keys, credentials)
  • The GitHub token with repository write permissions
  • Environment variables and runner configuration
  • Source code and build artifacts

Root Cause:

The root cause is the fundamental misunderstanding that GitHub Actions expressions are not simple string interpolation but rather a full expression language capable of executing logic. Untrusted data from webhook events (pull request titles, descriptions, commit messages, branch names) must never be directly embedded into ${{ }} blocks without explicit escaping or type-safe operations.

Impact

The practical impact of this vulnerability extends beyond theoretical remote code execution:

  1. Secret Exfiltration: Attackers can access and leak SONAR_TOKEN, deployment keys, API credentials, and any secrets configured in repository settings. These credentials often have elevated permissions across the organization’s infrastructure.

  2. Repository Poisoning: With the GitHub token’s write permissions, attackers can modify source code, alter build artifacts, commit malicious changes, and modify workflow files themselves to persist access.

  3. Supply Chain Compromise: For a project like OTClient that distributes compiled binaries or packages, attackers could inject malicious code into releases, affecting all downstream users and dependencies.

  4. Lateral Movement: Compromised secrets grant access to integrated services (SonarCloud, deployment platforms, cloud infrastructure) enabling further organizational compromise.

  5. Denial of Service: Attackers can consume GitHub Actions minutes, exhaust runner resources, or corrupt the repository to disrupt development workflows.

The attack requires only the ability to create a pull request, a capability available to external contributors in open-source projects, making this vulnerability trivially exploitable.

How to Fix It

The remediation strategy involves two complementary approaches:

Option 1: Use Workflow Inputs (Recommended)

name: Analysis - SonarCloud
on:
  pull_request_target:
    types: [opened, synchronize, reopened]

jobs:
  sonarcloud:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          ref: ${{ github.event.pull_request.head.sha }}
      
      - name: Run SonarCloud Analysis
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
          PR_KEY: ${{ github.event.pull_request.number }}
        run: |
          sonar-scanner \
            -Dsonar.projectKey=otclient \
            -Dsonar.pullRequest.key="${PR_KEY}" \
            -Dsonar.pullRequest.branch="${{ github.event.pull_request.head.ref }}"

Option 2: Explicit Expression Escaping

- name: Safe Title Check
  run: |
    TITLE="${{ github.event.pull_request.title }}"
    # Move untrusted data outside expressions
    if [[ "$TITLE" == *"SECURITY"* ]]; then
      echo "Security PR detected"
    fi

Option 3: Use Action Inputs Instead of Direct Variables

- name: Secure Analysis
  uses: SonarSource/[email protected]
  with:
    args: >
      -Dsonar.projectKey=otclient
      -Dsonar.sources=src
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

Key Principles:

  • Never embed github.event.* fields directly into ${{ }} expressions
  • Use pull_request_target trigger with explicit checkout of PR head for external contributions
  • Pass untrusted data through environment variables instead of expressions
  • Implement input validation before any expression evaluation

Apply commit db560de0b56476c87a2f967466407939196dd254 or equivalent remediation immediately.

Our Take

This vulnerability exemplifies a critical blind spot in modern CI/CD security. As organizations increasingly rely on GitHub Actions and similar automation platforms, the attack surface of workflow files rivals that of application code itself. Yet workflow security receives a fraction of the scrutiny.

The ease of exploitation—requiring only a pull request from an external contributor—makes this vulnerability class particularly dangerous for open-source projects. Security teams must recognize that CI/CD pipelines are infrastructure code deserving the same rigorous security analysis as production applications.

Organizations should:

  1. Audit all GitHub Actions workflows for expression injection vulnerabilities
  2. Establish a policy that untrusted webhook data never enters expression contexts
  3. Use dedicated security scanning for workflow files as part of their SAST program
  4. Implement least-privilege secrets management with short-lived credentials
  5. Require code review for all workflow modifications

Detection with SAST

Static analysis tools should flag expression injection vulnerabilities by detecting:

  • CWE-94: Improper Control of Generation of Code (‘Code Injection’) - github.event context variables used in expressions
  • CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code - untrusted input in ${{ }} blocks
  • CWE-643: Improper Neutralization of Data within XPath Expressions - application of injection principles to GitHub’s expression language

SAST Detection Patterns:

  • ${{ github.event.pull_request.* }} used directly in conditionals
  • ${{ github.event.*.*.body }} or similar fields without escaping
  • Variables sourced from webhook payloads within expression contexts
  • String concatenation of untrusted data into expression blocks

Offensive360’s SAST capabilities identify these patterns across YAML workflow files, flagging high-risk patterns and recommending safe alternatives using environment variables and explicit input validation.

References

#expression-injection #github-actions #ci-cd #remote-code-execution #secrets-exposure

Detect this vulnerability class in your codebase

Offensive360 SAST scans your source code for CVE-2024-21623-class vulnerabilities and thousands of other patterns — across 60+ languages.