Huny's Dev Blog
huny.dev

GitHub Secret Scanning for Actions Workflow Logs: Separate Print-Time Masking (::add-mask::) from Post-Run Scanning Blind Spots

Understand how GitHub's new secret scanning for Actions workflow logs (public preview) complements print-time ::add-mask:: redaction, and account for its 5 preview limitations including custom-pattern and notification blind spots.

Hun Jang
Hun Jang Nov 11, 2026

A conceptual illustration showing Stage 1 print-time redaction (::add-mask::) alongside Stage 2 post-run workflow log secret scanning for provider patterns and persistent alert storage. This is not an actual console screenshot.

On November 9, 2026, GitHub launched a public preview of secret scanning for GitHub Actions workflow logs, extending secret detection beyond repository code, issues, wikis, discussions, and pull requests into CI/CD console output. Whenever a workflow run completes, GitHub scans the finished logs for supported provider patterns, runs validity checks on matching credentials, and records findings in the repository's secret scanning alert list—preserving the alert even after the workflow logs themselves are deleted. GitHub Changelog Announcement, GitHub Enterprise Cloud Policy Docs

The core operational takeaway: post-run workflow log scanning is a safety net for unmasked provider tokens, not a replacement for print-time masking (::add-mask::), and it carries five critical preview limitations. During the public preview, the scanner (1) ignores generic patterns, custom enterprise regexes, and AI-detected secrets, (2) does not backfill existing workflow logs completed before activation, and (3) does not send email or webhook notifications when a log leak is found. Teams must combine strict print-time masking (“mask first, export second”) with direct polling of their secret scanning alert list.

This guide analyzes the boundary between runtime redaction and post-run log scanning, the five preview blind spots, and safe dynamic-token workflow patterns based on the GitHub Changelog post, the GitHub Enterprise policy documentation, and community security analyses (DEV Community, C# Corner). It does not inject live credentials into production GitHub Enterprise Cloud tenants; the local Python checks below model print-time masking order and post-run scanner coverage.

1. Why Secrets Still Leak Despite GitHub Actions Runtime Redaction (***)

The GitHub Actions runner redacts registered repository, environment, and organization secrets (secrets.*) as well as values passed to ::add-mask:: by replacing exact string matches with *** at print time. Leaks still reach saved workflow logs whenever a secret is dynamically minted or transformed before the runner knows to mask it:

Dimension
Stage 1: Runner Print-Time Redaction (***)
Stage 2: Post-Run Workflow Log Secret Scanning (Public Preview)
Execution Timing
Inline while the step is streaming standard output and standard error
After the workflow run completes, scanning the persisted log output
Matching Mechanism
Exact substring match against pre-registered secrets.* values and strings registered via ::add-mask::
Scans unmasked log text for supported provider patterns and executes partner validity checks
Common Blind Spots
Dynamically minted OAuth/cloud tokens printed before ::add-mask::, sliced/encoded strings, full JSON responses echoed by CLI tools, or commands run under set -x
Generic patterns, custom regex patterns, AI-detected secrets, and historical logs completed prior to enabling the policy (already-masked *** strings are also skipped)
Blast Radius & Log Deletion Behavior
Prevents the secret from ever reaching stored logs or log viewers
Anyone with read access to Actions logs can view the secret until the log is deleted; deleting the log does not close or delete the secret scanning alert

Keeping the alert open after log deletion is intentional: because read access to Actions logs is typically granted to a much broader group than secret administration, a deleted log is not a rotated credential.

2. Enablement Requirements and the Five Public Preview Limitations

Enabling workflow log scanning requires no changes to .github/workflows/*.yml, but enterprise administrators and security teams must account for five operational constraints:

Requirement / Constraint
Supported Scope & Configuration
Operational Impact During Public Preview
1. Plan & Licensing
GitHub Enterprise Cloud (including data residency on GHE.com) with GitHub Secret Protection or GitHub Advanced Security (GHAS)
Disabled by default. Applies only to repositories within the enterprise that already have secret scanning enabled
2. Policy Path
Enterprise Settings → Policies → Advanced Security → Secret scanning for Actions workflow logs → Enabled (under All repositories)
Configured at the enterprise policy level by an enterprise owner rather than per workflow file
3. No Historical Backfill
Scans only workflow runs that complete after the enterprise policy is enabled
Existing workflow logs from earlier runs are never retroactively scanned
4. Provider Patterns Only
Detects identifiable partner/provider token formats (and runs validity checks where supported)
Does not detect generic secrets, custom enterprise/org patterns, or AI-detected secrets in workflow logs
5. Zero Alert Notifications
Findings appear in the repository's Security → Secret scanning alerts list with a deep link to the workflow log
Alerts from workflow logs do not trigger email or webhook notifications during the preview. Teams must inspect the alert list or poll the REST API directly

3. Safe Workflow Patterns: “Mask First, Export Second”

Because custom internal tokens and generic passwords are not covered by the post-run log scanner—and because even provider tokens remain readable to log viewers until rotated—every workflow step that mints a dynamic credential must register ::add-mask:: before any command can print or export it:

To compensate for the lack of automatic notifications during the public preview, schedule a lightweight check using the GitHub CLI (gh api) to surface open secret scanning alerts across your repositories:

4. Modeling Print-Time Masking vs. Post-Run Log Scanning in Python

The dependency-free Python script below models the two-stage pipeline—showing how ordering ::add-mask:: before output prevents alerts entirely, while custom internal tokens and historical runs bypass the post-run workflow log scanner.

Scope Verified Locally

Running this simulation in a local Python environment verified four boundary scenarios:

  1. Provider token printed before ::add-mask::: Leaks into rendered_log[0] and triggers a github_pat alert at the end of the run with notification_sent: False and persists_after_log_deletion: True.
  1. Provider token masked via ::add-mask:: before printing: Redacted to echo 'Token: ***' at print time, producing 0 post-run alerts.
  1. Unmasked custom internal token (INTERNAL_TOKEN_...): Leaves 0 post-run alerts because workflow log scanning excludes custom, generic, and AI-detected patterns.
  1. Historical workflow run (is_historical_run=True): Produces 0 alerts because existing logs are not backfilled when the policy is enabled.

5. Rollout and SecOps Checklist

  • Enable the enterprise policy explicitly: Turn on Secret scanning for Actions workflow logs under Enterprise Settings → Policies → Advanced Security, and verify that target repositories have secret scanning enabled.
  • Poll the secret scanning alerts list or API directly: Because workflow log alerts do not generate notifications during public preview, integrate alert polling into your security triage workflow.
  • Prefer OIDC and pre-output ::add-mask:: for dynamic credentials: Use official OIDC actions (which automatically register masks before exporting tokens) and audit shell steps for printenv, set -x, or unmasked custom tokens that post-run log scanning will not catch.

References

Last verified: November 11, 2026

Korean version: GitHub Actions 워크플로 로그 시크릿 스캐닝 해부: 런타임 마스킹(::add-mask::)과 사후 스캔의 5가지 사각지대 점검하기GitHub Actions 워크플로 로그 시크릿 스캐닝 해부: 런타임 마스킹(::add-mask::)과 사후 스캔의 5가지 사각지대 점검하기

추천 글