block / block/buzz

git push fails because the NIP-98 credential is scoped to discovery GET and is not sent on git-receive-pack POST

Open
#2,880 4 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
32.7k
Forks
4.3k
Avg merge
1d 13h
Merged PRs (30d)
253

Description

**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**

1. Configure a valid Buzz repository remote and the `git-credential-nostr` credential helper.
2. Push a branch with `git push`.
3. Inspect the HTTP exchange:
1. Git probes `GET /git///info/refs?service=git-receive-pack`.
2. The relay responds with a Nostr authentication challenge scoped to GET.
3. `git-credential-nostr` generates a GET-scoped NIP-98 credential; Git retries discovery and receives HTTP 200.
4. Git sends `POST /git///git-receive-pack` without an Authorization header.
5. The relay responds with HTTP 401 and `WWW-Authenticate: Nostr realm="buzz", method="POST"`.
6. 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 " 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.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.