Skip to content

fix: use command tr so a user alias cannot hijack shipped pipelines - #509

Merged
Data-Wise merged 1 commit into
devfrom
feature/alias-proof-tr
Aug 24, 2026
Merged

fix: use command tr so a user alias cannot hijack shipped pipelines#509
Data-Wise merged 1 commit into
devfrom
feature/alias-proof-tr

Conversation

@Data-Wise

Copy link
Copy Markdown
Owner

Dispatchers run in the user's interactive shell, where aliases are live and expand at parse
time. A user alias on a coreutil silently hijacks any pipeline that uses it.

Found live, not hypothetically. This machine has:

tr='track-activity report'

so every ... | tr -d ' ' in lib/ ran track-activity report -d ' ', and its output landed in
the variable instead of the count. Visible in teach deploy --dry-run against a real course repo:

  Would deploy Monthly Terminal Report (2026-08):
================================== files:

— where 675 belonged.

How it surfaced

The uncommitted-file count shipped in v7.17.0 rendered garbled. Tracing it found the alias, and
then that the pre-existing file_count line had the identical bug. One root cause, two
symptoms — the new one just made it visible.

The change

101 pipeline sites across 34 files, | tr| command tr. command bypasses aliases and
functions and is identical when no alias exists.

Verified in the affected repo:

bare tr:     [Monthly Terminal Report (2026-08):
             ==================================]
command tr:  [1]

Note: 1 uncommitted file(s) are NOT included below.
Would deploy 675 files:

Guard

tests/test-alias-shadowing.zsh, three assertions:

  1. no bare | tr remains in lib/*.zsh
  2. command tr survives a planted hostile alias
  3. negative control — the bare form really is hijacked, so if the environment ever stops
    reproducing it the test says so rather than passing vacuously

Not changed

grep is also aliased here, but to grep --color=auto --exclude-dir={...} — behaviourally
compatible. Only tr was destructive. 113 grep pipeline sites left alone deliberately.

Tests

Full suite 83 passed / 2 failed. Both failures (e2e-em-dispatcher, test-atlas-contract)
reproduce on unmodified dev and are green in CI.

Dispatchers run in the user's INTERACTIVE shell, where aliases are live and
expand at parse time. A user alias on a coreutil silently hijacks any
pipeline using it.

Found live, not hypothetically. This machine has:

    tr='track-activity report'

so every `... | tr -d ' '` in lib/ ran `track-activity report -d ' '` and
its output landed in the variable instead of the count. Visible in
`teach deploy --dry-run` against a real course repo:

    Would deploy Monthly Terminal Report (2026-08):
    ================================== files:

where "675" belonged. The same alias also corrupted the uncommitted-file
count added in v7.17.0 - I found it because my own new line was garbled,
then traced it and discovered the pre-existing file_count line had the
identical bug.

101 pipeline sites across 34 files. All now use `command tr`, which
bypasses aliases and functions and is identical when no alias exists.

Verified in the affected repo:

    bare tr:     [Monthly Terminal Report (2026-08):\n===...]
    command tr:  [1]

    Note: 1 uncommitted file(s) are NOT included below.
    Would deploy 675 files:

tests/test-alias-shadowing.zsh guards it three ways: no bare `| tr` remains
in lib/*.zsh, `command tr` survives a planted hostile alias, and a NEGATIVE
control confirms the bare form really is hijacked - so if the environment
ever stops reproducing it, the test says so instead of going vacuously
green.

Not changed: `grep` is also aliased here, but to
`grep --color=auto --exclude-dir={...}`, which is behaviourally compatible.
Only `tr` was destructive.

Full suite 83 passed / 2 failed - both (e2e-em-dispatcher,
test-atlas-contract) reproduce on unmodified dev and are green in CI.
@Data-Wise
Data-Wise merged commit bc2b366 into dev Aug 24, 2026
3 checks passed
@Data-Wise Data-Wise mentioned this pull request Aug 24, 2026
5 tasks
Data-Wise added a commit that referenced this pull request Aug 24, 2026
Patch release for the alias-shadowing fix (#509).

A user alias on a coreutil could hijack shipped pipelines: dispatchers run
in the interactive shell where aliases expand at parse time, so on a machine
with tr='track-activity report' every '| tr -d' in lib/ ran that instead.
teach deploy --dry-run printed 'Would deploy Monthly Terminal Report
(2026-08):' where 'Would deploy 675 files:' belonged. 101 sites now use
'command tr'.

Both changelogs cut [7.17.1] with identical bodies; parity test green.
docs/index.md updated by hand again - release.sh still does not touch it
(both the What's New banner and the footer), which is worth folding into
the script.

Man-page guard 12/12, mkdocs --strict exit 0, no stale 7.17.0 refs outside
changelogs. Full suite 81 passed / 1 failed / 3 timeout - the failure and
timeouts are the known local-only set (e2e-em-dispatcher,
test-atlas-contract and friends), all green in CI.

Co-authored-by: Test User <test@example.com>
Data-Wise added a commit to Data-Wise/homebrew-tap that referenced this pull request Aug 24, 2026
Ships the tr-alias-shadowing fix (Data-Wise/flow-cli#509) to the tap.
Hand-edited: manifest.json marks flow-cli generated:false.
homebrew-release.yml automation remains broken (flow-cli#499).

Co-authored-by: Test User <test@example.com>
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