Repository navigation
[setup-security] Environment Variable Injection via OTLP Token in GitHub Actions Step #70120
Description
Summary
A critical environment variable injection vulnerability exists in actions/setup/js/action_setup_otlp.cjs. The mergeAuthorizationHeader() and mergeAuthorizationIntoOTLPEndpoints() functions directly interpolate the INPUT_OTLP_OIDC_TOKEN action input into header and endpoint strings without sanitizing newline characters. These unsanitized strings are then written to GITHUB_ENV via writeEnvLine(), enabling an attacker to inject arbitrary environment variables into the workflow step. This violates the GitHub Actions output safety contract where GITHUB_ENV values must not contain unescaped newlines.
Affected Files
| File | Lines | Pattern |
|---|---|---|
actions/setup/js/action_setup_otlp.cjs |
68-71 | mergeAuthorizationHeader() directly interpolates token into header string |
actions/setup/js/action_setup_otlp.cjs |
162-165 | writeEnvLine() writes unsanitized mergedHeaders to GITHUB_ENV |
actions/setup/js/action_setup_otlp.cjs |
168-171 | writeEnvLine() writes unsanitized mergedEndpoints to GITHUB_ENV |
Risk
Severity: 🔴 CRITICAL
Attack vector: An attacker who can control the INPUT_OTLP_OIDC_TOKEN action input (e.g., via workflow dispatch parameter, malicious PR, or compromised upstream action) can inject newline characters to escape the environment variable format and inject arbitrary environment variables into the step's environment.
Impact:
- Arbitrary environment variable injection for all subsequent steps in the job
- Potential token/credential theft by injecting
PATHmanipulation, credential disclosure via injected variables, or other side-channel attacks - Compromises the integrity of the CI/CD pipeline for that job
Proof of concept:
INPUT_OTLP_OIDC_TOKEN=legitimate-token%0nINJECTED_VAR=malicious-value
Would result in GITHUB_ENV containing:
OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer legitimate-token
INJECTED_VAR=malicious-value
Recommendation
-
Sanitize the
inputOTLPOIDCTokenbefore using it inmergeAuthorizationHeader(): strip or reject any newline characters (\r,\n).function sanitizeTokenForHeaders(token) { return (token || "").replace(/[\r\n]/g, ""); }
-
Apply sanitization in
mergeAuthorizationHeader():function mergeAuthorizationHeader(headers, token) { if (hasAuthorizationHeader(headers)) return headers; const cleanToken = sanitizeTokenForHeaders(token); return (headers ? `${headers},` : "") + "Authorization=Bearer " + cleanToken; }
-
Verify and test that newline-containing tokens are properly rejected or sanitized before reaching any
writeEnvLine()call. -
Consider using a structured encoding (e.g., base64 or URL encoding) for the entire Authorization header value if tokens may legitimately contain special characters.
Evidence
Vulnerable code snippet: mergeAuthorizationHeader (lines 68–71)
function mergeAuthorizationHeader(headers, token) {
if (hasAuthorizationHeader(headers)) return headers;
return (headers ? `${headers},` : "") + "Authorization=Bearer " + token;
}The token parameter is the raw inputOTLPOIDCToken which is not validated or sanitized.
Vulnerable code snippet: GITHUB_ENV write (lines 162–165)
const mergedHeaders = mergeAuthorizationHeader(existingHeaders, inputOTLPOIDCToken);
process.env.OTEL_EXPORTER_OTLP_HEADERS = mergedHeaders;
writeEnvLine(process.env.GITHUB_ENV, "OTEL_EXPORTER_OTLP_HEADERS", mergedHeaders, "OTEL_EXPORTER_OTLP_HEADERS", "GITHUB_ENV");The mergedHeaders variable contains unsanitized token data and is written directly to GITHUB_ENV without newline escaping.
Vulnerable code snippet: writeEnvLine (lines 37–49)
function writeEnvLine(filePath, key, value, logLabel, fileLabel) {
if (!filePath) return;
try {
appendFileSync(filePath, `${key}=${value}\n`);
core.info(`[otlp] ${logLabel} written to ${fileLabel}`);
} catch {
/* ignore */
}
}The value parameter is directly concatenated into the output line without any newline escaping or validation.
Generated by 🛡️ Daily action/setup/* Security Audit · copilot · opus48 · 24.3 AIC · ⊞ 7.6K · ◷
Activity
github-actions commentedon Oct 19, 2026
🍪 Issue Monster selected this for Copilot
I've identified this issue as a good candidate for automated resolution and requested assignment to the Copilot coding agent.
If assignment succeeds, the Copilot coding agent will analyze the issue and create a pull request with the fix.
Om nom nom! 🍪
github-actions commentedon Oct 19, 2026
🍪 Issue Monster selected this for Copilot
I've identified this issue as a good candidate for automated resolution and requested assignment to the Copilot coding agent.
If assignment succeeds, the Copilot coding agent will analyze the issue and create a pull request with the fix.
Om nom nom! 🍪
github-actions commentedon Oct 19, 2026
🍪 Issue Monster selected this for Copilot
I identified this issue as a good candidate for automated resolution and requested assignment to the Copilot coding agent.
If assignment succeeds, the Copilot coding agent will analyze the issue and create a pull request with the fix.
Om nom nom! 🍪
github-actions commentedon Oct 19, 2026
🍪 Issue Monster selected this for Copilot
I've identified this issue as a good candidate for automated resolution and requested assignment to the Copilot coding agent.
If assignment succeeds, the Copilot coding agent will analyze the issue and create a pull request with the fix.
Om nom nom! 🍪
github-actions commentedon Oct 19, 2026
🍪 Issue Monster selected this for Copilot
I've identified this issue as a good candidate for automated resolution and requested assignment to the Copilot coding agent.
If assignment succeeds, the Copilot coding agent will analyze the issue and create a pull request with the fix.
Om nom nom! 🍪