Skip to content

Add ::add-mask:: for OTEL_EXPORTER_OTLP_HEADERS to prevent telemetry auth token leakage#24805

Merged
pelikhan merged 1 commit intomainfrom
copilot/update-compiler-add-mask-otel-header
Apr 6, 2026
Merged

Add ::add-mask:: for OTEL_EXPORTER_OTLP_HEADERS to prevent telemetry auth token leakage#24805
pelikhan merged 1 commit intomainfrom
copilot/update-compiler-add-mask-otel-header

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 6, 2026

Static OTLP header values (e.g. Authorization=****** set via the observability.otlp.headers frontmatter field are injected as a workflow-level env var and can appear in plaintext in GitHub Actions runner debug logs (ACTIONS_RUNNER_DEBUG=true`).

Changes

  • observability_otlp.go — adds two helpers:

    • isOTLPHeadersPresent(data) — detects whether OTEL_EXPORTER_OTLP_HEADERS is in the workflow env block
    • generateOTLPHeadersMaskStep() — returns a YAML step that emits the ::add-mask:: command using mixed shell quoting to avoid injection in the prefix
  • Job generators — emit the masking step at the earliest possible point in each job that inherits the workflow env:

    • compiler_yaml_main_job.go — before checkout (first step in the agent job)
    • compiler_activation_job.go — immediately after the setup action
    • compiler_safe_outputs_job.go — immediately after the setup action

The generated step looks like:

- name: Mask OTLP telemetry headers
  run: echo '::add-mask::'$OTEL_EXPORTER_OTLP_HEADERS

Mixed quoting ('::add-mask::' single-quoted, variable double-quoted) keeps the prefix literal while still expanding the env var at runtime.

Masking applies to both static header values and secrets-expression headers (${{ secrets.OTLP_HEADERS }}), providing defence-in-depth for the latter.

Add GitHub Actions ::add-mask:: workflow command for OTEL_EXPORTER_OTLP_HEADERS
in activation job, main job, and safe outputs job to prevent authentication
tokens in the header value from leaking in runner logs (including debug logs).

- observability_otlp.go: add isOTLPHeadersPresent() and generateOTLPHeadersMaskStep()
- compiler_yaml_main_job.go: emit mask step at start of main job steps
- compiler_activation_job.go: emit mask step after setup in activation job
- compiler_safe_outputs_job.go: emit mask step after setup in safe outputs job
- Tests: unit tests for new helpers + integration tests for masking behavior

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/427e35d3-9c31-45eb-a1ed-5b54a5ff9f41

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
@pelikhan pelikhan marked this pull request as ready for review April 6, 2026 01:41
Copilot AI review requested due to automatic review settings April 6, 2026 01:41
@pelikhan pelikhan merged commit 1de4eba into main Apr 6, 2026
66 of 67 checks passed
@pelikhan pelikhan deleted the copilot/update-compiler-add-mask-otel-header branch April 6, 2026 01:45
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds GitHub Actions ::add-mask:: emission for OTEL_EXPORTER_OTLP_HEADERS to prevent OTLP auth headers from appearing in runner debug logs when headers are injected at workflow scope.

Changes:

  • Add helpers to detect injected OTEL_EXPORTER_OTLP_HEADERS and generate a masking step.
  • Insert the masking step into generated jobs (agent/main, activation, safe-outputs) when headers are present.
  • Update existing locked workflows to include the new masking step.
Show a summary per file
File Description
pkg/workflow/observability_otlp.go Adds detection + YAML step generation for masking OTEL_EXPORTER_OTLP_HEADERS.
pkg/workflow/observability_otlp_test.go Adds unit tests for header detection and mask step generation.
pkg/workflow/observability_job_summary_test.go Adds compilation-level tests asserting mask-step presence/absence and relative ordering in the agent job.
pkg/workflow/compiler_yaml_main_job.go Emits mask step early in the agent/main job when headers are present.
pkg/workflow/compiler_activation_job.go Emits mask step in activation job when headers are present.
pkg/workflow/compiler_safe_outputs_job.go Emits mask step in safe-outputs job when headers are present.
.github/workflows/smoke-update-cross-repo-pr.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/smoke-test-tools.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/smoke-temporary-id.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/smoke-service-ports.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/smoke-project.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/smoke-multi-pr.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/smoke-gemini.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/smoke-create-cross-repo-pr.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/smoke-copilot.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/smoke-copilot-arm.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/smoke-codex.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/smoke-claude.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/smoke-call-workflow.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/smoke-agent-scoped-approved.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/smoke-agent-public-none.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/smoke-agent-public-approved.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/smoke-agent-all-none.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/smoke-agent-all-merged.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-workflow-updater.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-testify-uber-super-expert.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-team-status.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-team-evolution-insights.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-syntax-error-quality.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-semgrep-scan.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-security-red-team.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-secrets-analysis.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-safe-outputs-conformance.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-safe-output-optimizer.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-safe-output-integrator.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-repo-chronicle.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-rendering-scripts-verifier.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-regulatory.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-performance-summary.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-otel-instrumentation-advisor.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-observability-report.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-news.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-multi-device-docs-tester.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-mcp-concurrency-analysis.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-malicious-code-scan.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-issues-report.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-integrity-analysis.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-function-namer.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-firewall-report.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-file-diet.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-fact.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-doc-updater.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-doc-healer.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-compiler-quality.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-community-attribution.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-code-metrics.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-cli-tools-tester.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-cli-performance.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-choice-test.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-assign-issue-to-user.lock.yml Regenerated lock workflow including OTLP headers masking step.
.github/workflows/daily-architecture-diagram.lock.yml Regenerated lock workflow including OTLP headers masking step.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 61/61 changed files
  • Comments generated: 3

Comment on lines +71 to +78
func generateOTLPHeadersMaskStep() string {
var sb strings.Builder
sb.WriteString(" - name: Mask OTLP telemetry headers\n")
// Use mixed quoting: single-quoted prefix concatenated with double-quoted variable
// so the ::add-mask:: prefix is never subject to shell word-splitting or glob expansion,
// and the variable value is expanded but not further interpreted.
sb.WriteString(" run: echo '::add-mask::'\"$OTEL_EXPORTER_OTLP_HEADERS\"\n")
return sb.String()
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

generateOTLPHeadersMaskStep emits run: echo '::add-mask::'"$OTEL_EXPORTER_OTLP_HEADERS" without specifying a shell. On runs-on: windows-latest, the default shell is PowerShell, where $OTEL_EXPORTER_OTLP_HEADERS is not an environment variable reference, so the mask command will not include the header value (and masking will be ineffective). Consider explicitly setting shell: bash (or using a shell-agnostic approach) for this step so it works across runner OSes supported by the compiler.

Copilot uses AI. Check for mistakes.
Comment on lines +48 to +52
// Mask OTLP telemetry headers immediately after setup so authentication tokens cannot
// leak into runner debug logs for any subsequent step in the activation job.
if isOTLPHeadersPresent(data) {
steps = append(steps, generateOTLPHeadersMaskStep())
}
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The OTLP header masking step is appended after the checkout/setup steps in the activation job. With ACTIONS_RUNNER_DEBUG=true, GitHub Actions can log step environment details when starting each step; if so, OTEL_EXPORTER_OTLP_HEADERS could still appear in plaintext for the earlier checkout/setup steps (before the mask step runs). To fully prevent leakage, emit the mask step as the very first step in the job whenever workflow-level headers are present.

Copilot uses AI. Check for mistakes.
Comment on lines +59 to +63
// Mask OTLP telemetry headers immediately after setup so authentication tokens cannot
// leak into runner debug logs for any subsequent step in the safe outputs job.
if isOTLPHeadersPresent(data) {
steps = append(steps, generateOTLPHeadersMaskStep())
}
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The safe-outputs job adds the OTLP header masking step only after the setup step. If runner debug logging prints environment info for the setup (or earlier) steps, OTEL_EXPORTER_OTLP_HEADERS could leak before the mask is applied. Consider inserting the masking step as the first step in the safe-outputs job when headers are present, so masking is in effect for all subsequent steps.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants