Bug: global remote.origin.url silently overrides git clone <URL>

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I have stumbled across some very unexpected behaviour in git related
to remote.origin.url. I initially reported it to the security mailing
list because of concern of possible exploits, but Glenn Choo and
Taylor Blau deemed that the issue was outside Git's security boundary,
and thus safe to discuss on the public list.

In short, I found out that if a user for some reason, either
intentionally/maliciously or unintentionally sets `remote.origin.url`
to a repo URL in their *global* config, then a subsequent `git
clone`operation will *silently* use this URL instead of the one
provided as the command line argument to `git clone`.

I believe this is unintentional behaviour, and not just a corner case
I haven’t thought of, because of the following observations:

* The folder name to clone to is still taken from the command-line specified URL
* Git still prints “cloning into…” and the folder name that the user specified
* Git sets sets the *local* `remote.origin.url` to the value provided
* However, Git fetches the actual repo content, and subsequent
workspace checkout, from the URL in the global config, without any
notification to the user.

Security implications: I believe that this behaviour could
theoretically be mis-used for supply-chain attacks, especially on a
build server, but Glenn and Taylor pointed out that if an attacker has
access to modify a global git config, then there are much worse things
they could do. Also, I realise that most build servers these days
don’t actually use `git clone` under normal operations (rather they
use git init, git remote add, git fetch) so the problem isn't that
severe.

If a team disables the regular build server fake cloning behaviour and
does actual cloning in e.g. a shell step for more control, an attacker
with access to pipelines running on the same build node, could
potentially set the global url to a malicious fork of a repo used in
other pipelines, and silently make the other pipelines clone this
forked and patched repo, and potentially execute code within.


What did you do before the bug happened? (Steps to reproduce your issue)
What happened instead? (Actual behaviour)
------------------------------------------------------------------

I discovered the problem in the wild, reproduced it on my Mac (see
later) and then went through the following controlled reproduction in
a Docker environment.

`docker run -it --entrypoint /bin/bash bitnami/git:2.19.2`

```
$ git config --global remote.origin.url https://github.com/JKrag/sc_demo.git
$ git clone https://github.com/eficode-academy/git-katas.git

Cloning into 'git-katas'...

$ cd git-katas
$ ls
README.md (i.e. content from sc_demo, not git-katas)

$ git remote show origin
* remote origin
Fetch URL: https://github.com/JKrag/sc_demo.git
Push URL: https://github.com/JKrag/sc_demo.git
Push URL: https://github.com/eficode-academy/git-katas.git

$ cat .git/config
...
[remote "origin"]
url = https://github.com/eficode-academy/git-katas.git
...


$ git config --list --show-origin |grep "remote\.origin"
file:/root/.gitconfig remote.origin.url=https://github.com/JKrag/sc_demo.git
file:.git/config
remote.origin.url=https://github.com/eficode-academy/git-katas.git
file:.git/config remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*


$ git fetch
$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

$ git config --global --unset remote.origin.url
$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

$ git fetch
remote: Enumerating objects: 2443, done.
remote: Counting objects: 100% (1109/1109), done.
remote: Compressing objects: 100% (465/465), done.
remote: Total 2443 (delta 699), reused 674 (delta 642), pack-reused 1334
Receiving objects: 100% (2443/2443), 2.46 MiB | 6.29 MiB/s, done.
Resolving deltas: 100% (1052/1052), done.
>From https://github.com/eficode-academy/git-katas
+ 398b171...8bc6cc8 master -> origin/master (forced update)
* [new branch] brent-clark-SED-Sw-Mgr/improve-overview ->
origin/brent-clark-SED-Sw-Mgr/improve-overview
* [new branch] improve-rebase-powershell -> origin/improve-rebase-powershell
* [new branch] pr-verify -> origin/pr-verify
* [new branch] reorder-instructions-unclear ->
origin/reorder-instructions-unclear
* [new branch] sofusalbertsen-patch-1 -> origin/sofusalbertsen-patch-1
* [new branch] sofusalbertsen-patch-2 -> origin/sofusalbertsen-patch-2
* [new branch] test-script -> origin/test-script
* [new branch] tree-vis -> origin/tree-vis
* [new branch] uppercase -> origin/uppercase
* [new tag] 0.1.1 -> 0.1.1
* [new tag] 0.2.0 -> 0.2.0
* [new tag] 0.3.0 -> 0.3.0

$ git rev-list --max-parents=0 --all
398b17173d150371977cc12d4406f927a4be32ea # Initial commit from sc-demo repo
ad31d12363a181b998317d5f075d89b3fb990122 # Initial commit from git-katas repo

```


What did you expect to happen? (Expected behaviour)

First off, I would expect that Git used the url specified on the
command line, as it is normal that command-line arguments override
both local and global configs.
Alternatively, if there really is a good reason to use the global
configured one, git should at least take the folder name from there
and print out “Cloning into [global configured repo name]”

In reality, I can’t see any reason why there would ever be a need to
configure global remote.origin.url, and ideally doing so could lead to
an error/warning message, but I also know that the philosophy behind
Git config is to basically allow any settings, and there is no natural
place to “stop” such entries, although I guess it might be reasonable
to expect a warning at least when cloning a new repo.

Anything else you want to add:
--------------------------------------------
Yes, I am aware that this is a very obscure scenario, and as an
experienced Git user, it had never crossed my mind that this could
happen, but I saw it “in the wild” a few weeks ago, when delivering a
2-day Git training. I asked the participants to clone our “git-katas”
repo (as in the reproduced scenario above), and then one participant
was VERY confused because the folder then had “her own code”, and she
couldn’t understand why. After going through her bash history and
verifying that there was no other good explanation, I finally found
the explanation by looking in the global config where I found the
unexpected setting. The user had no real idea how it had gotten there,
except some vague idea of having tried “some stuff” to fix “some
issue” a long time ago. Since she only used a single repo on her
computer, she would never really have noticed under normal conditions.

Platform:
----------------
Problem originally seen “in the wild” on an Ubuntu laptop running Git
2.17 as I recall.
Issue reproduced on OSX Git 2.39.2, and in docker containers running
2.19.2 and 2.40.

[ Local Mac ]
[System Info]
git version:
git version 2.39.2
cpu: x86_64
no commit associated with this build
sizeof-long: 8
sizeof-size_t: 8
shell-path: /bin/sh
feature: fsmonitor--daemon
uname: Darwin 22.4.0 Darwin Kernel Version 22.4.0: Mon Mar 6 21:00:17
PST 2023; root:xnu-8796.101.5~3/RELEASE_X86_64 x86_64
compiler info: clang: 14.0.0 (clang-1400.0.29.202)
libc info: no libc information available
$SHELL (typically, interactive shell): /bin/zsh

[ Bitnami/git:2:40 ]
$ docker run -it --entrypoint /bin/bash bitnami/git:2.40.0
root@89543b59ce2c:/# git version --build-options
git version 2.40.0
cpu: x86_64
$SHELL = /bin/bash

[ Bitnami/git:2.19.2 ]
$ docker run -it --entrypoint /bin/bash bitnami/git:2.19.2
root@6a86a5c92e58:/# git version --build-options
git version 2.19.2
cpu: x86_64
$SHELL = /bin/bash
$ uname -a
Linux 6a86a5c92e58 5.15.49-linuxkit #1 SMP Tue Sep 13 07:51:46 UTC
2022 x86_64 GNU/Linux


Regards Jan

-----------------------
Jan Krag
Git Trainer & DevOps Consultant
jan.krag@xxxxxxxxxxx
www.eficode.com
Copenhagen, Denmark




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux