Hacker News new | past | comments | ask | show | jobs | submit login
Command Path Security in Go (golang.org)
136 points by pjmlp on Jan 25, 2021 | hide | past | favorite | 13 comments



> If that describes you, today is a good day to remove dot from your path

Good security tip/reminder! It's a slight inconvenience to have to type "./" in front of any local executable or script you want to run, and it's tempting to add "." to $PATH, but here's a good reason it's not there by default.


Is it actually inconvenient? I think it only took me a month or something to get used to typing `./` for commands not in my path when I switched to Unix (and someone explained why adding a . to path was a bad idea); I don't think I've forgotten to type `./` when running a directory-local script or binary in decades.

The difference between "run a system command" and "run a command in this directory" is as different to me as "the cat" and "a cat" -- I'm as likely to forget the `./` as I am to forget an article when composing a sentence.


On e.g. a Swedish keyboard it's physically inconvenient, since '/' is typed by pressing Shift-7. I agree with your distinction between system and directory-local commands though.


I've never seen a Swedish keyboard before. Neat.

On my keyboard I've remapped the caps lock to control, pause/break to suspend, etc. Is "§" used often, or could that be safely remapped?


I don't think I've ever seen anyone write a § except when discussing its uselessness on the keyboard (much like ¤). It's somewhat common for people to switch to US layout while programming, probably more so than remapping.


You don't have to give up the convenience of it if you don't want to.

If you're using zsh, it has the "command_not_found" option, which will be triggered for shell commands that aren't found, but won't be triggered for subcommands or non-interactive shells.

If you add the following as your command not found handler, you'll be able to keep on typing "a.out" instead of "./a.out" without the security issue.

    command_not_found_handler() { [ -x "./$0" ] && exec "./$@" }
Bash has a similar mechanism (command_not_found_handle) as well.


The point is that you don't want this convenience, implemented in any way. You want to be sure that all the invocations of stuff like `ssh` or `sudo` or even plain `cat` would actually come from your OS userland, and not some executable that happens to be in the current directory.


With this, it's only run from cwd if there is no "ssh" in PATH. It's basically the same as putting "." at the end of the PATH though.

Putting "." at the start of PATH is probably not a good idea (and probably also not very convenient), but putting it at the end should be mostly harmless for most desktop users.


It's better than putting '.' at the end of your path though, because your PATH is inherited by non-interactive processes (like the compiler run by 'go get'), while command_not_found is only for your interactive shell session.

The vulnerability this post is about is one where command_not_found is safe, but a '.' at the end might not be (if you don't have 'gcc' installed, but the malicious repository you 'go get' included a 'gcc' executable)


You might also occasionally mistype ssh as shs or so?


What's the point of this? The original vulnerability was "I execute an untrusted binary because my shell searched an untrusted directory". Isn't this just reimplementing PATH and still subject to the same vulnerability?


The vulnerability was that 'go get github.com/malicious/go-repo' would execute arbitrary code if that repo had a specifically named executable file in it.

A user's interactive terminal having certain conveniences is different, and the command not found handler is only used in an interactive context.

Yes, if a user types "pwnme" in their terminal in a directory that has a malicious executable from the internet named "pwnme", they're owned. Same as if they type "./pwnme" without the command not found handler.

It doesn't really change anything; you have to be aware of what you're typing and what it'll do at an interactive terminal.

The go one is a vulnerability because 'go get' is supposed to have a contract that it can't execute arbitrary code, while an interactive terminal that a user types text into doesn't necessarily have that contract.

Also, it will try the path _first_ before command-not-found, so most forms of this vulnerability (a file named 'ls' or whatever) won't cause a vulnerability with this helper variant.


PATH is one of those puzzling concepts that shell beginners grapple with.

It’s a miracle that Windows and Unix converged a similar implantation.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: