> If the shell would expand the contents of PS1 when drawing the prompt, a raw ref name must not be included in PS1. This protects the user from arbitrary code execution via specially crafted ref names. For example, a ref named 'refs/heads/$(IFS=_;cmd=sudo_rm_-rf_/;$cmd)' might cause the shell to execute 'sudo rm -rf /' when the prompt is drawn.
Tab autocompletion looks to be affected too, at least on my system. Create a branch called 'complete_$(./foo)'. Then type 'git checkout comp<TAB>'. This gets autocompleted to
git checkout complete_$(./foo)
If you hit Enter at this point without thinking you'll end up running './foo'. It should have expanded instead to something like
It's always cute to find new vectors for command injection. Really anytime you mix data and commands this type of crap is bound to happen (ex: sql injection).
Still not as worrisome to me as the full scripts that get executed by package managers when you install dependencies. Effectively every time you run something like "npm install" you're putting your faith in the entire tree of ancestor dependencies as any of them could have a pwnage script as a post install.
More often than not, building and deploying is secondary for developers to writing the library itself, if that. Build scripts and installation don't get the same treatment and care the library does.
The is one of the primary reasons why I prefer distribution-packaged libraries to pulling a library and its dependencies directly from developers. Staleness is a small price to pay relative to having at least two sets of eyes glance over the source and not execute arbitrary build scripts on my system.
Cute idea. I'm willing to bet that the Bash script I wrote for some of my co-workers is vulnerable. I guess that's something I should find out ... by making their computers do stuff.
Since branch name parsing is done by a lot of scripts, and I can't control the default branch name, I've installed this global post-checkout hook for now until I can stop panicking and think clearly.
#!/bin/sh
prev_head=$1
new_head=$2
changing_branch=$3
REPO_DIR="$(git rev-parse --show-toplevel 2>/dev/null)"
if [ "$changing_branch" = 1 -a "$prev_head" = "0000000000000000000000000000000000000000" ]; then
new_head_name="$(git name-rev --name-only "$new_head"|sed -e 's|`|_|g' -e 's|$(|_|g')"
new_head_name_untaint="$(git name-rev --name-only "$new_head"|sed -e 's|`|x|g' -e 's|$(|x|g')"
if [ "$new_head_name" != "$new_head_name_untaint" ]; then
echo "
DANGER! INSECURE BRANCH NAME.
">&2
git name-rev --name-only "$new_head"
echo "
MOVING $REPO_DIR TO TRASH.
">&2
mkdir -p ~/.Trash
mv "$REPO_DIR" "$HOME/.Trash/${REPO_DIR##*/}.$(date +"%Y%m%d%H%M%S")"
fi
fi
Dang. Unfortunately I am not vulnerable, and I use default ohmyzsh.
This is a neat bug, though. Lots of package managers have similar problems, and I would not be surprised if there's a lot of git/shell/environment problems left to find.
Code quality is pretty much the reason though. The oh-my-zsh maintainer himself even wrote a post once upon a time about how not to run an OSS project.
Prezto forked the project and cleaned up everything quite nicely a long time ago.
Neat. My fancy Git prompt is a program I wrote in C, though. I'm sure it's vulnerable to something, but not to this. Maybe it should escape shell metacharacters in branch names, though.
Nice find. Luckily I am hyper-paranoid about escaping, so even though my custom jankery is probably not as performant as it could be, it's not vulnerable to this or similar exploits.
Forgive me if I'm misunderstanding the vulnerability, but isn't this one of Raymond Chen's "It rather involved being on the other side of this airtight hatchway" exploits? That is, any commands you run has the same permissions as you have.
Now, I understand that you may not intimately understand 100% the code of the commands and shell extensions you use, but is that a "vulnerability"?
The privilege escalation is from "can push code to a repository that you pull from" to "can run code as you". The idea is that you trust the shell extension you're using, but a particular git repo exploits a vulnerability in that shell extension.
git cloning code vs. running code is sometimes a security boundary and sometimes not. For instance, if you go cd into that directory and then run make or ./configure or ./setup.py install or docker run or something, then yeah, you've removed that boundary. But in general, it's reasonable to keep the boundary there. Perhaps you're doing code review of code by an untrusted author, either of someone else's project or of a pull request to your own project. Perhaps you're packaging up the software to run it as a less-privileged account. Perhaps you're a sysadmin helping a user figure something out. And so forth.
It wouldn't even require an explicit clone. An attacker could send you a zip file containing a malicious .git directory, and then you'd lose the moment you cd'd into the unzipped directory to check it out.
If allows an attacker to execute arbitrary code in a situation where you wouldn't expect that (such as merely CDing to an attacker-controlled directory), then yeah of course it's a vulnerability.
Didn't work for me - I'm using oh-my-zsh in iTerm2, and I'm just using the git plugin & a custom theme, nothing else. Maybe we're using different plugins?
[1]: https://github.com/git/git/blob/master/contrib/completion/gi...