From 9f46adcdfa8c8efd321bd6ba9236a895dfb18847 Mon Sep 17 00:00:00 2001 From: Oliver Kieselbach Date: Sun, 4 Oct 2026 12:52:01 +0200 Subject: [PATCH] ci: the storage auth helper masks its token in the run log, like the Key Vault token GitHub masks only secrets.* by itself. The bearer token Get-StorageAuthHeaders.ps1 mints at run time was never registered as a mask, unlike the Key Vault signing token, which build-agent, build-msi and publish-scripts mask before exporting it. No caller prints it today -- every call site captures the hashtable and passes it only as -Headers -- but this repository's run logs are public, and a single debugging line would have published it: an uncaptured call of the helper, or Get-Error / Format-List on a failed request, whose TargetObject is the HttpRequestMessage including the Authorization header (reproduced locally with a dummy token). The helper now emits ::add-mask:: for every token it hands out, which covers all six workflows in one place. Write-Host, never Write-Output: the output stream is the script's return value. Verified with a mocked az that the result stays one hashtable and that a nested caller in the Request-BuildNumber.ps1 pattern still returns only its build number. Only under GITHUB_ACTIONS -- locally the line would print the token instead of hiding it. Prompted by an external AI review of the public scripts. Co-Authored-By: Claude Opus 5.5 (1M context) --- .github/scripts/Get-StorageAuthHeaders.ps1 | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/scripts/Get-StorageAuthHeaders.ps1 b/.github/scripts/Get-StorageAuthHeaders.ps1 index ca42620a..44100324 100644 --- a/.github/scripts/Get-StorageAuthHeaders.ps1 +++ b/.github/scripts/Get-StorageAuthHeaders.ps1 @@ -11,6 +11,7 @@ Identity comes from whatever `az login` established: the federated GitHub OIDC principal in CI (azure/login, subject repo:okieselbach/AutopilotMonitor:ref:refs/heads/main), the operator's own account for the local build. No secret is read, stored or passed around. + Under GitHub Actions the token is masked in the run log before it is returned. x-ms-version is MANDATORY here, not decoration: Entra-authorized requests are rejected below 2017-11-09, and Table requests without a SAS must carry the header at all. 2021-08-06 @@ -45,6 +46,15 @@ if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($token)) { 'on the table -- a missing role shows up later as HTTP 403 AuthorizationPermissionMismatch.') } +# GitHub masks only secrets.* on its own; a token minted at run time is clear text in the +# (public) run log the moment anything prints it -- an uncaptured call of this script, or +# Get-Error / Format-List on a failed request, whose TargetObject carries this header. +# Write-Host, never Write-Output: the output stream is this script's return value. Only +# under Actions -- anywhere else the line would print the token instead of hiding it. +if ($env:GITHUB_ACTIONS -eq 'true') { + Write-Host "::add-mask::$token" +} + return @{ 'Authorization' = "Bearer $token" 'x-ms-version' = '2021-08-06'