From 3688205c574f3657ec184b2dfbeefe398d83ded4 Mon Sep 17 00:00:00 2001 From: Michael Dunton Date: Wed, 24 Aug 2016 17:09:15 -0400 Subject: [PATCH 1/2] Adding signature verification to hubot-github-webhook-listener --- src/hubot-github-webhook-listener.coffee | 36 ++++++++++++++++++++---- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/src/hubot-github-webhook-listener.coffee b/src/hubot-github-webhook-listener.coffee index 0e29962..f48e97b 100644 --- a/src/hubot-github-webhook-listener.coffee +++ b/src/hubot-github-webhook-listener.coffee @@ -31,6 +31,8 @@ # 5. Fire off a github event by interacting with your repo. Comment on an issue or a PR for example. # 6. Navigate to `http://127.0.0.1:4040/` # There you can see all webhooks posted to your local machine, and can replay them as many times as you wish. +# 7. If you set up a secret on your github webhook make sure HUBOT_GITHUB_WEBHOOK_TOKEN=yourverylongtoken if the +# token is not set we will not verify the x-hub-signature. # # Authors: # Taytay @@ -38,18 +40,41 @@ url = require('url') querystring = require('querystring') +crypto = require('crypto') debug = false +HUBOT_GITHUB_WEBHOOK_TOKEN = process.env.HUBOT_GITHUB_WEBHOOK_TOKEN + +getSignature = (payload) -> + hmac = crypto.createHmac 'sha1', HUBOT_GITHUB_WEBHOOK_TOKEN + hmac.update new Buffer JSON.stringify(payload) + return 'sha1=' + hmac.digest('hex') + +#from https://github.com/vdemedes/secure-compare +secureCompare = (a, b) -> + if typeof a != 'string' or typeof b != 'string' + return false + mismatch = if a.length == b.length then 0 else 1 + if mismatch + b = a + i = 0 + il = a.length + while i < il + mismatch |= a.charCodeAt(i) ^ b.charCodeAt(i) + ++i + return (mismatch is 0) + module.exports = (robot) -> - #TODO: Introduce secret so that these are verified: - # See: https://developer.github.com/webhooks/securing/ and - # https://gist.github.com/dcollien/c5d86c968cbc85e88286 robot.router.post "/hubot/github-repo-listener", (req, res) -> try if (debug) robot.logger.info("Github post received: ", req) + if HUBOT_GITHUB_WEBHOOK_TOKEN isnt undefined + signature = getSignature(req.body) + if not secureCompare(signature, req.headers['x-hub-signature']) + throw new Error('Signatures Do Not Match') eventBody = eventType : req.headers["x-github-event"] signature : req.headers["X-Hub-Signature"] @@ -58,7 +83,8 @@ module.exports = (robot) -> query : querystring.parse(url.parse(req.url).query) robot.emit "github-repo-event", eventBody - catch error - robot.logger.error "Github repo webhook listener error: #{error.stack}. Request: #{req.body}" + catch err + robot.logger.error "Github repo webhook listener error: #{err.message}. Request: #{req.body}" + robot.logger.error err.stack res.end "" From 8c46b06cf2b81f5b2eb05835a681f39f73368fdb Mon Sep 17 00:00:00 2001 From: Michael Dunton Date: Thu, 25 Aug 2016 09:29:56 -0400 Subject: [PATCH 2/2] Removing the secure compare since this code doesn't respond to the request anyways --- src/hubot-github-webhook-listener.coffee | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/src/hubot-github-webhook-listener.coffee b/src/hubot-github-webhook-listener.coffee index f48e97b..df0d2ff 100644 --- a/src/hubot-github-webhook-listener.coffee +++ b/src/hubot-github-webhook-listener.coffee @@ -51,29 +51,14 @@ getSignature = (payload) -> hmac.update new Buffer JSON.stringify(payload) return 'sha1=' + hmac.digest('hex') -#from https://github.com/vdemedes/secure-compare -secureCompare = (a, b) -> - if typeof a != 'string' or typeof b != 'string' - return false - mismatch = if a.length == b.length then 0 else 1 - if mismatch - b = a - i = 0 - il = a.length - while i < il - mismatch |= a.charCodeAt(i) ^ b.charCodeAt(i) - ++i - return (mismatch is 0) - module.exports = (robot) -> - robot.router.post "/hubot/github-repo-listener", (req, res) -> try if (debug) robot.logger.info("Github post received: ", req) if HUBOT_GITHUB_WEBHOOK_TOKEN isnt undefined signature = getSignature(req.body) - if not secureCompare(signature, req.headers['x-hub-signature']) + if signature isnt req.headers['x-hub-signature'] throw new Error('Signatures Do Not Match') eventBody = eventType : req.headers["x-github-event"]