@@ -42,6 +42,10 @@ const (
4242 EventTypeHeader = "X-Github-Event"
4343 // DeliveryIDHeader is the GitHub header key used to pass the unique ID for the webhook event.
4444 DeliveryIDHeader = "X-Github-Delivery"
45+
46+ // maxPayloadSize is the maximum size of a GitHub webhook payload.
47+ // GitHub documents a 25 MB limit for webhook payloads.
48+ maxPayloadSize = 25 * 1024 * 1024
4549)
4650
4751var (
@@ -146,7 +150,19 @@ func checkMAC(message, messageMAC, key []byte, hashFunc func() hash.Hash) bool {
146150 return hmac .Equal (messageMAC , expectedMAC )
147151}
148152
149- // messageMAC returns the hex-decoded HMAC tag from the signature and its
153+ // readPayloadBody reads the body from readable, enforcing maxPayloadSize.
154+ func readPayloadBody (readable io.Reader ) ([]byte , error ) {
155+ body , err := io .ReadAll (io .LimitReader (readable , maxPayloadSize + 1 ))
156+ if err != nil {
157+ return nil , err
158+ }
159+ if len (body ) > maxPayloadSize {
160+ return nil , errors .New ("webhook payload exceeds maximum allowed size" )
161+ }
162+ return body , nil
163+ }
164+
165+
150166// corresponding hash function.
151167func messageMAC (signature string ) ([]byte , func () hash.Hash , error ) {
152168 if signature == "" {
@@ -199,7 +215,7 @@ func ValidatePayloadFromBody(contentType string, readable io.Reader, signature s
199215 switch contentType {
200216 case "application/json" :
201217 var err error
202- if body , err = io . ReadAll (readable ); err != nil {
218+ if body , err = readPayloadBody (readable ); err != nil {
203219 return nil , err
204220 }
205221
@@ -213,7 +229,7 @@ func ValidatePayloadFromBody(contentType string, readable io.Reader, signature s
213229 const payloadFormParam = "payload"
214230
215231 var err error
216- if body , err = io . ReadAll (readable ); err != nil {
232+ if body , err = readPayloadBody (readable ); err != nil {
217233 return nil , err
218234 }
219235
0 commit comments