fix: use command tr so a user alias cannot hijack shipped pipelines - #509
Merged
Conversation
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
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>
This was referenced Aug 24, 2026
Merged
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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:
so every
... | tr -d ' 'inlib/rantrack-activity report -d ' ', and its output landed inthe variable instead of the count. Visible in
teach deploy --dry-runagainst a real course repo:— where
675belonged.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_countline had the identical bug. One root cause, twosymptoms — the new one just made it visible.
The change
101 pipeline sites across 34 files,
| tr→| command tr.commandbypasses aliases andfunctions and is identical when no alias exists.
Verified in the affected repo:
Guard
tests/test-alias-shadowing.zsh, three assertions:| trremains inlib/*.zshcommand trsurvives a planted hostile aliasreproducing it the test says so rather than passing vacuously
Not changed
grepis also aliased here, but togrep --color=auto --exclude-dir={...}— behaviourallycompatible. Only
trwas destructive. 113greppipeline sites left alone deliberately.Tests
Full suite 83 passed / 2 failed. Both failures (
e2e-em-dispatcher,test-atlas-contract)reproduce on unmodified
devand are green in CI.