{"thread":{"id":"59792","subject":"Bug: global remote.origin.url silently overrides git clone <URL>","startedAt":"2023-05-26T08:28:53Z","lastAt":"2023-05-26T08:28:53Z","messageCount":1,"participants":["Jan Krag"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"477731","messageId":"CAF0TW5uB0zbSqw7rUFxED77683h7qHoqeBD6dnSOCpajGV=tYw@mail.gmail.com","threadId":"59792","inReplyTo":null,"subject":"Bug: global remote.origin.url silently overrides git clone <URL>","fromName":"Jan Krag","fromEmail":"jan.krag@eficode.com","sentAt":"2023-05-26T08:28:26Z","receivedAt":"2023-05-26T08:28:53Z","isPatch":false,"sender":{"key":"jan.krag@eficode.com","avatar":null},"body":"I have stumbled across some very unexpected behaviour in git related\nto remote.origin.url. I initially reported it to the security mailing\nlist because of concern of possible exploits, but Glenn Choo and\nTaylor Blau deemed that the issue was outside Git's security boundary,\nand thus safe to discuss on the public list.\n\nIn short, I found out that if a user for some reason, either\nintentionally/maliciously or unintentionally sets `remote.origin.url`\nto a repo URL in their *global* config, then a subsequent `git\nclone`operation will *silently* use this URL instead of the one\nprovided as the command line argument to `git clone`.\n\nI believe this is unintentional behaviour, and not just a corner case\nI haven’t thought of, because of the following observations:\n\n* The folder name to clone to is still taken from the command-line specified URL\n* Git still prints “cloning into…” and the folder name that the user specified\n* Git sets sets the *local* `remote.origin.url` to the value provided\n* However, Git fetches the actual repo content, and subsequent\nworkspace checkout, from the URL in the global config, without any\nnotification to the user.\n\nSecurity implications: I believe that this behaviour could\ntheoretically be mis-used for supply-chain attacks, especially on a\nbuild server, but Glenn and Taylor pointed out that if an attacker has\naccess to modify a global git config, then there are much worse things\nthey could do. Also, I realise that most build servers these days\ndon’t actually use `git clone` under normal operations (rather they\nuse git init, git remote add, git fetch) so the problem isn't that\nsevere.\n\nIf a team disables the regular build server fake cloning behaviour and\ndoes actual cloning in e.g. a shell step for more control, an attacker\nwith access to pipelines running on the same build node, could\npotentially set the global url to a malicious fork of a repo used in\nother pipelines, and silently make the other pipelines clone this\nforked and patched repo, and potentially execute code within.\n\n\nWhat did you do before the bug happened? (Steps to reproduce your issue)\nWhat happened instead? (Actual behaviour)\n------------------------------------------------------------------\n\nI discovered the problem in the wild, reproduced it on my Mac (see\nlater) and then went through the following controlled reproduction in\na Docker environment.\n\n`docker run -it --entrypoint /bin/bash bitnami/git:2.19.2`\n\n```\n$ git config --global remote.origin.url https://github.com/JKrag/sc_demo.git\n$ git clone https://github.com/eficode-academy/git-katas.git\n\nCloning into 'git-katas'...\n\n$ cd git-katas\n$ ls\nREADME.md (i.e. content from sc_demo, not git-katas)\n\n$ git remote show origin\n* remote origin\nFetch URL: https://github.com/JKrag/sc_demo.git\nPush URL: https://github.com/JKrag/sc_demo.git\nPush URL: https://github.com/eficode-academy/git-katas.git\n\n$ cat .git/config\n...\n[remote \"origin\"]\nurl = https://github.com/eficode-academy/git-katas.git\n...\n\n\n$ git config --list --show-origin |grep \"remote\\.origin\"\nfile:/root/.gitconfig remote.origin.url=https://github.com/JKrag/sc_demo.git\nfile:.git/config\nremote.origin.url=https://github.com/eficode-academy/git-katas.git\nfile:.git/config remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*\n\n\n$ git fetch\n$ git status\nOn branch master\nYour branch is up to date with 'origin/master'.\n\nnothing to commit, working tree clean\n\n$ git config --global --unset remote.origin.url\n$ git status\nOn branch master\nYour branch is up to date with 'origin/master'.\n\nnothing to commit, working tree clean\n\n$ git fetch\nremote: Enumerating objects: 2443, done.\nremote: Counting objects: 100% (1109/1109), done.\nremote: Compressing objects: 100% (465/465), done.\nremote: Total 2443 (delta 699), reused 674 (delta 642), pack-reused 1334\nReceiving objects: 100% (2443/2443), 2.46 MiB | 6.29 MiB/s, done.\nResolving deltas: 100% (1052/1052), done.\nFrom https://github.com/eficode-academy/git-katas\n+ 398b171...8bc6cc8 master -> origin/master (forced update)\n* [new branch] brent-clark-SED-Sw-Mgr/improve-overview ->\norigin/brent-clark-SED-Sw-Mgr/improve-overview\n* [new branch] improve-rebase-powershell -> origin/improve-rebase-powershell\n* [new branch] pr-verify -> origin/pr-verify\n* [new branch] reorder-instructions-unclear ->\norigin/reorder-instructions-unclear\n* [new branch] sofusalbertsen-patch-1 -> origin/sofusalbertsen-patch-1\n* [new branch] sofusalbertsen-patch-2 -> origin/sofusalbertsen-patch-2\n* [new branch] test-script -> origin/test-script\n* [new branch] tree-vis -> origin/tree-vis\n* [new branch] uppercase -> origin/uppercase\n* [new tag] 0.1.1 -> 0.1.1\n* [new tag] 0.2.0 -> 0.2.0\n* [new tag] 0.3.0 -> 0.3.0\n\n$ git rev-list --max-parents=0 --all\n398b17173d150371977cc12d4406f927a4be32ea # Initial commit from sc-demo repo\nad31d12363a181b998317d5f075d89b3fb990122 # Initial commit from git-katas repo\n\n```\n\n\nWhat did you expect to happen? (Expected behaviour)\n\nFirst off, I would expect that Git used the url specified on the\ncommand line, as it is normal that command-line arguments override\nboth local and global configs.\nAlternatively, if there really is a good reason to use the global\nconfigured one, git should at least take the folder name from there\nand print out “Cloning into [global configured repo name]”\n\nIn reality, I can’t see any reason why there would ever be a need to\nconfigure global remote.origin.url, and ideally doing so could lead to\nan error/warning message, but I also know that the philosophy behind\nGit config is to basically allow any settings, and there is no natural\nplace to “stop” such entries, although I guess it might be reasonable\nto expect a warning at least when cloning a new repo.\n\nAnything else you want to add:\n--------------------------------------------\nYes, I am aware that this is a very obscure scenario, and as an\nexperienced Git user, it had never crossed my mind that this could\nhappen, but I saw it “in the wild” a few weeks ago, when delivering a\n2-day Git training. I asked the participants to clone our “git-katas”\nrepo (as in the reproduced scenario above), and then one participant\nwas VERY confused because the folder then had “her own code”, and she\ncouldn’t understand why. After going through her bash history and\nverifying that there was no other good explanation, I finally found\nthe explanation by looking in the global config where I found the\nunexpected setting. The user had no real idea how it had gotten there,\nexcept some vague idea of having tried “some stuff” to fix “some\nissue” a long time ago. Since she only used a single repo on her\ncomputer, she would never really have noticed under normal conditions.\n\nPlatform:\n----------------\nProblem originally seen “in the wild” on an Ubuntu laptop running Git\n2.17 as I recall.\nIssue reproduced on OSX Git 2.39.2, and in docker containers running\n2.19.2 and 2.40.\n\n[ Local Mac ]\n[System Info]\ngit version:\ngit version 2.39.2\ncpu: x86_64\nno commit associated with this build\nsizeof-long: 8\nsizeof-size_t: 8\nshell-path: /bin/sh\nfeature: fsmonitor--daemon\nuname: Darwin 22.4.0 Darwin Kernel Version 22.4.0: Mon Mar 6 21:00:17\nPST 2023; root:xnu-8796.101.5~3/RELEASE_X86_64 x86_64\ncompiler info: clang: 14.0.0 (clang-1400.0.29.202)\nlibc info: no libc information available\n$SHELL (typically, interactive shell): /bin/zsh\n\n[ Bitnami/git:2:40 ]\n$ docker run -it --entrypoint /bin/bash bitnami/git:2.40.0\nroot@89543b59ce2c:/# git version --build-options\ngit version 2.40.0\ncpu: x86_64\n$SHELL = /bin/bash\n\n[ Bitnami/git:2.19.2 ]\n$ docker run -it --entrypoint /bin/bash bitnami/git:2.19.2\nroot@6a86a5c92e58:/# git version --build-options\ngit version 2.19.2\ncpu: x86_64\n$SHELL = /bin/bash\n$ uname -a\nLinux 6a86a5c92e58 5.15.49-linuxkit #1 SMP Tue Sep 13 07:51:46 UTC\n2022 x86_64 GNU/Linux\n\n\nRegards Jan\n\n-----------------------\nJan Krag\nGit Trainer & DevOps Consultant\njan.krag@eficode.com\nwww.eficode.com\nCopenhagen, Denmark\n"}]}