Skip to content

[static-analysis] RGS-016: Unicode Steganography in Workflow File in agentic_commands.ymlΒ #53587

Description

@github-actions

🚨 Runner-Guard Security Finding

Rule: RGS-016 β€” Unicode Steganography in Workflow File
Severity: Critical
File: .github/workflows/agentic_commands.yml
Line: 143

Description

The workflow file contains invisible Unicode characters in ranges commonly used for steganographic payloads. These characters render as zero-width whitespace in code editors, terminals, and GitHub's diff viewer, making them invisible to human code review. Attackers embed hidden payloads using variation selectors (U+FE00-FE0F), supplementary variation selectors (U+E0100-E01EF), tag characters (U+E0001-E007F), and zero-width formatting characters (U+200B-200F). This technique was prominently used by the GlassWorm supply chain attack campaign (active since October 2025) to compromise 433+ components across GitHub, npm, and VS Code/OpenVSX registries.

Investigation / Likely False Positive

Decoding line 143 (the GH_AW_SLASH_ROUTING / GH_AW_LABEL_ROUTING / GH_AW_HELP_COMMANDS env values) character-by-character shows the flagged codepoints are all:

  • U+FE0F VARIATION SELECTOR-16 (7 occurrences) β€” the standard modifier that renders a preceding codepoint as a colorful emoji, e.g. ✏️ (U+270F U+FE0F) and βœ… (U+2705 U+FE0F) used as the emoji field values in the slash-command routing table.
  • U+200D ZERO WIDTH JOINER (4 occurrences) β€” used to compose multi-part emoji sequences (e.g. a person + role emoji), also present in the same JSON routing strings.

Both codepoints fall inside RGS-016's flagged ranges (VS16 is literally U+FE0F, inside U+FE00-FE0F; ZWJ is U+200D, inside U+200B-200F) purely because ordinary emoji rendering conventions overlap with the steganography-detection ranges. There is no hidden/invisible-only run of characters here β€” every flagged codepoint is immediately adjacent to a visible emoji base character and serves a normal rendering purpose. This looks like a scanner false positive rather than a real payload.

Impact

If unaddressed as a detection-rule gap, RGS-016 will fire on any gh-aw workflow that uses emoji with variation selectors or ZWJ sequences in its slash-command/label routing tables (a common and growing pattern in this repo β€” reaction emojis are used throughout agentic_commands.yml), producing recurring critical-severity noise that risks alert fatigue and could mask genuine steganographic payloads in the future.

Remediation

Two independent, non-exclusive fixes:

  1. In this repo: if the false-positive read above is confirmed, add a # runner-guard:ignore RGS-016 (or equivalent suppression the tool supports) near line 143 with a comment noting the finding is emoji VS16/ZWJ sequences, not steganography.
  2. In runner-guard upstream: refine the RGS-016 detector so it doesn't flag VS16/ZWJ codepoints when they immediately follow a valid emoji base codepoint (i.e., part of a well-formed grapheme cluster), and/or requires a minimum run of isolated invisible characters (not attached to a visible base) before flagging β€” this would eliminate the false-positive class while still catching genuinely hidden/invisible-only payloads.

Detected by runner-guard v2.6.0 β€” CI/CD source-to-sink vulnerability scanner
Workflow run: https://github.com/github/gh-aw/actions/runs/32100578123

Generated by πŸ“Š Static Analysis Report Β· agent Β· 192.6 AIC Β· βŒ– 14.6 AIC Β· ⊞ 11.5K Β· β—·

  • expires on Aug 24, 2026, 9:16 PM UTC-08:00

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions