{"thread":{"id":"64734","subject":"[PATCH] t5550: add netrc tests for http 401/403","startedAt":"2026-01-06T09:42:18Z","lastAt":"2026-02-06T20:53:29Z","messageCount":14,"participants":["Ashlesh Gawande","Junio C Hamano","Jeff King"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"533116","messageId":"20260106093451.748761-1-git@ashlesh.me","threadId":"64734","inReplyTo":null,"subject":"[PATCH] t5550: add netrc tests for http 401/403","fromName":"Ashlesh Gawande","fromEmail":"git@ashlesh.me","sentAt":"2026-01-06T09:34:51Z","receivedAt":"2026-01-06T09:42:18Z","isPatch":true,"sender":{"key":"git@ashlesh.me","avatar":"https://avatars.githubusercontent.com/u/8251376?v=4"},"body":"Signed-off-by: Ashlesh Gawande <git@ashlesh.me>\n---\nSending netrc test patches as suggested in: https://lore.kernel.org/git/aPAg3gYwzA9fHCC3@fruit.crustytoothpaste.net\n\n t/lib-httpd.sh             |  9 +++++++++\n t/lib-httpd/apache.conf    |  4 ++++\n t/lib-httpd/passwd         |  1 +\n t/t5550-http-fetch-dumb.sh | 25 +++++++++++++++++++++++++\n 4 files changed, 39 insertions(+)\n\ndiff --git a/t/lib-httpd.sh b/t/lib-httpd.sh\nindex 5091db949b..cdc92b2916 100644\n--- a/t/lib-httpd.sh\n+++ b/t/lib-httpd.sh\n@@ -325,6 +325,15 @@ set_askpass() {\n \techo \"$2\" >\"$TRASH_DIRECTORY/askpass-pass\"\n }\n \n+set_netrc() {\n+\t# $HOME=$TRASH_DIRECTORY\n+\techo \"machine $1 login $2 password $3\" > $TRASH_DIRECTORY/.netrc\n+}\n+\n+clear_netrc() {\n+\trm \"$TRASH_DIRECTORY/.netrc\"\n+}\n+\n expect_askpass() {\n \tdest=$HTTPD_DEST${3+/$3}\n \ndiff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf\nindex e631ab0eb5..6b8c50a51a 100644\n--- a/t/lib-httpd/apache.conf\n+++ b/t/lib-httpd/apache.conf\n@@ -238,6 +238,10 @@ SSLEngine On\n \tAuthName \"git-auth\"\n \tAuthUserFile passwd\n \tRequire valid-user\n+\n+\t# return 403 for authenticated user: forbidden-user@host\n+\tRewriteCond \"%{REMOTE_USER}\" \"^forbidden-user@host\"\n+\tRewriteRule ^ - [F]\n </Location>\n \n <LocationMatch \"^/auth-push/.*/git-receive-pack$\">\ndiff --git a/t/lib-httpd/passwd b/t/lib-httpd/passwd\nindex d9c122f348..3bab7b6423 100644\n--- a/t/lib-httpd/passwd\n+++ b/t/lib-httpd/passwd\n@@ -1 +1,2 @@\n user@host:$apr1$LGPmCZWj$9vxEwj5Z5GzQLBMxp3mCx1\n+forbidden-user@host:$apr1$LGPmCZWj$9vxEwj5Z5GzQLBMxp3mCx1\ndiff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh\nindex ed0ad66fad..e002c7357d 100755\n--- a/t/t5550-http-fetch-dumb.sh\n+++ b/t/t5550-http-fetch-dumb.sh\n@@ -102,6 +102,31 @@ test_expect_success 'cloning password-protected repository can fail' '\n \texpect_askpass both wrong\n '\n \n+test_expect_success 'using credentials from netrc to clone successfully' '\n+\tset_askpass wrong &&\n+\tset_netrc 127.0.0.1 user@host pass@host &&\n+\tgit clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc &&\n+\texpect_askpass none\n+'\n+clear_netrc\n+\n+test_expect_success 'netrc unauthorized credentials (prompt after 401)' '\n+\tset_askpass wrong &&\n+\tset_netrc 127.0.0.1 user@host pass@wrong &&\n+\ttest_must_fail git clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc-401 &&\n+\texpect_askpass both wrong\n+'\n+clear_netrc\n+\n+test_expect_success 'netrc authorized but forbidden credentials (fail on 403)' '\n+\tset_askpass wrong &&\n+\tset_netrc 127.0.0.1 forbidden-user@host pass@host &&\n+\ttest_must_fail git clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc-403 2>err &&\n+\texpect_askpass none &&\n+\tgrep \"The requested URL returned error: 403\" err\n+'\n+clear_netrc\n+\n test_expect_success 'http auth can use user/pass in URL' '\n \tset_askpass wrong &&\n \tgit clone \"$HTTPD_URL_USER_PASS/auth/dumb/repo.git\" clone-auth-none &&\n\nbase-commit: e0bfec3dfc356f7d808eb5ee546a54116b794397\n-- \n2.43.0\n\n"},{"id":"533122","messageId":"xmqqjyxvjb4c.fsf@gitster.g","threadId":"64734","inReplyTo":"20260106093451.748761-1-git@ashlesh.me","subject":"Re: [PATCH] t5550: add netrc tests for http 401/403","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-01-06T10:20:35Z","receivedAt":"2026-01-06T10:20:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ashlesh Gawande <git@ashlesh.me> writes:\n\n> Signed-off-by: Ashlesh Gawande <git@ashlesh.me>\n> ---\n> Sending netrc test patches as suggested in: https://lore.kernel.org/git/aPAg3gYwzA9fHCC3@fruit.crustytoothpaste.net\n\nAt the conceptual level, I am happy to have tests for features that\nwe claim to support.  It is a different matter if we want to support\nnetrc, though ;-).\n\nThere are some nits.\n\n> +set_netrc() {\n\nStyle.  SP on both sides of ().  I.e.\n\n    set_netrc () {\n\n> +\t# $HOME=$TRASH_DIRECTORY\n> +\techo \"machine $1 login $2 password $3\" > $TRASH_DIRECTORY/.netrc\n\nStyle.  No space between the redirection operator \">\" and\nredirection target.\n\nStyle.  Enclose the redirection target inside a pair of double\nquotes if it involves variable interpolation.  I.e.\n\n\techo ... >\"$TRASH_DIRECTORY/.netrc\"\n\n> +}\n> +\n> +clear_netrc() {\n\nDitto.\n\n> +\trm \"$TRASH_DIRECTORY/.netrc\"\n> +}\n\nShould this fail if .netrc did not exist in the first place, or is\nthe primary purpose of this helper to ensure the file does not exist\nafter it returns (in which case it would be desirable not to fail if\nthe file did not exist when it was called, with \"rm -f\")?\n\n>  expect_askpass() {\n\nDitto.\n\n> +test_expect_success 'using credentials from netrc to clone successfully' '\n> +\tset_askpass wrong &&\n> +\tset_netrc 127.0.0.1 user@host pass@host &&\n> +\tgit clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc &&\n> +\texpect_askpass none\n> +'\n> +clear_netrc\n\nWe try not to run random shell functions outside the test_expect_*\nblocks.  A clean-up function like this is better called at the end\nof each piece, arranged with the test_when_finished helper.\n\n\ttest_expect_success 'do random thing' '\n\t\ttest_when_finished clear_netrc &&\n\t\tset_askpass wrong &&\n\t\tset_netrc ... &&\n\t\t...\n\t'\n\n"},{"id":"533136","messageId":"20260106114029.763351-1-git@ashlesh.me","threadId":"64734","inReplyTo":"20260106093451.748761-1-git@ashlesh.me","subject":"[PATCH v2] t5550: add netrc tests for http 401/403","fromName":"Ashlesh Gawande","fromEmail":"git@ashlesh.me","sentAt":"2026-01-06T11:40:29Z","receivedAt":"2026-01-06T11:47:29Z","isPatch":true,"sender":{"key":"git@ashlesh.me","avatar":"https://avatars.githubusercontent.com/u/8251376?v=4"},"body":"Signed-off-by: Ashlesh Gawande <git@ashlesh.me>\n---\nRange-diff against v1:\n1:  27e112ea42 ! 1:  0b68f1d1af t5550: add netrc tests for http 401/403\n    @@ Commit message\n         Signed-off-by: Ashlesh Gawande <git@ashlesh.me>\n     \n      ## t/lib-httpd.sh ##\n    -@@ t/lib-httpd.sh: set_askpass() {\n    +@@ t/lib-httpd.sh: setup_askpass_helper() {\n    + \t'\n    + }\n    + \n    +-set_askpass() {\n    ++set_askpass () {\n    + \t>\"$TRASH_DIRECTORY/askpass-query\" &&\n    + \techo \"$1\" >\"$TRASH_DIRECTORY/askpass-user\" &&\n      \techo \"$2\" >\"$TRASH_DIRECTORY/askpass-pass\"\n      }\n      \n    -+set_netrc() {\n    +-expect_askpass() {\n    ++set_netrc () {\n     +\t# $HOME=$TRASH_DIRECTORY\n    -+\techo \"machine $1 login $2 password $3\" > $TRASH_DIRECTORY/.netrc\n    ++\techo \"machine $1 login $2 password $3\" >\"$TRASH_DIRECTORY/.netrc\"\n     +}\n     +\n    -+clear_netrc() {\n    -+\trm \"$TRASH_DIRECTORY/.netrc\"\n    ++clear_netrc () {\n    ++\trm -f \"$TRASH_DIRECTORY/.netrc\"\n     +}\n     +\n    - expect_askpass() {\n    ++expect_askpass () {\n      \tdest=$HTTPD_DEST${3+/$3}\n      \n    + \t{\n     \n      ## t/lib-httpd/apache.conf ##\n     @@ t/lib-httpd/apache.conf: SSLEngine On\n    @@ t/t5550-http-fetch-dumb.sh: test_expect_success 'cloning password-protected repo\n      '\n      \n     +test_expect_success 'using credentials from netrc to clone successfully' '\n    ++\ttest_when_finished clear_netrc &&\n     +\tset_askpass wrong &&\n     +\tset_netrc 127.0.0.1 user@host pass@host &&\n     +\tgit clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc &&\n     +\texpect_askpass none\n     +'\n    -+clear_netrc\n     +\n     +test_expect_success 'netrc unauthorized credentials (prompt after 401)' '\n    ++\ttest_when_finished clear_netrc &&\n     +\tset_askpass wrong &&\n     +\tset_netrc 127.0.0.1 user@host pass@wrong &&\n     +\ttest_must_fail git clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc-401 &&\n     +\texpect_askpass both wrong\n     +'\n    -+clear_netrc\n     +\n     +test_expect_success 'netrc authorized but forbidden credentials (fail on 403)' '\n    ++\ttest_when_finished clear_netrc &&\n     +\tset_askpass wrong &&\n     +\tset_netrc 127.0.0.1 forbidden-user@host pass@host &&\n     +\ttest_must_fail git clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc-403 2>err &&\n     +\texpect_askpass none &&\n     +\tgrep \"The requested URL returned error: 403\" err\n     +'\n    -+clear_netrc\n     +\n      test_expect_success 'http auth can use user/pass in URL' '\n      \tset_askpass wrong &&\n\n t/lib-httpd.sh             | 13 +++++++++++--\n t/lib-httpd/apache.conf    |  4 ++++\n t/lib-httpd/passwd         |  1 +\n t/t5550-http-fetch-dumb.sh | 25 +++++++++++++++++++++++++\n 4 files changed, 41 insertions(+), 2 deletions(-)\n\ndiff --git a/t/lib-httpd.sh b/t/lib-httpd.sh\nindex 5091db949b..5f42c311c2 100644\n--- a/t/lib-httpd.sh\n+++ b/t/lib-httpd.sh\n@@ -319,13 +319,22 @@ setup_askpass_helper() {\n \t'\n }\n \n-set_askpass() {\n+set_askpass () {\n \t>\"$TRASH_DIRECTORY/askpass-query\" &&\n \techo \"$1\" >\"$TRASH_DIRECTORY/askpass-user\" &&\n \techo \"$2\" >\"$TRASH_DIRECTORY/askpass-pass\"\n }\n \n-expect_askpass() {\n+set_netrc () {\n+\t# $HOME=$TRASH_DIRECTORY\n+\techo \"machine $1 login $2 password $3\" >\"$TRASH_DIRECTORY/.netrc\"\n+}\n+\n+clear_netrc () {\n+\trm -f \"$TRASH_DIRECTORY/.netrc\"\n+}\n+\n+expect_askpass () {\n \tdest=$HTTPD_DEST${3+/$3}\n \n \t{\ndiff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf\nindex e631ab0eb5..6b8c50a51a 100644\n--- a/t/lib-httpd/apache.conf\n+++ b/t/lib-httpd/apache.conf\n@@ -238,6 +238,10 @@ SSLEngine On\n \tAuthName \"git-auth\"\n \tAuthUserFile passwd\n \tRequire valid-user\n+\n+\t# return 403 for authenticated user: forbidden-user@host\n+\tRewriteCond \"%{REMOTE_USER}\" \"^forbidden-user@host\"\n+\tRewriteRule ^ - [F]\n </Location>\n \n <LocationMatch \"^/auth-push/.*/git-receive-pack$\">\ndiff --git a/t/lib-httpd/passwd b/t/lib-httpd/passwd\nindex d9c122f348..3bab7b6423 100644\n--- a/t/lib-httpd/passwd\n+++ b/t/lib-httpd/passwd\n@@ -1 +1,2 @@\n user@host:$apr1$LGPmCZWj$9vxEwj5Z5GzQLBMxp3mCx1\n+forbidden-user@host:$apr1$LGPmCZWj$9vxEwj5Z5GzQLBMxp3mCx1\ndiff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh\nindex ed0ad66fad..9530f01b9e 100755\n--- a/t/t5550-http-fetch-dumb.sh\n+++ b/t/t5550-http-fetch-dumb.sh\n@@ -102,6 +102,31 @@ test_expect_success 'cloning password-protected repository can fail' '\n \texpect_askpass both wrong\n '\n \n+test_expect_success 'using credentials from netrc to clone successfully' '\n+\ttest_when_finished clear_netrc &&\n+\tset_askpass wrong &&\n+\tset_netrc 127.0.0.1 user@host pass@host &&\n+\tgit clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc &&\n+\texpect_askpass none\n+'\n+\n+test_expect_success 'netrc unauthorized credentials (prompt after 401)' '\n+\ttest_when_finished clear_netrc &&\n+\tset_askpass wrong &&\n+\tset_netrc 127.0.0.1 user@host pass@wrong &&\n+\ttest_must_fail git clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc-401 &&\n+\texpect_askpass both wrong\n+'\n+\n+test_expect_success 'netrc authorized but forbidden credentials (fail on 403)' '\n+\ttest_when_finished clear_netrc &&\n+\tset_askpass wrong &&\n+\tset_netrc 127.0.0.1 forbidden-user@host pass@host &&\n+\ttest_must_fail git clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc-403 2>err &&\n+\texpect_askpass none &&\n+\tgrep \"The requested URL returned error: 403\" err\n+'\n+\n test_expect_success 'http auth can use user/pass in URL' '\n \tset_askpass wrong &&\n \tgit clone \"$HTTPD_URL_USER_PASS/auth/dumb/repo.git\" clone-auth-none &&\n-- \n2.43.0\n\n"},{"id":"533137","messageId":"168f4c53-4f33-42e3-b3c9-b44ab101da94@ashlesh.me","threadId":"64734","inReplyTo":"xmqqjyxvjb4c.fsf@gitster.g","subject":"Re: [PATCH] t5550: add netrc tests for http 401/403","fromName":"Ashlesh Gawande","fromEmail":"git@ashlesh.me","sentAt":"2026-01-06T11:47:32Z","receivedAt":"2026-01-06T11:53:05Z","isPatch":true,"sender":{"key":"git@ashlesh.me","avatar":"https://avatars.githubusercontent.com/u/8251376?v=4"},"body":"\nOn 1/6/26 15:50, Junio C Hamano wrote:\n> Ashlesh Gawande <git@ashlesh.me> writes:\n>\n>> Signed-off-by: Ashlesh Gawande <git@ashlesh.me>\n>> ---\n>> Sending netrc test patches as suggested in: https://lore.kernel.org/git/aPAg3gYwzA9fHCC3@fruit.crustytoothpaste.net\n> At the conceptual level, I am happy to have tests for features that\n> we claim to support.  It is a different matter if we want to support\n> netrc, though ;-).\n>\n> There are some nits.\nThanks for the quick review!\nI think Brian also suggested getting rid of netrc in the future.\nI have sent v2 to address your comments.\n>\n>> +set_netrc() {\n> Style.  SP on both sides of ().  I.e.\n>\n>      set_netrc () {\n>\n>> +\t# $HOME=$TRASH_DIRECTORY\n>> +\techo \"machine $1 login $2 password $3\" > $TRASH_DIRECTORY/.netrc\n> Style.  No space between the redirection operator \">\" and\n> redirection target.\n>\n> Style.  Enclose the redirection target inside a pair of double\n> quotes if it involves variable interpolation.  I.e.\n>\n> \techo ... >\"$TRASH_DIRECTORY/.netrc\"\n>\n>> +}\n>> +\n>> +clear_netrc() {\n> Ditto.\n>\n>> +\trm \"$TRASH_DIRECTORY/.netrc\"\n>> +}\n> Should this fail if .netrc did not exist in the first place, or is\n> the primary purpose of this helper to ensure the file does not exist\n> after it returns (in which case it would be desirable not to fail if\n> the file did not exist when it was called, with \"rm -f\")?\nYes, the primary purpose is to just clear the file as it might \npotentially break other tests (added -f in v2).\n>>   expect_askpass() {\n> Ditto.\n>\n>> +test_expect_success 'using credentials from netrc to clone successfully' '\n>> +\tset_askpass wrong &&\n>> +\tset_netrc 127.0.0.1 user@host pass@host &&\n>> +\tgit clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc &&\n>> +\texpect_askpass none\n>> +'\n>> +clear_netrc\n> We try not to run random shell functions outside the test_expect_*\n> blocks.  A clean-up function like this is better called at the end\n> of each piece, arranged with the test_when_finished helper.\n>\n> \ttest_expect_success 'do random thing' '\n> \t\ttest_when_finished clear_netrc &&\n> \t\tset_askpass wrong &&\n> \t\tset_netrc ... &&\n> \t\t...\n> \t'\n>\n>\n"},{"id":"533173","messageId":"xmqqwm1ui7od.fsf@gitster.g","threadId":"64734","inReplyTo":"20260106114029.763351-1-git@ashlesh.me","subject":"Re: [PATCH v2] t5550: add netrc tests for http 401/403","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-01-07T00:32:34Z","receivedAt":"2026-01-07T00:32:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ashlesh Gawande <git@ashlesh.me> writes:\n\nHere between the title and your sign-off is a space to explain why\nit makes sense to add these new tests.  One way to do so may be to\nexplain that some cases were missing in the existing tests, and the\nnew ones are added to cover those cases, i.e., what the new tests\ntry to see under what situation, what behaviour do we expect out of\nthe system, and why do we expect that behaviour?\n\nThanks.\n\n> Signed-off-by: Ashlesh Gawande <git@ashlesh.me>\n> ---\n> Range-diff against v1:\n> 1:  27e112ea42 ! 1:  0b68f1d1af t5550: add netrc tests for http 401/403\n>     @@ Commit message\n>          Signed-off-by: Ashlesh Gawande <git@ashlesh.me>\n>      \n>       ## t/lib-httpd.sh ##\n>     -@@ t/lib-httpd.sh: set_askpass() {\n>     +@@ t/lib-httpd.sh: setup_askpass_helper() {\n>     + \t'\n>     + }\n>     + \n>     +-set_askpass() {\n>     ++set_askpass () {\n>     + \t>\"$TRASH_DIRECTORY/askpass-query\" &&\n>     + \techo \"$1\" >\"$TRASH_DIRECTORY/askpass-user\" &&\n>       \techo \"$2\" >\"$TRASH_DIRECTORY/askpass-pass\"\n>       }\n>       \n>     -+set_netrc() {\n>     +-expect_askpass() {\n>     ++set_netrc () {\n>      +\t# $HOME=$TRASH_DIRECTORY\n>     -+\techo \"machine $1 login $2 password $3\" > $TRASH_DIRECTORY/.netrc\n>     ++\techo \"machine $1 login $2 password $3\" >\"$TRASH_DIRECTORY/.netrc\"\n>      +}\n>      +\n>     -+clear_netrc() {\n>     -+\trm \"$TRASH_DIRECTORY/.netrc\"\n>     ++clear_netrc () {\n>     ++\trm -f \"$TRASH_DIRECTORY/.netrc\"\n>      +}\n>      +\n>     - expect_askpass() {\n>     ++expect_askpass () {\n>       \tdest=$HTTPD_DEST${3+/$3}\n>       \n>     + \t{\n>      \n>       ## t/lib-httpd/apache.conf ##\n>      @@ t/lib-httpd/apache.conf: SSLEngine On\n>     @@ t/t5550-http-fetch-dumb.sh: test_expect_success 'cloning password-protected repo\n>       '\n>       \n>      +test_expect_success 'using credentials from netrc to clone successfully' '\n>     ++\ttest_when_finished clear_netrc &&\n>      +\tset_askpass wrong &&\n>      +\tset_netrc 127.0.0.1 user@host pass@host &&\n>      +\tgit clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc &&\n>      +\texpect_askpass none\n>      +'\n>     -+clear_netrc\n>      +\n>      +test_expect_success 'netrc unauthorized credentials (prompt after 401)' '\n>     ++\ttest_when_finished clear_netrc &&\n>      +\tset_askpass wrong &&\n>      +\tset_netrc 127.0.0.1 user@host pass@wrong &&\n>      +\ttest_must_fail git clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc-401 &&\n>      +\texpect_askpass both wrong\n>      +'\n>     -+clear_netrc\n>      +\n>      +test_expect_success 'netrc authorized but forbidden credentials (fail on 403)' '\n>     ++\ttest_when_finished clear_netrc &&\n>      +\tset_askpass wrong &&\n>      +\tset_netrc 127.0.0.1 forbidden-user@host pass@host &&\n>      +\ttest_must_fail git clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc-403 2>err &&\n>      +\texpect_askpass none &&\n>      +\tgrep \"The requested URL returned error: 403\" err\n>      +'\n>     -+clear_netrc\n>      +\n>       test_expect_success 'http auth can use user/pass in URL' '\n>       \tset_askpass wrong &&\n>\n>  t/lib-httpd.sh             | 13 +++++++++++--\n>  t/lib-httpd/apache.conf    |  4 ++++\n>  t/lib-httpd/passwd         |  1 +\n>  t/t5550-http-fetch-dumb.sh | 25 +++++++++++++++++++++++++\n>  4 files changed, 41 insertions(+), 2 deletions(-)\n>\n> diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh\n> index 5091db949b..5f42c311c2 100644\n> --- a/t/lib-httpd.sh\n> +++ b/t/lib-httpd.sh\n> @@ -319,13 +319,22 @@ setup_askpass_helper() {\n>  \t'\n>  }\n>  \n> -set_askpass() {\n> +set_askpass () {\n>  \t>\"$TRASH_DIRECTORY/askpass-query\" &&\n>  \techo \"$1\" >\"$TRASH_DIRECTORY/askpass-user\" &&\n>  \techo \"$2\" >\"$TRASH_DIRECTORY/askpass-pass\"\n>  }\n>  \n> -expect_askpass() {\n> +set_netrc () {\n> +\t# $HOME=$TRASH_DIRECTORY\n> +\techo \"machine $1 login $2 password $3\" >\"$TRASH_DIRECTORY/.netrc\"\n> +}\n> +\n> +clear_netrc () {\n> +\trm -f \"$TRASH_DIRECTORY/.netrc\"\n> +}\n> +\n> +expect_askpass () {\n>  \tdest=$HTTPD_DEST${3+/$3}\n>  \n>  \t{\n> diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf\n> index e631ab0eb5..6b8c50a51a 100644\n> --- a/t/lib-httpd/apache.conf\n> +++ b/t/lib-httpd/apache.conf\n> @@ -238,6 +238,10 @@ SSLEngine On\n>  \tAuthName \"git-auth\"\n>  \tAuthUserFile passwd\n>  \tRequire valid-user\n> +\n> +\t# return 403 for authenticated user: forbidden-user@host\n> +\tRewriteCond \"%{REMOTE_USER}\" \"^forbidden-user@host\"\n> +\tRewriteRule ^ - [F]\n>  </Location>\n>  \n>  <LocationMatch \"^/auth-push/.*/git-receive-pack$\">\n> diff --git a/t/lib-httpd/passwd b/t/lib-httpd/passwd\n> index d9c122f348..3bab7b6423 100644\n> --- a/t/lib-httpd/passwd\n> +++ b/t/lib-httpd/passwd\n> @@ -1 +1,2 @@\n>  user@host:$apr1$LGPmCZWj$9vxEwj5Z5GzQLBMxp3mCx1\n> +forbidden-user@host:$apr1$LGPmCZWj$9vxEwj5Z5GzQLBMxp3mCx1\n> diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh\n> index ed0ad66fad..9530f01b9e 100755\n> --- a/t/t5550-http-fetch-dumb.sh\n> +++ b/t/t5550-http-fetch-dumb.sh\n> @@ -102,6 +102,31 @@ test_expect_success 'cloning password-protected repository can fail' '\n>  \texpect_askpass both wrong\n>  '\n>  \n> +test_expect_success 'using credentials from netrc to clone successfully' '\n> +\ttest_when_finished clear_netrc &&\n> +\tset_askpass wrong &&\n> +\tset_netrc 127.0.0.1 user@host pass@host &&\n> +\tgit clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc &&\n> +\texpect_askpass none\n> +'\n> +\n> +test_expect_success 'netrc unauthorized credentials (prompt after 401)' '\n> +\ttest_when_finished clear_netrc &&\n> +\tset_askpass wrong &&\n> +\tset_netrc 127.0.0.1 user@host pass@wrong &&\n> +\ttest_must_fail git clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc-401 &&\n> +\texpect_askpass both wrong\n> +'\n> +\n> +test_expect_success 'netrc authorized but forbidden credentials (fail on 403)' '\n> +\ttest_when_finished clear_netrc &&\n> +\tset_askpass wrong &&\n> +\tset_netrc 127.0.0.1 forbidden-user@host pass@host &&\n> +\ttest_must_fail git clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc-403 2>err &&\n> +\texpect_askpass none &&\n> +\tgrep \"The requested URL returned error: 403\" err\n> +'\n> +\n>  test_expect_success 'http auth can use user/pass in URL' '\n>  \tset_askpass wrong &&\n>  \tgit clone \"$HTTPD_URL_USER_PASS/auth/dumb/repo.git\" clone-auth-none &&\n"},{"id":"533185","messageId":"20260107074724.13165-1-git@ashlesh.me","threadId":"64734","inReplyTo":"20260106114029.763351-1-git@ashlesh.me","subject":"[PATCH v3] t5550: add netrc tests for http 401/403","fromName":"Ashlesh Gawande","fromEmail":"git@ashlesh.me","sentAt":"2026-01-07T07:47:24Z","receivedAt":"2026-01-07T07:53:23Z","isPatch":true,"sender":{"key":"git@ashlesh.me","avatar":"https://avatars.githubusercontent.com/u/8251376?v=4"},"body":"git allows using .netrc file to supply credentials for HTTP auth.\nThree test cases are added in this patch to provide missing coverage\nwhen cloning over HTTP using .netrc file:\n\n  - First test case checks that the git clone is successful when credentials\n    are provided via .netrc file\n  - Second test case checks that the git clone fails when the .netrc file\n    provides invalid credentials. The HTTP server is expected to return\n    401 Unauthorized in such a case. The test checks that the user is\n    provided with a prompt for username/password on 401 to provide\n    the valid ones.\n  - Third test case checks that the git clone fails when the .netrc file\n    provides credentials that are valid but do not have permission for\n    this user. For example one may have multiple tokens in GitHub\n    and uses the one which was not authorized for cloning this repo.\n    In such a case the HTTP server returns 403 Forbidden.\n    For this test, the apache.conf is modified to return a 403\n    on finding a forbidden-user. No prompt for username/password is\n    expected after the 403 (unlike 401). This is because prompting may wipe\n    out existing credentials or conflict with custom credential helpers.\n\nSigned-off-by: Ashlesh Gawande <git@ashlesh.me>\n---\nRange-diff against v2:\n1:  0b68f1d1af ! 1:  25ef751f28 t5550: add netrc tests for http 401/403\n    @@ Metadata\n      ## Commit message ##\n         t5550: add netrc tests for http 401/403\n     \n    +    git allows using .netrc file to supply credentials for HTTP auth.\n    +    Three test cases are added in this patch to provide missing coverage\n    +    when cloning over HTTP using .netrc file:\n    +\n    +      - First test case checks that the git clone is successful when credentials\n    +        are provided via .netrc file\n    +      - Second test case checks that the git clone fails when the .netrc file\n    +        provides invalid credentials. The HTTP server is expected to return\n    +        401 Unauthorized in such a case. The test checks that the user is\n    +        provided with a prompt for username/password on 401 to provide\n    +        the valid ones.\n    +      - Third test case checks that the git clone fails when the .netrc file\n    +        provides credentials that are valid but do not have permission for\n    +        this user. For example one may have multiple tokens in GitHub\n    +        and uses the one which was not authorized for cloning this repo.\n    +        In such a case the HTTP server returns 403 Forbidden.\n    +        For this test, the apache.conf is modified to return a 403\n    +        on finding a forbidden-user. No prompt for username/password is\n    +        expected after the 403 (unlike 401). This is because prompting may wipe\n    +        out existing credentials or conflict with custom credential helpers.\n    +\n         Signed-off-by: Ashlesh Gawande <git@ashlesh.me>\n     \n      ## t/lib-httpd.sh ##\n\n t/lib-httpd.sh             | 13 +++++++++++--\n t/lib-httpd/apache.conf    |  4 ++++\n t/lib-httpd/passwd         |  1 +\n t/t5550-http-fetch-dumb.sh | 25 +++++++++++++++++++++++++\n 4 files changed, 41 insertions(+), 2 deletions(-)\n\ndiff --git a/t/lib-httpd.sh b/t/lib-httpd.sh\nindex 5091db949b..5f42c311c2 100644\n--- a/t/lib-httpd.sh\n+++ b/t/lib-httpd.sh\n@@ -319,13 +319,22 @@ setup_askpass_helper() {\n \t'\n }\n \n-set_askpass() {\n+set_askpass () {\n \t>\"$TRASH_DIRECTORY/askpass-query\" &&\n \techo \"$1\" >\"$TRASH_DIRECTORY/askpass-user\" &&\n \techo \"$2\" >\"$TRASH_DIRECTORY/askpass-pass\"\n }\n \n-expect_askpass() {\n+set_netrc () {\n+\t# $HOME=$TRASH_DIRECTORY\n+\techo \"machine $1 login $2 password $3\" >\"$TRASH_DIRECTORY/.netrc\"\n+}\n+\n+clear_netrc () {\n+\trm -f \"$TRASH_DIRECTORY/.netrc\"\n+}\n+\n+expect_askpass () {\n \tdest=$HTTPD_DEST${3+/$3}\n \n \t{\ndiff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf\nindex e631ab0eb5..6b8c50a51a 100644\n--- a/t/lib-httpd/apache.conf\n+++ b/t/lib-httpd/apache.conf\n@@ -238,6 +238,10 @@ SSLEngine On\n \tAuthName \"git-auth\"\n \tAuthUserFile passwd\n \tRequire valid-user\n+\n+\t# return 403 for authenticated user: forbidden-user@host\n+\tRewriteCond \"%{REMOTE_USER}\" \"^forbidden-user@host\"\n+\tRewriteRule ^ - [F]\n </Location>\n \n <LocationMatch \"^/auth-push/.*/git-receive-pack$\">\ndiff --git a/t/lib-httpd/passwd b/t/lib-httpd/passwd\nindex d9c122f348..3bab7b6423 100644\n--- a/t/lib-httpd/passwd\n+++ b/t/lib-httpd/passwd\n@@ -1 +1,2 @@\n user@host:$apr1$LGPmCZWj$9vxEwj5Z5GzQLBMxp3mCx1\n+forbidden-user@host:$apr1$LGPmCZWj$9vxEwj5Z5GzQLBMxp3mCx1\ndiff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh\nindex ed0ad66fad..9530f01b9e 100755\n--- a/t/t5550-http-fetch-dumb.sh\n+++ b/t/t5550-http-fetch-dumb.sh\n@@ -102,6 +102,31 @@ test_expect_success 'cloning password-protected repository can fail' '\n \texpect_askpass both wrong\n '\n \n+test_expect_success 'using credentials from netrc to clone successfully' '\n+\ttest_when_finished clear_netrc &&\n+\tset_askpass wrong &&\n+\tset_netrc 127.0.0.1 user@host pass@host &&\n+\tgit clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc &&\n+\texpect_askpass none\n+'\n+\n+test_expect_success 'netrc unauthorized credentials (prompt after 401)' '\n+\ttest_when_finished clear_netrc &&\n+\tset_askpass wrong &&\n+\tset_netrc 127.0.0.1 user@host pass@wrong &&\n+\ttest_must_fail git clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc-401 &&\n+\texpect_askpass both wrong\n+'\n+\n+test_expect_success 'netrc authorized but forbidden credentials (fail on 403)' '\n+\ttest_when_finished clear_netrc &&\n+\tset_askpass wrong &&\n+\tset_netrc 127.0.0.1 forbidden-user@host pass@host &&\n+\ttest_must_fail git clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc-403 2>err &&\n+\texpect_askpass none &&\n+\tgrep \"The requested URL returned error: 403\" err\n+'\n+\n test_expect_success 'http auth can use user/pass in URL' '\n \tset_askpass wrong &&\n \tgit clone \"$HTTPD_URL_USER_PASS/auth/dumb/repo.git\" clone-auth-none &&\n-- \n2.43.0\n\n"},{"id":"534913","messageId":"49baf22b-ce7c-464c-8f6b-65ca7ed1e9f2@ashlesh.me","threadId":"64734","inReplyTo":"20260107074724.13165-1-git@ashlesh.me","subject":"Re: [PATCH v3] t5550: add netrc tests for http 401/403","fromName":"Ashlesh Gawande","fromEmail":"git@ashlesh.me","sentAt":"2026-01-31T12:33:30Z","receivedAt":"2026-01-31T12:39:08Z","isPatch":true,"sender":{"key":"git@ashlesh.me","avatar":"https://avatars.githubusercontent.com/u/8251376?v=4"},"body":"Any other comments or suggestions on this patch that I can address?\n(re-sending because the mailing list rejected my previous email for not \nbeing plain text).\n\nThanks\nAshlesh\n\nOn 1/7/26 13:17, Ashlesh Gawande wrote:\n> git allows using .netrc file to supply credentials for HTTP auth.\n> Three test cases are added in this patch to provide missing coverage\n> when cloning over HTTP using .netrc file:\n>\n>    - First test case checks that the git clone is successful when credentials\n>      are provided via .netrc file\n>    - Second test case checks that the git clone fails when the .netrc file\n>      provides invalid credentials. The HTTP server is expected to return\n>      401 Unauthorized in such a case. The test checks that the user is\n>      provided with a prompt for username/password on 401 to provide\n>      the valid ones.\n>    - Third test case checks that the git clone fails when the .netrc file\n>      provides credentials that are valid but do not have permission for\n>      this user. For example one may have multiple tokens in GitHub\n>      and uses the one which was not authorized for cloning this repo.\n>      In such a case the HTTP server returns 403 Forbidden.\n>      For this test, the apache.conf is modified to return a 403\n>      on finding a forbidden-user. No prompt for username/password is\n>      expected after the 403 (unlike 401). This is because prompting may wipe\n>      out existing credentials or conflict with custom credential helpers.\n>\n> Signed-off-by: Ashlesh Gawande <git@ashlesh.me>\n> ---\n> Range-diff against v2:\n> 1:  0b68f1d1af ! 1:  25ef751f28 t5550: add netrc tests for http 401/403\n>      @@ Metadata\n>        ## Commit message ##\n>           t5550: add netrc tests for http 401/403\n>       \n>      +    git allows using .netrc file to supply credentials for HTTP auth.\n>      +    Three test cases are added in this patch to provide missing coverage\n>      +    when cloning over HTTP using .netrc file:\n>      +\n>      +      - First test case checks that the git clone is successful when credentials\n>      +        are provided via .netrc file\n>      +      - Second test case checks that the git clone fails when the .netrc file\n>      +        provides invalid credentials. The HTTP server is expected to return\n>      +        401 Unauthorized in such a case. The test checks that the user is\n>      +        provided with a prompt for username/password on 401 to provide\n>      +        the valid ones.\n>      +      - Third test case checks that the git clone fails when the .netrc file\n>      +        provides credentials that are valid but do not have permission for\n>      +        this user. For example one may have multiple tokens in GitHub\n>      +        and uses the one which was not authorized for cloning this repo.\n>      +        In such a case the HTTP server returns 403 Forbidden.\n>      +        For this test, the apache.conf is modified to return a 403\n>      +        on finding a forbidden-user. No prompt for username/password is\n>      +        expected after the 403 (unlike 401). This is because prompting may wipe\n>      +        out existing credentials or conflict with custom credential helpers.\n>      +\n>           Signed-off-by: Ashlesh Gawande <git@ashlesh.me>\n>       \n>        ## t/lib-httpd.sh ##\n>\n>   t/lib-httpd.sh             | 13 +++++++++++--\n>   t/lib-httpd/apache.conf    |  4 ++++\n>   t/lib-httpd/passwd         |  1 +\n>   t/t5550-http-fetch-dumb.sh | 25 +++++++++++++++++++++++++\n>   4 files changed, 41 insertions(+), 2 deletions(-)\n>\n> diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh\n> index 5091db949b..5f42c311c2 100644\n> --- a/t/lib-httpd.sh\n> +++ b/t/lib-httpd.sh\n> @@ -319,13 +319,22 @@ setup_askpass_helper() {\n>   \t'\n>   }\n>   \n> -set_askpass() {\n> +set_askpass () {\n>   \t>\"$TRASH_DIRECTORY/askpass-query\" &&\n>   \techo \"$1\" >\"$TRASH_DIRECTORY/askpass-user\" &&\n>   \techo \"$2\" >\"$TRASH_DIRECTORY/askpass-pass\"\n>   }\n>   \n> -expect_askpass() {\n> +set_netrc () {\n> +\t# $HOME=$TRASH_DIRECTORY\n> +\techo \"machine $1 login $2 password $3\" >\"$TRASH_DIRECTORY/.netrc\"\n> +}\n> +\n> +clear_netrc () {\n> +\trm -f \"$TRASH_DIRECTORY/.netrc\"\n> +}\n> +\n> +expect_askpass () {\n>   \tdest=$HTTPD_DEST${3+/$3}\n>   \n>   \t{\n> diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf\n> index e631ab0eb5..6b8c50a51a 100644\n> --- a/t/lib-httpd/apache.conf\n> +++ b/t/lib-httpd/apache.conf\n> @@ -238,6 +238,10 @@ SSLEngine On\n>   \tAuthName \"git-auth\"\n>   \tAuthUserFile passwd\n>   \tRequire valid-user\n> +\n> +\t# return 403 for authenticated user: forbidden-user@host\n> +\tRewriteCond \"%{REMOTE_USER}\" \"^forbidden-user@host\"\n> +\tRewriteRule ^ - [F]\n>   </Location>\n>   \n>   <LocationMatch \"^/auth-push/.*/git-receive-pack$\">\n> diff --git a/t/lib-httpd/passwd b/t/lib-httpd/passwd\n> index d9c122f348..3bab7b6423 100644\n> --- a/t/lib-httpd/passwd\n> +++ b/t/lib-httpd/passwd\n> @@ -1 +1,2 @@\n>   user@host:$apr1$LGPmCZWj$9vxEwj5Z5GzQLBMxp3mCx1\n> +forbidden-user@host:$apr1$LGPmCZWj$9vxEwj5Z5GzQLBMxp3mCx1\n> diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh\n> index ed0ad66fad..9530f01b9e 100755\n> --- a/t/t5550-http-fetch-dumb.sh\n> +++ b/t/t5550-http-fetch-dumb.sh\n> @@ -102,6 +102,31 @@ test_expect_success 'cloning password-protected repository can fail' '\n>   \texpect_askpass both wrong\n>   '\n>   \n> +test_expect_success 'using credentials from netrc to clone successfully' '\n> +\ttest_when_finished clear_netrc &&\n> +\tset_askpass wrong &&\n> +\tset_netrc 127.0.0.1 user@host pass@host &&\n> +\tgit clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc &&\n> +\texpect_askpass none\n> +'\n> +\n> +test_expect_success 'netrc unauthorized credentials (prompt after 401)' '\n> +\ttest_when_finished clear_netrc &&\n> +\tset_askpass wrong &&\n> +\tset_netrc 127.0.0.1 user@host pass@wrong &&\n> +\ttest_must_fail git clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc-401 &&\n> +\texpect_askpass both wrong\n> +'\n> +\n> +test_expect_success 'netrc authorized but forbidden credentials (fail on 403)' '\n> +\ttest_when_finished clear_netrc &&\n> +\tset_askpass wrong &&\n> +\tset_netrc 127.0.0.1 forbidden-user@host pass@host &&\n> +\ttest_must_fail git clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc-403 2>err &&\n> +\texpect_askpass none &&\n> +\tgrep \"The requested URL returned error: 403\" err\n> +'\n> +\n>   test_expect_success 'http auth can use user/pass in URL' '\n>   \tset_askpass wrong &&\n>   \tgit clone \"$HTTPD_URL_USER_PASS/auth/dumb/repo.git\" clone-auth-none &&\n"},{"id":"535308","messageId":"xmqqms1mihqo.fsf@gitster.g","threadId":"64734","inReplyTo":"20260107074724.13165-1-git@ashlesh.me","subject":"Re: [PATCH v3] t5550: add netrc tests for http 401/403","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-02-06T05:05:51Z","receivedAt":"2026-02-06T05:05:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ashlesh Gawande <git@ashlesh.me> writes:\n\n> git allows using .netrc file to supply credentials for HTTP auth.\n> Three test cases are added in this patch to provide missing coverage\n> when cloning over HTTP using .netrc file:\n>\n>   - First test case checks that the git clone is successful when credentials\n>     are provided via .netrc file\n>   - Second test case checks that the git clone fails when the .netrc file\n>     provides invalid credentials. The HTTP server is expected to return\n>     401 Unauthorized in such a case. The test checks that the user is\n>     provided with a prompt for username/password on 401 to provide\n>     the valid ones.\n>   - Third test case checks that the git clone fails when the .netrc file\n>     provides credentials that are valid but do not have permission for\n>     this user. For example one may have multiple tokens in GitHub\n>     and uses the one which was not authorized for cloning this repo.\n>     In such a case the HTTP server returns 403 Forbidden.\n>     For this test, the apache.conf is modified to return a 403\n>     on finding a forbidden-user. No prompt for username/password is\n>     expected after the 403 (unlike 401). This is because prompting may wipe\n>     out existing credentials or conflict with custom credential helpers.\n\nNicely summarised.  So we say 401 when we do not know you, while we\nsay 403 when we know you and do not want you to be accessing the\nresource.  We test for both.\n\nJust out of curiosity, do we test for these codes with other\ncredential helpers or is this only relevant for .netrc users?\n\n> +test_expect_success 'using credentials from netrc to clone successfully' '\n> +\ttest_when_finished clear_netrc &&\n> +\tset_askpass wrong &&\n> +\tset_netrc 127.0.0.1 user@host pass@host &&\n> +\tgit clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc &&\n> +\texpect_askpass none\n> +'\n> +\n> +test_expect_success 'netrc unauthorized credentials (prompt after 401)' '\n> +\ttest_when_finished clear_netrc &&\n> +\tset_askpass wrong &&\n> +\tset_netrc 127.0.0.1 user@host pass@wrong &&\n> +\ttest_must_fail git clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc-401 &&\n> +\texpect_askpass both wrong\n> +'\n> +\n> +test_expect_success 'netrc authorized but forbidden credentials (fail on 403)' '\n> +\ttest_when_finished clear_netrc &&\n> +\tset_askpass wrong &&\n> +\tset_netrc 127.0.0.1 forbidden-user@host pass@host &&\n> +\ttest_must_fail git clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc-403 2>err &&\n> +\texpect_askpass none &&\n> +\tgrep \"The requested URL returned error: 403\" err\n> +'\n> +\n>  test_expect_success 'http auth can use user/pass in URL' '\n>  \tset_askpass wrong &&\n>  \tgit clone \"$HTTPD_URL_USER_PASS/auth/dumb/repo.git\" clone-auth-none &&\n"},{"id":"535328","messageId":"20260206093840.GC2761602@coredump.intra.peff.net","threadId":"64734","inReplyTo":"xmqqms1mihqo.fsf@gitster.g","subject":"Re: [PATCH v3] t5550: add netrc tests for http 401/403","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2026-02-06T09:38:40Z","receivedAt":"2026-02-06T09:38:41Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Feb 05, 2026 at 09:05:51PM -0800, Junio C Hamano wrote:\n\n> >   - Third test case checks that the git clone fails when the .netrc file\n> >     provides credentials that are valid but do not have permission for\n> >     this user. For example one may have multiple tokens in GitHub\n> >     and uses the one which was not authorized for cloning this repo.\n> >     In such a case the HTTP server returns 403 Forbidden.\n> >     For this test, the apache.conf is modified to return a 403\n> >     on finding a forbidden-user. No prompt for username/password is\n> >     expected after the 403 (unlike 401). This is because prompting may wipe\n> >     out existing credentials or conflict with custom credential helpers.\n> \n> Nicely summarised.  So we say 401 when we do not know you, while we\n> say 403 when we know you and do not want you to be accessing the\n> resource.  We test for both.\n\nI think it is fine to check the 403 handling, but note that this _isn't_\nhow GitHub would respond. If you try to fetch from a repository you\ndon't have access to, it will return a 401 first (so you try to log in)\nand then a 404. The idea being to avoid revealing the existence of the\nrepository to unauthorized users.\n\n> Just out of curiosity, do we test for these codes with other\n> credential helpers or is this only relevant for .netrc users?\n\nThe netrc support here should not involve credential helpers at all. It\nis all being done internally by curl. So in this (third and final) test:\n\n> > +test_expect_success 'netrc authorized but forbidden credentials (fail on 403)' '\n> > +\ttest_when_finished clear_netrc &&\n> > +\tset_askpass wrong &&\n> > +\tset_netrc 127.0.0.1 forbidden-user@host pass@host &&\n> > +\ttest_must_fail git clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc-403 2>err &&\n> > +\texpect_askpass none &&\n> > +\tgrep \"The requested URL returned error: 403\" err\n> > +'\n\n...what is happening is roughly:\n\n  - curl sends the first request with no credentials, which gets a 401\n\n  - curl internally, without returning a response to Git, looks up the\n    netrc value and repeats the request with an Authorization header\n\n  - curl returns the resulting 403 to Git\n\n  - Git calls this an error (just like it would a 404) and bails\n\nBut from Git's perspective the use of netrc here is not really\ninteresting. We don't even know it happened! And if the server did\nreturn a 401, we'd happily try to get credentials (from the user or from\na helper) in the usual way. And that's what happens in the second test:\n\n> > +test_expect_success 'netrc unauthorized credentials (prompt after 401)' '\n> > +\ttest_when_finished clear_netrc &&\n> > +\tset_askpass wrong &&\n> > +\tset_netrc 127.0.0.1 user@host pass@wrong &&\n> > +\ttest_must_fail git clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc-401 &&\n> > +\texpect_askpass both wrong\n> > +'\n\nCurl tries the credential under the hood, but we have no idea, and we\nprocess a 401 in the usual way.\n\nAnd in the first one:\n\n> > +test_expect_success 'using credentials from netrc to clone successfully' '\n> > +\ttest_when_finished clear_netrc &&\n> > +\tset_askpass wrong &&\n> > +\tset_netrc 127.0.0.1 user@host pass@host &&\n> > +\tgit clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc &&\n> > +\texpect_askpass none\n> > +'\n\nWe do not ever even see the 401, and curl just magically handles it for\nus. We see only the successful 200 code, just as if authentication was\nnot required in the first place.\n\n\nSo really, none of this is testing anything novel in Git at all that is\nnot covered elsewhere, except for the fact that we pass the flag to curl\nthat says \"you may use netrc\". And so there's some value in adding it in\nthat case. But trying to answer your question about other credential\nhelpers, no, they're not even entering the picture here.\n\n-Peff\n"},{"id":"535349","messageId":"8ac465f8-6fda-43a1-8bfc-3e88f30d1ca5@ashlesh.me","threadId":"64734","inReplyTo":"20260206093840.GC2761602@coredump.intra.peff.net","subject":"Re: [PATCH v3] t5550: add netrc tests for http 401/403","fromName":"Ashlesh Gawande","fromEmail":"git@ashlesh.me","sentAt":"2026-02-06T15:25:26Z","receivedAt":"2026-02-06T15:30:56Z","isPatch":true,"sender":{"key":"git@ashlesh.me","avatar":"https://avatars.githubusercontent.com/u/8251376?v=4"},"body":"\nOn 2/6/26 15:08, Jeff King wrote:\n> On Thu, Feb 05, 2026 at 09:05:51PM -0800, Junio C Hamano wrote:\n>\n>>>    - Third test case checks that the git clone fails when the .netrc file\n>>>      provides credentials that are valid but do not have permission for\n>>>      this user. For example one may have multiple tokens in GitHub\n>>>      and uses the one which was not authorized for cloning this repo.\n>>>      In such a case the HTTP server returns 403 Forbidden.\n>>>      For this test, the apache.conf is modified to return a 403\n>>>      on finding a forbidden-user. No prompt for username/password is\n>>>      expected after the 403 (unlike 401). This is because prompting may wipe\n>>>      out existing credentials or conflict with custom credential helpers.\n>> Nicely summarised.  So we say 401 when we do not know you, while we\n>> say 403 when we know you and do not want you to be accessing the\n>> resource.  We test for both.\n> I think it is fine to check the 403 handling, but note that this _isn't_\n> how GitHub would respond. If you try to fetch from a repository you\n> don't have access to, it will return a 401 first (so you try to log in)\n> and then a 404. The idea being to avoid revealing the existence of the\n> repository to unauthorized users.\nIn the case of fine-grained access token such that the token has read \naccess to the repository\nbut not write access GitHub does return a 403.\n(I think this is correct behavior as the token has read access so user \nis authorized/knows about the repository).\n>> Just out of curiosity, do we test for these codes with other\n>> credential helpers or is this only relevant for .netrc users?\n> The netrc support here should not involve credential helpers at all. It\n> is all being done internally by curl. So in this (third and final) test:\n>\n>>> +test_expect_success 'netrc authorized but forbidden credentials (fail on 403)' '\n>>> +\ttest_when_finished clear_netrc &&\n>>> +\tset_askpass wrong &&\n>>> +\tset_netrc 127.0.0.1 forbidden-user@host pass@host &&\n>>> +\ttest_must_fail git clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc-403 2>err &&\n>>> +\texpect_askpass none &&\n>>> +\tgrep \"The requested URL returned error: 403\" err\n>>> +'\n> ...what is happening is roughly:\n>\n>    - curl sends the first request with no credentials, which gets a 401\n>\n>    - curl internally, without returning a response to Git, looks up the\n>      netrc value and repeats the request with an Authorization header\n>\n>    - curl returns the resulting 403 to Git\n>\n>    - Git calls this an error (just like it would a 404) and bails\n>\n> But from Git's perspective the use of netrc here is not really\n> interesting. We don't even know it happened! And if the server did\n> return a 401, we'd happily try to get credentials (from the user or from\n> a helper) in the usual way. And that's what happens in the second test:\n>\n>>> +test_expect_success 'netrc unauthorized credentials (prompt after 401)' '\n>>> +\ttest_when_finished clear_netrc &&\n>>> +\tset_askpass wrong &&\n>>> +\tset_netrc 127.0.0.1 user@host pass@wrong &&\n>>> +\ttest_must_fail git clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc-401 &&\n>>> +\texpect_askpass both wrong\n>>> +'\n> Curl tries the credential under the hood, but we have no idea, and we\n> process a 401 in the usual way.\n>\n> And in the first one:\n>\n>>> +test_expect_success 'using credentials from netrc to clone successfully' '\n>>> +\ttest_when_finished clear_netrc &&\n>>> +\tset_askpass wrong &&\n>>> +\tset_netrc 127.0.0.1 user@host pass@host &&\n>>> +\tgit clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc &&\n>>> +\texpect_askpass none\n>>> +'\n> We do not ever even see the 401, and curl just magically handles it for\n> us. We see only the successful 200 code, just as if authentication was\n> not required in the first place.\n>\n>\n> So really, none of this is testing anything novel in Git at all that is\n> not covered elsewhere, except for the fact that we pass the flag to curl\n> that says \"you may use netrc\". And so there's some value in adding it in\n> that case. But trying to answer your question about other credential\n> helpers, no, they're not even entering the picture here.\n>\n> -Peff\n>\n"},{"id":"535358","messageId":"7583bd2c-4f2f-4a43-a36f-7e0698da8a57@ashlesh.me","threadId":"64734","inReplyTo":"8ac465f8-6fda-43a1-8bfc-3e88f30d1ca5@ashlesh.me","subject":"Re: [PATCH v3] t5550: add netrc tests for http 401/403","fromName":"Ashlesh Gawande","fromEmail":"git@ashlesh.me","sentAt":"2026-02-06T15:53:18Z","receivedAt":"2026-02-06T15:58:54Z","isPatch":true,"sender":{"key":"git@ashlesh.me","avatar":"https://avatars.githubusercontent.com/u/8251376?v=4"},"body":"\nOn 2/6/26 20:55, Ashlesh Gawande wrote:\n>\n> On 2/6/26 15:08, Jeff King wrote:\n>> On Thu, Feb 05, 2026 at 09:05:51PM -0800, Junio C Hamano wrote:\n>>\n>>>>    - Third test case checks that the git clone fails when the \n>>>> .netrc file\n>>>>      provides credentials that are valid but do not have permission \n>>>> for\n>>>>      this user. For example one may have multiple tokens in GitHub\n>>>>      and uses the one which was not authorized for cloning this repo.\n>>>>      In such a case the HTTP server returns 403 Forbidden.\n>>>>      For this test, the apache.conf is modified to return a 403\n>>>>      on finding a forbidden-user. No prompt for username/password is\n>>>>      expected after the 403 (unlike 401). This is because prompting \n>>>> may wipe\n>>>>      out existing credentials or conflict with custom credential \n>>>> helpers.\n>>> Nicely summarised.  So we say 401 when we do not know you, while we\n>>> say 403 when we know you and do not want you to be accessing the\n>>> resource.  We test for both.\n>> I think it is fine to check the 403 handling, but note that this _isn't_\n>> how GitHub would respond. If you try to fetch from a repository you\n>> don't have access to, it will return a 401 first (so you try to log in)\n>> and then a 404. The idea being to avoid revealing the existence of the\n>> repository to unauthorized users.\n> In the case of fine-grained access token such that the token has read \n> access to the repository\n> but not write access GitHub does return a 403.\n> (I think this is correct behavior as the token has read access so user \n> is authorized/knows about the repository).\nSo should I modify that test case to do a push instead for this specific \nscenario (and update the description)?\n>>> Just out of curiosity, do we test for these codes with other\n>>> credential helpers or is this only relevant for .netrc users?\n>> The netrc support here should not involve credential helpers at all. It\n>> is all being done internally by curl. So in this (third and final) test:\n>>\n>>>> +test_expect_success 'netrc authorized but forbidden credentials \n>>>> (fail on 403)' '\n>>>> +    test_when_finished clear_netrc &&\n>>>> +    set_askpass wrong &&\n>>>> +    set_netrc 127.0.0.1 forbidden-user@host pass@host &&\n>>>> +    test_must_fail git clone \"$HTTPD_URL/auth/dumb/repo.git\" \n>>>> clone-auth-netrc-403 2>err &&\n>>>> +    expect_askpass none &&\n>>>> +    grep \"The requested URL returned error: 403\" err\n>>>> +'\n>> ...what is happening is roughly:\n>>\n>>    - curl sends the first request with no credentials, which gets a 401\n>>\n>>    - curl internally, without returning a response to Git, looks up the\n>>      netrc value and repeats the request with an Authorization header\n>>\n>>    - curl returns the resulting 403 to Git\n>>\n>>    - Git calls this an error (just like it would a 404) and bails\n>>\n>> But from Git's perspective the use of netrc here is not really\n>> interesting. We don't even know it happened! And if the server did\n>> return a 401, we'd happily try to get credentials (from the user or from\n>> a helper) in the usual way. And that's what happens in the second test:\n>>\n>>>> +test_expect_success 'netrc unauthorized credentials (prompt after \n>>>> 401)' '\n>>>> +    test_when_finished clear_netrc &&\n>>>> +    set_askpass wrong &&\n>>>> +    set_netrc 127.0.0.1 user@host pass@wrong &&\n>>>> +    test_must_fail git clone \"$HTTPD_URL/auth/dumb/repo.git\" \n>>>> clone-auth-netrc-401 &&\n>>>> +    expect_askpass both wrong\n>>>> +'\n>> Curl tries the credential under the hood, but we have no idea, and we\n>> process a 401 in the usual way.\n>>\n>> And in the first one:\n>>\n>>>> +test_expect_success 'using credentials from netrc to clone \n>>>> successfully' '\n>>>> +    test_when_finished clear_netrc &&\n>>>> +    set_askpass wrong &&\n>>>> +    set_netrc 127.0.0.1 user@host pass@host &&\n>>>> +    git clone \"$HTTPD_URL/auth/dumb/repo.git\" clone-auth-netrc &&\n>>>> +    expect_askpass none\n>>>> +'\n>> We do not ever even see the 401, and curl just magically handles it for\n>> us. We see only the successful 200 code, just as if authentication was\n>> not required in the first place.\n>>\n>>\n>> So really, none of this is testing anything novel in Git at all that is\n>> not covered elsewhere, except for the fact that we pass the flag to curl\n>> that says \"you may use netrc\". And so there's some value in adding it in\n>> that case. But trying to answer your question about other credential\n>> helpers, no, they're not even entering the picture here.\n>>\n>> -Peff\n>>\n>\n"},{"id":"535372","messageId":"xmqqtsvtg49h.fsf@gitster.g","threadId":"64734","inReplyTo":"20260206093840.GC2761602@coredump.intra.peff.net","subject":"Re: [PATCH v3] t5550: add netrc tests for http 401/403","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-02-06T17:39:54Z","receivedAt":"2026-02-06T17:39:56Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> I think it is fine to check the 403 handling, but note that this _isn't_\n> how GitHub would respond. If you try to fetch from a repository you\n> don't have access to, it will return a 401 first (so you try to log in)\n> and then a 404. The idea being to avoid revealing the existence of the\n> repository to unauthorized users.\n\nThat is a sensible thing to do on the server side.  Presumably when\nwe talk with such a server we would report 404, right?  It is not\nlike we behave all that differently with either type of errors---as\nlong as we just give up and do not fall into an infinite loop of\nasking \"oops, that password did not work, try again\", it would be\nOK.\n\n>> Just out of curiosity, do we test for these codes with other\n>> credential helpers or is this only relevant for .netrc users?\n>\n> The netrc support here should not involve credential helpers at all. It\n> is all being done internally by curl.\n\nYeah, I phrased my question in a wrong way.  As the code paths\ninvolving credential helpers are separate, I wondered if we have\nsimilar test coverage there as well.\n\n> So really, none of this is testing anything novel in Git at all that is\n> not covered elsewhere, except for the fact that we pass the flag to curl\n> that says \"you may use netrc\". And so there's some value in adding it in\n> that case. But trying to answer your question about other credential\n> helpers, no, they're not even entering the picture here.\n"},{"id":"535395","messageId":"20260206204428.GA2787536@coredump.intra.peff.net","threadId":"64734","inReplyTo":"7583bd2c-4f2f-4a43-a36f-7e0698da8a57@ashlesh.me","subject":"Re: [PATCH v3] t5550: add netrc tests for http 401/403","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2026-02-06T20:44:28Z","receivedAt":"2026-02-06T20:44:32Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Feb 06, 2026 at 09:23:18PM +0530, Ashlesh Gawande wrote:\n\n> > > I think it is fine to check the 403 handling, but note that this _isn't_\n> > > how GitHub would respond. If you try to fetch from a repository you\n> > > don't have access to, it will return a 401 first (so you try to log in)\n> > > and then a 404. The idea being to avoid revealing the existence of the\n> > > repository to unauthorized users.\n> > In the case of fine-grained access token such that the token has read\n> > access to the repository\n> > but not write access GitHub does return a 403.\n> > (I think this is correct behavior as the token has read access so user\n> > is authorized/knows about the repository).\n\nAh, that makes sense.\n\n> So should I modify that test case to do a push instead for this specific\n> scenario (and update the description)?\n\nNo, I think what you have is fine. From the client's perspective, they\nknow only that they got a 403 for some reason. So there's no need for\ncomplex modeling of what the server thinks is going on.\n\n-Peff\n"},{"id":"535396","messageId":"20260206205327.GB2787536@coredump.intra.peff.net","threadId":"64734","inReplyTo":"xmqqtsvtg49h.fsf@gitster.g","subject":"Re: [PATCH v3] t5550: add netrc tests for http 401/403","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2026-02-06T20:53:27Z","receivedAt":"2026-02-06T20:53:29Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Feb 06, 2026 at 09:39:54AM -0800, Junio C Hamano wrote:\n\n> Jeff King <peff@peff.net> writes:\n> \n> > I think it is fine to check the 403 handling, but note that this _isn't_\n> > how GitHub would respond. If you try to fetch from a repository you\n> > don't have access to, it will return a 401 first (so you try to log in)\n> > and then a 404. The idea being to avoid revealing the existence of the\n> > repository to unauthorized users.\n> \n> That is a sensible thing to do on the server side.  Presumably when\n> we talk with such a server we would report 404, right?  It is not\n> like we behave all that differently with either type of errors---as\n> long as we just give up and do not fall into an infinite loop of\n> asking \"oops, that password did not work, try again\", it would be\n> OK.\n\nRight, we'd report the 404. We never loop on trying to authenticate, but\ndo a maximum of two tries (and then only if we get a 401 on the first\nrequest and did not already provide a credential ourselves to curl).\nCurl might make multiple requests under the hood for each \"try\", but we\nwon't even know about them.\n\nAnd all of that is independent of which HTTP error code was returned\n(except for 401, obviously). We do eventually produce a different\nmessage for 404 vs a 403, but that's at the top-level of remote-curl.c.\n\nThe interesting bits are in http_request_reauth(), though some of the\nlogic is in handle_curl_result().\n\n> > The netrc support here should not involve credential helpers at all. It\n> > is all being done internally by curl.\n> \n> Yeah, I phrased my question in a wrong way.  As the code paths\n> involving credential helpers are separate, I wondered if we have\n> similar test coverage there as well.\n\nThe workings are hopefully covered by the explanation above. As far as\ntest coverage, I think t5550 covers this already. When we provide the\nwrong password, we bail rather than asking repeatedly (e.g., in \"cloning\npassword-protected repository can fail\").\n\n-Peff\n"}]}