{"thread":{"id":"64145","subject":"safe.directory does not work at all (git 2.39.5, 2.51.0)","startedAt":"2025-09-13T17:46:31Z","lastAt":"2025-09-17T20:22:54Z","messageCount":6,"participants":["Marc-Jano Knopp","Carlo Marcelo Arenas Belón","Jeff King"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"526252","messageId":"duuus2ifgydpwpja6vccvxbcnxdgy6mc6h63okzv7xdqo23fpi@ermurkhms4j3","threadId":"64145","inReplyTo":null,"subject":"safe.directory does not work at all (git 2.39.5, 2.51.0)","fromName":"Marc-Jano Knopp","fromEmail":"y--gitbugs@marc-jano.de","sentAt":"2025-09-13T17:38:53Z","receivedAt":"2025-09-13T17:46:31Z","isPatch":false,"sender":{"key":"y--gitbugs@marc-jano.de","avatar":null},"body":"Hi everyone!\n\n\ngit seems to have freshly implemented some security measure, and the\ndocumented solution / workaround / whatever does not seem to work at all.\nFor the first time in years, git does not work for me anymore, I cannot\npush my changes to the remote repository.\n\nSee below for what was created using \"git bugreport\":\n\n\n=====================================================================\nThank you for filling out a Git bug report!\nPlease answer the following questions to help us understand your issue.\n\n- What did you do before the bug happened? (Steps to reproduce your issue)\n\n  I created a shared bare repo on my.server, permissions for everything\n  are 2770 (rwxrws---) for dirs and 660 (rw-rw----) for files in that\n  remote repository, and all dirs and files belong to root:git. I have\n  an account \"myuser:git\" on that server.\n  \n  Then I tried to clone it to my local PC, which failed to some new\n  security measure git seems to have introduced recently:\n\n--------- snip ---------\n$ git clone myuser@my.server:/git/main/test.git\nCloning into 'test'...\nfatal: detected dubious ownership in repository at '/git/main/test.git'\nTo add an exception for this directory, call:\n\n        git config --global --add safe.directory /git/main/test.git\nfatal: Could not read from remote repository.\n\nPlease make sure you have the correct access rights\nand the repository exists.\n$\n--------- snip ---------\n\n  I did execute the suggested command, so that my ~/.gitconfig now\n  (only) contains:\n\n--------- snip ---------\n[safe]\n        directory = /git/main/test.git\n--------- snip ---------\n          \n  but the error still occurs. Using \"git -c safe.directory='....'\"\n  did not help, either.\n  \n\n- What did you expect to happen? (Expected behavior)\n\n  I expected the disabling of the above security measure to work.\n  Actually, I want safe.directory to be set to \"*\", but that does not\n  work, either.\n  \n\n- What happened instead? (Actual behavior)\n\n  See above.\n\n\n- What's different between what you expected and what actually happened?\n\n  See above.\n\n\n- Anything else you want to add:\n\n  Can we please make suddenly occurring security measures and other\n  breaking changes opt-in?\n\n\nPlease review the rest of the bug report below.\nYou can delete any lines you don't wish to share.\n\n\n[System Info]\ngit version:\ngit version 2.39.5 (same error with 2.51.0 on a different PC)\ncpu: x86_64\nno commit associated with this build\nsizeof-long: 8\nsizeof-size_t: 8\nshell-path: /bin/sh\nuname: Linux 6.12.38+deb12-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.38-1~bpo12+1 (2025-07-27) x86_64\ncompiler info: gnuc: 12.2\nlibc info: glibc: 2.36\n$SHELL (typically, interactive shell): /usr/bin/zsh\n\n\n[Enabled Hooks]\nnot run from a git repository - no hooks to show\n=====================================================================\n\n\nAny help is appreciated!\n\nIf all else fails, I would downgrade to the last git version without\nthat security feature, if someone knows the version number that\nintroduced this feature ...\n\n\nMJK\n"},{"id":"526266","messageId":"lamzerhpp6kbgzbhztgaqvdcymaqvec232sen67t6wx4rmobih@lqqivgroonmp","threadId":"64145","inReplyTo":"duuus2ifgydpwpja6vccvxbcnxdgy6mc6h63okzv7xdqo23fpi@ermurkhms4j3","subject":"Re: safe.directory does not work at all (git 2.39.5, 2.51.0)","fromName":"Carlo Marcelo Arenas Belón","fromEmail":"carenas@gmail.com","sentAt":"2025-09-13T22:13:14Z","receivedAt":"2025-09-13T22:13:17Z","isPatch":false,"sender":{"key":"carenas@gmail.com","avatar":"https://avatars.githubusercontent.com/u/76036?v=4"},"body":"On Sat, Sep 13, 2025 at 07:38:53PM -0800, Marc-Jano Knopp wrote:\n> $ git clone myuser@my.server:/git/main/test.git\n> Cloning into 'test'...\n> fatal: detected dubious ownership in repository at '/git/main/test.git'\n> To add an exception for this directory, call:\n> \n>         git config --global --add safe.directory /git/main/test.git\n> fatal: Could not read from remote repository.\n\nit is a little confusing, but the message comes from the git command\nrunning in \"my.server\".\n\ndoest it work if you run the same command after first doing ssh with \"myuser\"\naccount into \"my.server\"?\n\nCarlo\n"},{"id":"526279","messageId":"hbghuae56gm6ypox6q34mt4q6awoeb3itxsnmgpouycn7qodch@4pjsh24jhmqs","threadId":"64145","inReplyTo":"lamzerhpp6kbgzbhztgaqvdcymaqvec232sen67t6wx4rmobih@lqqivgroonmp","subject":"[SOLVED] Re: safe.directory does not work at all (git 2.39.5, 2.51.0)","fromName":"Marc-Jano Knopp","fromEmail":"y--gitbugs@marc-jano.de","sentAt":"2025-09-14T18:26:53Z","receivedAt":"2025-09-14T18:27:05Z","isPatch":false,"sender":{"key":"y--gitbugs@marc-jano.de","avatar":null},"body":"On Sun, 2025-09-14, at 00:13:14 (+0200), Carlo Marcelo Arenas Belón wrote:\n> On Sat, Sep 13, 2025 at 07:38:53PM -0800, Marc-Jano Knopp wrote:\n> > $ git clone myuser@my.server:/git/main/test.git\n> > Cloning into 'test'...\n> > fatal: detected dubious ownership in repository at '/git/main/test.git'\n> > To add an exception for this directory, call:\n> > \n> >         git config --global --add safe.directory /git/main/test.git\n> > fatal: Could not read from remote repository.\n> \n> it is a little confusing, but the message comes from the git command\n> running in \"my.server\".\n\nD'oh! Is there a way for the layman to see if a message comes from the\nclient or the server?\n\n\n> doest it work if you run the same command after first doing ssh with \"myuser\"\n> account into \"my.server\"?\n\nYes, it does! Thanks a million! *smooch* <3  :)\n\n\nMJK\n"},{"id":"526295","messageId":"20250915022301.GA593748@coredump.intra.peff.net","threadId":"64145","inReplyTo":"hbghuae56gm6ypox6q34mt4q6awoeb3itxsnmgpouycn7qodch@4pjsh24jhmqs","subject":"Re: [SOLVED] Re: safe.directory does not work at all (git 2.39.5, 2.51.0)","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2025-09-15T02:23:01Z","receivedAt":"2025-09-15T02:23:03Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sun, Sep 14, 2025 at 08:26:53PM +0200, Marc-Jano Knopp wrote:\n\n> > > Cloning into 'test'...\n> > > fatal: detected dubious ownership in repository at '/git/main/test.git'\n> > > To add an exception for this directory, call:\n> > > \n> > >         git config --global --add safe.directory /git/main/test.git\n> > > fatal: Could not read from remote repository.\n> > \n> > it is a little confusing, but the message comes from the git command\n> > running in \"my.server\".\n> \n> D'oh! Is there a way for the layman to see if a message comes from the\n> client or the server?\n\nUsually we try to pass error messages from the server over the sideband\nchannel, where the client prefixes them with \"remote:\" before showing\nthem to the user. Or report them via ERR packets, in which case the\nclient says something like \"remote error: foo\". Like:\n\n  [this is an ERR packet; we are asking for a nonsense object id]\n  $ git fetch origin 0000000000000000000000000000000000000001\n  fatal: remote error: upload-pack: not our ref 0000000000000000000000000000000000000001\n\n  [this is stderr from a server sub-process routed over the err\n   sideband; I corrupted the server-side repo by removing one of\n   its packfiles]\n  $ git fetch $url\n  remote: error: Could not read 576053ed5ad378490974fabe97e4bd59633d2d1e\n  remote: fatal: Failed to traverse parents of commit a3287c454eb8f7b89d969e675768a6cfa258ad34\n  remote: aborting due to possible repository corruption on the remote side.\n  fatal: early EOF\n  fatal: index-pack failed\n\nBut for the error you're seeing, it is happening within upload-pack\nitself (the server-side process handling the request), it happens before\nwe have even established that the client can handle sideband data, and\nit is a die() call from within library code that does not know about ERR\npackets. So the message goes to upload-pack's stderr on the server side,\nand then ssh just passes it back. In fact, you are a little lucky to see\nit at all; for a clone over http, it would just go to the webserver's\nlog (or maybe /dev/null).\n\nI do agree it is not very friendly, so I'm laying this out to help\nbrainstorm ideas to make it better. Some possible directions I can think\nof:\n\n  - could upload-pack install a die() handler that prints the message in\n    an ERR packet? I worry a little that older versions of Git would not\n    handle this great, as I don't think they were always prepared to see\n    an ERR packet at any point. OTOH, it is probably better than sending\n    nothing, which is what we do now.\n\n  - could the client-side process (git-clone or git-fetch) intercept\n    stderr from processes it spawns (ssh in this case, but also\n    git-upload-pack directly for local-system clones) and prefix it with\n    \"remote:\" or similar? That might help ssh and local system cases,\n    but other transports like http wouldn't benefit at all. Also, it\n    would probably involve forking off another process to consume\n    stderr.\n\nI dunno. I don't love either of those that much. And while it could help\nthings in general, I think the main clue in this case is just that the\nerror message refers to '/git/main/test.git'. And that path is only\nmeaningful on the server, since the url was my.server:/git/main/test.git.\nKnowing that the config advice is _also_ coming from the server is\nprobably the key subtle bit, though.\n\n-Peff\n"},{"id":"526296","messageId":"20250915024630.GA595592@coredump.intra.peff.net","threadId":"64145","inReplyTo":"20250915022301.GA593748@coredump.intra.peff.net","subject":"Re: [SOLVED] Re: safe.directory does not work at all (git 2.39.5, 2.51.0)","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2025-09-15T02:46:30Z","receivedAt":"2025-09-15T02:46:32Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sun, Sep 14, 2025 at 10:23:01PM -0400, Jeff King wrote:\n\n>   - could upload-pack install a die() handler that prints the message in\n>     an ERR packet? I worry a little that older versions of Git would not\n>     handle this great, as I don't think they were always prepared to see\n>     an ERR packet at any point. OTOH, it is probably better than sending\n>     nothing, which is what we do now.\n\nJust for fun, I tried the patch below on v2.39.5:\n\ndiff --git a/builtin/upload-pack.c b/builtin/upload-pack.c\nindex f446ff04f6..ad40143beb 100644\n--- a/builtin/upload-pack.c\n+++ b/builtin/upload-pack.c\n@@ -13,6 +13,21 @@ static const char * const upload_pack_usage[] = {\n \tNULL\n };\n \n+NORETURN\n+static void send_err_pkt_on_die(const char *fmt, va_list ap)\n+{\n+\tstruct strbuf buf = STRBUF_INIT;\n+\n+\t/* format into a buf since interfaces below do not handle va_list */\n+\tstrbuf_vaddf(&buf, fmt, ap);\n+\n+\t/* write our ERR packet */\n+\tpacket_write_fmt_gently(1, \"ERR %s\", buf.buf);\n+\n+\t/* and then do the usual die to stderr */\n+\texit(die_message(\"%s\", buf.buf));\n+}\n+\n int cmd_upload_pack(int argc, const char **argv, const char *prefix)\n {\n \tconst char *dir;\n@@ -38,6 +53,8 @@ int cmd_upload_pack(int argc, const char **argv, const char *prefix)\n \t/* TODO: This should use NO_LAZY_FETCH_ENVIRONMENT */\n \txsetenv(\"GIT_NO_LAZY_FETCH\", \"1\", 0);\n \n+\tset_die_routine(send_err_pkt_on_die);\n+\n \targc = parse_options(argc, argv, prefix, options, upload_pack_usage, 0);\n \n \tif (argc != 1)\n\n\nThe results are...not great. You get every message twice, of course,\nbecause we still print it to stderr. Though that could easily be fixed.\nBut for the multi-line message in question, the \"remote error\" part is\nhard to see amidst the other lines:\n\n  Cloning into 'foo'...\n  fatal: detected dubious ownership in repository at '/tmp/foo.git'\n  To add an exception for this directory, call:\n  \n  \tgit config --global --add safe.directory /tmp/foo.git\n  fatal: remote error: detected dubious ownership in repository at '/tmp/foo.git'\n  To add an exception for this directory, call:\n  \n  \tgit config --global --add safe.directory /tmp/foo.git\n\nProbably it would help to look for newlines and prefix every line with\n\"remote: or similar. But an even bigger problem is that we die\nimmediately on seeing the remote ERR packet, so we miss out on any local\nerror messages. An obvious one is trying to clone something that doesn't\nexist at all. We used to say:\n\n  Cloning into 'does-not-exist'...\n  fatal: '/tmp/does-not-exist.git' does not appear to be a git repository\n  fatal: Could not read from remote repository.\n\n  Please make sure you have the correct access rights\n  and the repository exists.\n\nNoting that we saw an error from the remote side and giving some hints.\nAnd the stderr from the other side is enough to give us the more\nspecific message (though again, over http the user would not get that\nstderr message; however, if we get a 404 we do show a useful message).\n\nBut with the patch above we just relay what the other side says:\n\n  Cloning into 'does-not-exist'...\n  fatal: '/tmp/does-not-exist.git' does not appear to be a git repository\n  fatal: remote error: '/tmp/does-not-exist.git' does not appear to be a git repository\n\nwhich seems worse to me.\n\nSo probably not a very productive direction. Oh well.\n\n-Peff\n"},{"id":"526618","messageId":"vuldcnyfwo6nii35kpwzpjws74hvgbeesovjpq4r5n2244usry@svmiikrnpviu","threadId":"64145","inReplyTo":"20250915022301.GA593748@coredump.intra.peff.net","subject":"Re: [SOLVED] Re: safe.directory does not work at all (git 2.39.5, 2.51.0)","fromName":"Marc-Jano Knopp","fromEmail":"y--gitbugs@marc-jano.de","sentAt":"2025-09-17T20:22:43Z","receivedAt":"2025-09-17T20:22:54Z","isPatch":false,"sender":{"key":"y--gitbugs@marc-jano.de","avatar":null},"body":"On Mon, 2025-09-15, at 04:23:01 (+0200), Jeff King wrote:\n[...]\n> I dunno. I don't love either of those that much. And while it could help\n> things in general, I think the main clue in this case is just that the\n> error message refers to '/git/main/test.git'. And that path is only\n> meaningful on the server, since the url was my.server:/git/main/test.git.\nGood point!\n\n> Knowing that the config advice is _also_ coming from the server is\n> probably the key subtle bit, though.\nYeah, the keyword \"remote\" would probably have been successfully caught\nby my brain's pattern matching algorithm ...\n\n\nMJK\n"}]}