git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH] git_connect: clear GIT_* environment for ssh

From
Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
Date
Sep 5, 2015, 13:50 UTC
Message-ID
<CAOxFTcz9dZRQVnVnt+GtzAiu+GBi7CPE17d7rGo3H0v56MMAZQ@mail.gmail.com>
In-Reply-To
<20150904224008.GA11164@sigill.intra.peff.net>
On Sat, Sep 5, 2015 at 12:40 AM, Jeff King <peff@peff.net> wrote:
Show 5 quoted lines
> So here is the patch I would propose. I'm fairly certain it will solve
> Giuseppe's problem, though I think there is something else odd going on
> here that I don't understand. I'm worried that we're papering over
> another regression. Giuseppe, if you can still find time to do that
> bisect, it would be helpful.

So, as it happens I was able to script the check in a not-too-convoluted way using the same pair of machines where I came across the problem,, and it turns out that the culprit is as obvious as one would expect:

d95138e695d99d32dcad528a2a7974f434c51e79 is the first bad commit
commit d95138e695d99d32dcad528a2a7974f434c51e79
Author: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Date:   Fri Jun 26 17:37:35 2015 +0700
    setup: set env $GIT_WORK_TREE when work tree is set, like $GIT_DIR

which matches my previous findings in that the problem was GIT_WORK_TREE being leaked. Since setting GIT_WORK_TREE when setting GIT_DIR is correct, the solution is indeed to clear GIT_* environment variables for ssh, as you propose. I tested your patch and indeed it fixes my problem.

I still don't understand why you cannot replicate the issue on your side. One thing that is _extremely_ important in reproducing the problem is that the leaked GIT_WORK_TREE point to a non-existent (or otherwise inaccessible) directory in the server machine. For example, on my first attempt to reproduce I was trying to use my clone of the git repo, and it wouldn't work because I _did_ have a ~/src/git on both machines, even though I was pushing to a remote.machine:/tmp/test.git

Would it be worth looking at the issue server-side too, as this looks like something that might have exploit potential? (At the very least, it could be used to test if/which directories the remote user has access to.)

Show 8 quoted lines
> -- >8 --
> Subject: git_connect: clear GIT_* environment for ssh
>
> When we "switch" to another local repository to run the server
> side of a fetch or push, we must clear the variables in
> local_repo_env so that our local $GIT_DIR, etc, do not
> pollute the upload-pack or receive-pack that is executing in
> the "remote" repository.

I think we might want to mention GIT_WORK_TREE explicitly here, since this seems to be the one causing issues.

Show 15 quoted lines
> We have never done so for ssh connections. For the most
> part, nobody has noticed because ssh will not pass unknown
> environment variables by default. However, it is not out of
> the question for a user to configure ssh to pass along GIT_*
> variables using SendEnv/AcceptEnv.
>
> We can demonstrate the problem by using "git -c" on a local
> command and seeing its impact on a remote repository.  This
> config ends up in $GIT_CONFIG_PARAMETERS. In the local case,
> the config has no impact, but in the ssh transport, it does
> (our test script has a fake ssh that passes through all
> environment variables; this isn't normal, but does simulate
> one possible setup).
>
> Signed-off-by: Jeff King <peff@peff.net>

The patch works for me, so aside from the suggested commit message change, I'm all for it.

Reviewed-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
Show 16 quoted lines
> ---
>  connect.c                     |  4 ++--
>  t/t5507-remote-environment.sh | 34 ++++++++++++++++++++++++++++++++++
>  2 files changed, 36 insertions(+), 2 deletions(-)
>  create mode 100755 t/t5507-remote-environment.sh
>
> diff --git a/connect.c b/connect.c
> index c0144d8..962f990 100644
> --- a/connect.c
> +++ b/connect.c
> @@ -721,6 +721,8 @@ struct child_process *git_connect(int fd[2], const char *url,
>                 strbuf_addch(&cmd, ' ');
>                 sq_quote_buf(&cmd, path);
>
> +               /* remove repo-local variables from the environment */
> +               conn->env = local_repo_env;

A posteriori, this makes a lot of sense too: why single out a single protocol in the environment cleanup?

Show 10 quoted lines
>                 conn->in = conn->out = -1;
>                 if (protocol == PROTO_SSH) {
>                         const char *ssh;
> @@ -778,8 +780,6 @@ struct child_process *git_connect(int fd[2], const char *url,
>                         }
>                         argv_array_push(&conn->args, ssh_host);
>                 } else {
> -                       /* remove repo-local variables from the environment */
> -                       conn->env = local_repo_env;
>                         conn->use_shell = 1;

Of course we're now left with just conn->use_shell = 1 in the non-ssh case. This could be moved in front of the if, and replaced with something like conn>use_shell = !(procol == PROTO_SSH), but maybe this would kill legibility. It's just that a single line i the else clause of a large if looks odd.

-- 
Giuseppe "Oblomov" Bilotta
Previous: Jeff KingNext: Jeff King
Message 9 of 12 in “[RFC] a tale of Git 2.5, ssh transport and GIT_* environment variables”
  1. Giuseppe BilottaSep 4, 2015
  2. Jeff KingSep 4, 2015
  3. Giuseppe BilottaSep 4, 2015
  4. Jeff KingSep 4, 2015
  5. Junio C HamanoSep 4, 2015
  6. Giuseppe BilottaSep 4, 2015
  7. Jeff KingSep 4, 2015
  8. git_connect: clear GIT_* environment for sshJeff King, Sep 4, 2015
  9. Giuseppe BilottaSep 5, 2015
  10. git_connect: clarify conn->use_shell flagJeff King, Sep 8, 2015
  11. Junio C HamanoSep 8, 2015
  12. Jeff KingSep 8, 2015

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.