diff --git a/jekyll-hook.js b/jekyll-hook.js index 7bedc41..ebd8bdb 100755 --- a/jekyll-hook.js +++ b/jekyll-hook.js @@ -13,17 +13,32 @@ var crypto = require('crypto'); app.use(express.bodyParser({ verify: function(req,res,buffer){ - if(!req.headers['x-hub-signature']){ - return; + if (!config.secret || config.secret === "") { + console.warn("Webhook secret is not configured."); + var err = new Error("Webhook secret is required"); + err.status = 500; + throw err; } - if(!config.secret || config.secret==""){ - console.log("Recieved a X-Hub-Signature header, but cannot validate as no secret is configured"); - return; + if (!req.headers['x-hub-signature']) { + console.warn("Missing X-Hub-Signature header."); + var err = new Error("Missing signature"); + err.status = 403; + throw err; + } + + var signature = req.headers['x-hub-signature']; + var parts = signature.split('='); + + if (parts.length !== 2 || parts[0] !== 'sha1') { + console.warn("Invalid X-Hub-Signature format."); + var err = new Error("Invalid signature format"); + err.status = 403; + throw err; } var hmac = crypto.createHmac('sha1', config.secret); - var recieved_sig = req.headers['x-hub-signature'].split('=')[1]; + var recieved_sig = parts[1]; var computed_sig = hmac.update(buffer).digest('hex'); if(recieved_sig != computed_sig){ @@ -52,6 +67,13 @@ app.post('/hooks/jekyll/*', function(req, res) { data.branch = data.ref.replace('refs/heads/', ''); data.owner = data.repository.owner.name; + var safePattern = /^[a-zA-Z0-9._-]+$/; + if (!safePattern.test(data.repo) || !safePattern.test(data.branch) || !safePattern.test(data.owner)) { + console.log('Security Error: Invalid characters detected in webhook data.'); + if (typeof cb === 'function') cb(); + return; + } + // End early if not permitted account if (config.accounts.indexOf(data.owner) === -1) { console.log(data.owner + ' is not an authorized account.');