Skip to content

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

Description

@nandubatchu

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/<owner>/<repo>/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/<owner>/<repo>/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 <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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions