Describe the bug
Pushing to a Buzz-hosted Git repository fails with HTTP 401 even when repository ownership, relay authorization, and signing credentials are valid. Authentication succeeds for receive-pack discovery, but Git sends the subsequent streamed POST without an Authorization header. The relay challenges that POST, but Git cannot replay it after receiving the challenge.
Steps to reproduce
- Configure a valid Buzz repository remote and the
git-credential-nostr credential helper.
- Push a branch with
git push.
- Inspect the HTTP exchange:
- Git probes
GET /git/<owner>/<repo>/info/refs?service=git-receive-pack.
- The relay responds with a Nostr authentication challenge scoped to GET.
git-credential-nostr generates a GET-scoped NIP-98 credential; Git retries discovery and receives HTTP 200.
- Git sends
POST /git/<owner>/<repo>/git-receive-pack without an Authorization header.
- The relay responds with HTTP 401 and
WWW-Authenticate: Nostr realm="buzz", method="POST".
- The push aborts because Git cannot replay the streamed POST after the challenge.
Expected behavior
A valid push should authenticate the git-receive-pack POST preemptively with a fresh, POST-scoped NIP-98 credential and complete without a 401 challenge.
Version and platform
- Buzz version: unknown
- OS: macOS
- Git: 2.50.1
- Buzz Git relay using NIP-98 authentication
git-credential-nostr credential helper
Logs / additional context
Root-cause evidence:
-
A direct POST carrying a helper-generated, POST-scoped NIP-98 credential returns HTTP 200.
-
Injecting the same kind of credential preemptively makes the push succeed:
git -c http.extraHeader="Authorization: Nostr <POST_SCOPED_TOKEN>" push
-
The successful authenticated POST rules out repository ownership, auth-tag, relay provisioning, and repository-permission failures.
This indicates an authentication-handshake mismatch: discovery authenticates a GET, but that credential is neither valid for nor attached to the later POST. Challenging only after the streamed POST begins is too late for Git to recover.
Workaround:
Generate a fresh POST-scoped NIP-98 token and attach it preemptively using http.extraHeader for the push. Tokens should remain short-lived and must not be logged or persisted in repository configuration.
Recommended fix:
Before invoking git-receive-pack, have the Buzz Git integration attach a fresh NIP-98 Authorization header whose URL and method match the POST request. Alternatively, establish a short-lived authenticated session during discovery that is accepted by the subsequent POST.
Please also add an integration test covering the full smart-HTTP push sequence and asserting that the POST succeeds without relying on a replay after a 401 challenge.
Describe the bug
Pushing to a Buzz-hosted Git repository fails with HTTP 401 even when repository ownership, relay authorization, and signing credentials are valid. Authentication succeeds for receive-pack discovery, but Git sends the subsequent streamed POST without an Authorization header. The relay challenges that POST, but Git cannot replay it after receiving the challenge.
Steps to reproduce
git-credential-nostrcredential helper.git push.GET /git/<owner>/<repo>/info/refs?service=git-receive-pack.git-credential-nostrgenerates a GET-scoped NIP-98 credential; Git retries discovery and receives HTTP 200.POST /git/<owner>/<repo>/git-receive-packwithout an Authorization header.WWW-Authenticate: Nostr realm="buzz", method="POST".Expected behavior
A valid push should authenticate the
git-receive-packPOST preemptively with a fresh, POST-scoped NIP-98 credential and complete without a 401 challenge.Version and platform
git-credential-nostrcredential helperLogs / additional context
Root-cause evidence:
A direct POST carrying a helper-generated, POST-scoped NIP-98 credential returns HTTP 200.
Injecting the same kind of credential preemptively makes the push succeed:
git -c http.extraHeader="Authorization: Nostr <POST_SCOPED_TOKEN>" pushThe successful authenticated POST rules out repository ownership, auth-tag, relay provisioning, and repository-permission failures.
This indicates an authentication-handshake mismatch: discovery authenticates a GET, but that credential is neither valid for nor attached to the later POST. Challenging only after the streamed POST begins is too late for Git to recover.
Workaround:
Generate a fresh POST-scoped NIP-98 token and attach it preemptively using
http.extraHeaderfor the push. Tokens should remain short-lived and must not be logged or persisted in repository configuration.Recommended fix:
Before invoking
git-receive-pack, have the Buzz Git integration attach a fresh NIP-98 Authorization header whose URL and method match the POST request. Alternatively, establish a short-lived authenticated session during discovery that is accepted by the subsequent POST.Please also add an integration test covering the full smart-HTTP push sequence and asserting that the POST succeeds without relying on a replay after a 401 challenge.