touch $(echo -e "\e[31mfoo\e[0m")
git-annex add
git-annex whereis

That displays "foo" in red twice. Compare with behavior of git commands that display that filename, which display it escaped.

git-annex should probably do the same, when displaying filenames that it's working on or in messages.

git-annex find is an interesting case because it's expected to be pipeable, and so should have raw filenames. Note that find actually escapes such filenames when outputting to a terminal, but not a pipe.

git porcelain also accepts the escaped form of files as input, necessary for round-tripping though. git-annex currently does not. (git plumbing doesn't either)

While terminals mostly protect against escape sequences doing very bad things, there are security holes in terminals still being found.

Of course, such files in git repos can also be exploited by other commands eg echo *.

So this does not seem like a security hole in git-annex, but it would be useful defense in depth against terminal security holes, and also good to behave more like git.

--Joey

Git.Filename.encode is implemented, and only needs to be used. Note that core.quotePath controls whether git quotes unicode characters (by default it does), so once this gets implemented, some users may want to set that config to false. --Joey

Update: Messages now handles quoting of filenames, and also filtering out any escape sequences in other things that get displayed (like Keys..)

Update: git-annex find and others that output directly all do escaping/filtering.


Also: It's possible that keys can also contain an escape sequence, eg in the extension of a SHA-E key. So commands like git-annex lookupkey and git-annex find that output keys might need to handle that, when outputting to a terminal?

Fixed this with filtering of control characters in output.

Also: git-annex initremote with autoenable may be able to cause a remote with a malicious name to be set up?

Fixed this by silently skipping autoenable, which seems fine since only an attacker would ever try this.

Also: Any place that an exception is thrown with an attacker-controlled value. giveup has been made to filter out control characters, but that leaves other exceptions, including ones thrown by libraries. Catch all exceptions at top-level (of program and/or worker threads) and filter out control characters?

Fixed with a top-level exception catcher; assuming all worker threads have something waiting on them that displays or propagates their exceptions.


all fixed! --Joey