From 8e0f0bead3f6fbe8561f91d32d73095b94920971 Mon Sep 17 00:00:00 2001 From: prasanna8585 Date: Thu, 24 Sep 2026 11:38:14 +0530 Subject: [PATCH] fix(github): enforce persona/pubkey match and verify against server-computed payload Two coupled issues in the GitHub validator: 1. The public key recovered from the Gist's persona field (payload.Persona) was never asserted to match the avatar key supplied in the upload request (gh.Pubkey). 2. The final signature check used payload.SignPayload -- content taken directly from the attacker-controlled Gist -- instead of gh.SignaturePayload, the payload the server itself computes (line 88) and expects to have been signed. Fix: assert the recovered pubkey matches the request's declared pubkey via crypto.CompressedPubkeyHex, and verify the signature against the server-computed gh.SignaturePayload rather than the Gist-supplied value. --- validator/github/github.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/validator/github/github.go b/validator/github/github.go index c94dad0..f18137b 100644 --- a/validator/github/github.go +++ b/validator/github/github.go @@ -125,11 +125,18 @@ func (gh *Github) Validate() (err error) { if err != nil { return xerrors.Errorf("error when recovering pubkey: %w", err) } + if crypto.CompressedPubkeyHex(pubkey_recovered) != crypto.CompressedPubkeyHex(gh.Pubkey) { + return xerrors.Errorf( + "persona in gist (%s) does not match supplied public key (%s)", + crypto.CompressedPubkeyHex(pubkey_recovered), + crypto.CompressedPubkeyHex(gh.Pubkey), + ) + } signature, err := util.DecodeString(payload.Signature) if err != nil { return xerrors.Errorf("error when decoding signature: %w", err) } - return crypto.ValidatePersonalSignature(payload.SignPayload, signature, pubkey_recovered) + return crypto.ValidatePersonalSignature(gh.SignaturePayload, signature, pubkey_recovered) } func (gh *Github) GetAltID() string {