Skip to content

fix: scrub access token from logs on failure path - #47

Open
adamrtalbot wants to merge 1 commit into
mainfrom
fix/scrub-token-on-launch-failure
Open

fix: scrub access token from logs on failure path#47
adamrtalbot wants to merge 1 commit into
mainfrom
fix/scrub-token-on-launch-failure

Conversation

@adamrtalbot

@adamrtalbot adamrtalbot commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Problem

tower_action_*.log could contain the Seqera access token in plain text, and CI uploads it as a workflow artifact even when the run fails.

The scrub existed, but it was the second-to-last line of entrypoint.sh:

sed -i "s/$TOWER_ACCESS_TOKEN/xxxxxx/" $LOG_FN

Under set -euo pipefail, a non-zero tw launch kills the script at the launch line, ~35 lines earlier. The log is already written by then, so it ships unscrubbed. .github/workflows/ci.yml uploads it on success() || failure(), and CI deliberately launches a nonexistent pipeline to test the failure path.

::add-mask:: does not cover this: it redacts the live console, not files on disk.

Fix

Run the scrub from an EXIT trap, so it happens whether the script finishes or aborts. Also applied to the .json file. The explicit call before cat stays, because the trap fires after it.

Minor hardening in the same sed: delimiter / to | so a / in a future token format cannot break the expression, the g flag, and a guard for an empty token (where s||xxxxxx|g would insert the replacement between every character).

Only the token is scrubbed. The other masked values are identifiers, and workspaceId is documented content of the .json artifact, so redacting it would break consumers.

Secrets you interpolate into nextflow_config, parameters or pre_run_script are still your problem: the entrypoint never sees those values.

The token scrub ran as the second-to-last statement in the script, so a
non-zero `tw launch` aborted under `set -e` before reaching it. The log
file was already on disk with the raw token, and CI uploads
`tower_action_*.log` with `if: success() || failure()`.

Move the scrub into a function armed as an EXIT trap so it runs on the
abort path too, and cover the json file as well. The explicit call before
`cat` stays because the trap fires after it.

Also switch the sed delimiter from `/` to `|` so a `/` in a future token
format cannot break the expression, and add `g` plus an empty-token guard.

Generated by Claude Code
@github-actions

Copy link
Copy Markdown

🚀 Pipelines launched

Name Info
🔨 AWS Workflow ID 1etKr3x73EaCBv
🏠 AWS Workspace [seqeralabs / scidev-aws]
🗂️ AWS Workspace ID 64430228002560
😎 AWS Workflow URL https://cloud.stage-seqera.io//orgs/seqeralabs/workspaces/scidev-aws/watch/1etKr3x73EaCBv
🔨 Azure Workflow ID 2crJtQNeah4dRl
🏠 Azure Workspace [seqeralabs / scidev-azure]
🗂️ Azure Workspace ID 280116106690509
😎 Azure Workflow URL https://cloud.stage-seqera.io//orgs/seqeralabs/workspaces/scidev-google/watch/402qylMTIeBZJ0
🔨 GCP Workflow ID 402qylMTIeBZJ0
🏠 GCP Workspace [seqeralabs / scidev-google]
🗂️ GCP Workspace ID 124007984423021
😎 GCP Workflow URL https://cloud.stage-seqera.io//orgs/seqeralabs/workspaces/scidev-google/watch/402qylMTIeBZJ0

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.

1 participant