+
Skip to content

No webhook secret #1127

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions github/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,9 @@ func messageMAC(signature string) ([]byte, func() hash.Hash, error) {
// and returns the (JSON) payload.
// The Content-Type header of the payload can be "application/json" or "application/x-www-form-urlencoded".
// If the Content-Type is neither then an error is returned.
// secretKey is the GitHub Webhook secret message.
// secretToken is the GitHub Webhook secret token.
// If your webhook does not contain a secret token, you can pass nil or an empty slice.
// This is intended for local development purposes only and all webhooks should ideally set up a secret token.
//
// Example usage:
//
Expand All @@ -139,7 +141,7 @@ func messageMAC(signature string) ([]byte, func() hash.Hash, error) {
// // Process payload...
// }
//
func ValidatePayload(r *http.Request, secretKey []byte) (payload []byte, err error) {
func ValidatePayload(r *http.Request, secretToken []byte) (payload []byte, err error) {
var body []byte // Raw body that GitHub uses to calculate the signature.

switch ct := r.Header.Get("Content-Type"); ct {
Expand Down Expand Up @@ -175,25 +177,30 @@ func ValidatePayload(r *http.Request, secretKey []byte) (payload []byte, err err
return nil, fmt.Errorf("Webhook request has unsupported Content-Type %q", ct)
}

sig := r.Header.Get(signatureHeader)
if err := ValidateSignature(sig, body, secretKey); err != nil {
return nil, err
// Only validate the signature if a secret token exists. This is intended for
// local development only and all webhooks should ideally set up a secret token.
if len(secretToken) > 0 {
sig := r.Header.Get(signatureHeader)
if err := ValidateSignature(sig, body, secretToken); err != nil {
return nil, err
}
}

return payload, nil
}

// ValidateSignature validates the signature for the given payload.
// signature is the GitHub hash signature delivered in the X-Hub-Signature header.
// payload is the JSON payload sent by GitHub Webhooks.
// secretKey is the GitHub Webhook secret message.
// secretToken is the GitHub Webhook secret token.
//
// GitHub API docs: https://developer.github.com/webhooks/securing/#validating-payloads-from-github
func ValidateSignature(signature string, payload, secretKey []byte) error {
func ValidateSignature(signature string, payload, secretToken []byte) error {
messageMAC, hashFunc, err := messageMAC(signature)
if err != nil {
return err
}
if !checkMAC(payload, messageMAC, secretKey, hashFunc) {
if !checkMAC(payload, messageMAC, secretToken, hashFunc) {
return errors.New("payload signature check failed")
}
return nil
Expand Down
25 changes: 23 additions & 2 deletions github/messages_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ func TestValidatePayload_FormGet(t *testing.T) {

// check that if payload is invalid we get error
req.Header.Set(signatureHeader, "invalid signature")
if _, err = ValidatePayload(req, nil); err == nil {
if _, err = ValidatePayload(req, []byte{0}); err == nil {
t.Error("ValidatePayload = nil, want err")
}
}
Expand Down Expand Up @@ -140,7 +140,7 @@ func TestValidatePayload_FormPost(t *testing.T) {

// check that if payload is invalid we get error
req.Header.Set(signatureHeader, "invalid signature")
if _, err = ValidatePayload(req, nil); err == nil {
if _, err = ValidatePayload(req, []byte{0}); err == nil {
t.Error("ValidatePayload = nil, want err")
}
}
Expand All @@ -156,6 +156,27 @@ func TestValidatePayload_InvalidContentType(t *testing.T) {
}
}

func TestValidatePayload_NoSecretKey(t *testing.T) {
payload := `{"yo":true}`

form := url.Values{}
form.Set("payload", payload)
buf := bytes.NewBufferString(form.Encode())
req, err := http.NewRequest("POST", "http://localhost/event", buf)
if err != nil {
t.Fatalf("NewRequest: %v", err)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

got, err := ValidatePayload(req, nil)
if err != nil {
t.Errorf("ValidatePayload(%#v): err = %v, want nil", payload, err)
}
if string(got) != payload {
t.Errorf("ValidatePayload = %q, want %q", got, payload)
}
}

func TestParseWebHook(t *testing.T) {
tests := []struct {
payload interface{}
Expand Down
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载