Conversation
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>
There was a problem hiding this comment.
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_HEADERSand 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
| 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() |
There was a problem hiding this comment.
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.
| // 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()) | ||
| } |
There was a problem hiding this comment.
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.
| // 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()) | ||
| } |
There was a problem hiding this comment.
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.
Static OTLP header values (e.g.
Authorization=****** set via theobservability.otlp.headersfrontmatter 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 whetherOTEL_EXPORTER_OTLP_HEADERSis in the workflow env blockgenerateOTLPHeadersMaskStep()— returns a YAML step that emits the::add-mask::command using mixed shell quoting to avoid injection in the prefixJob 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 actioncompiler_safe_outputs_job.go— immediately after the setup actionThe generated step looks like:
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.