Skip to content

Commit 9e53feb

Browse files
committed
Add webhook secret and support payload validation
Backported from c11aad1. Fixes #295 Conflicts: SourceGithub/SourceGithub.php
1 parent 616b8c8 commit 9e53feb

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

SourceGithub/SourceGithub.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ public function update_repo_form( $p_repo ) {
9595
$t_hub_app_client_id = null;
9696
$t_hub_app_secret = null;
9797
$t_hub_app_access_token = null;
98+
$t_hub_webhook_secret = null;
9899

99100
if ( isset( $p_repo->info['hub_username'] ) ) {
100101
$t_hub_username = $p_repo->info['hub_username'];
@@ -116,6 +117,10 @@ public function update_repo_form( $p_repo ) {
116117
$t_hub_app_access_token = $p_repo->info['hub_app_access_token'];
117118
}
118119

120+
if ( isset( $p_repo->info['hub_webhook_secret'] ) ) {
121+
$t_hub_webhook_secret = $p_repo->info['hub_webhook_secret'];
122+
}
123+
119124
if ( isset( $p_repo->info['master_branch'] ) ) {
120125
$t_master_branch = $p_repo->info['master_branch'];
121126
} else {
@@ -176,6 +181,14 @@ public function update_repo_form( $p_repo ) {
176181
<span class="label-style"></span>
177182
</div>
178183

184+
<div class="field-container">
185+
<label><span><?php echo plugin_lang_get( 'hub_webhook_secret' ) ?></span></label>
186+
<span class="input">
187+
<input name="hub_webhook_secret" maxlength="250" size="40" value="<?php echo string_attribute( $t_hub_webhook_secret ) ?>"/>
188+
</span>
189+
<span class="label-style"></span>
190+
</div>
191+
179192
<div class="field-container">
180193
<label><span><?php echo plugin_lang_get( 'master_branch' ) ?></span></label>
181194
<span class="input">
@@ -197,6 +210,7 @@ public function update_repo( $p_repo ) {
197210
$f_hub_reponame = gpc_get_string( 'hub_reponame' );
198211
$f_hub_app_client_id = gpc_get_string( 'hub_app_client_id' );
199212
$f_hub_app_secret = gpc_get_string( 'hub_app_secret' );
213+
$f_hub_webhook_secret = gpc_get_string( 'hub_webhook_secret' );
200214
$f_master_branch = gpc_get_string( 'master_branch' );
201215

202216
$this->validate_branch_list( $f_master_branch );
@@ -205,6 +219,7 @@ public function update_repo( $p_repo ) {
205219
$p_repo->info['hub_reponame'] = $f_hub_reponame;
206220
$p_repo->info['hub_app_client_id'] = $f_hub_app_client_id;
207221
$p_repo->info['hub_app_secret'] = $f_hub_app_secret;
222+
$p_repo->info['hub_webhook_secret'] = $f_hub_webhook_secret;
208223
$p_repo->info['master_branch'] = $f_master_branch;
209224

210225
return $p_repo;
@@ -279,6 +294,29 @@ public function precommit() {
279294
$t_repo->id = $t_row['id'];
280295

281296
if ( $t_repo->info['hub_reponame'] == $t_reponame ) {
297+
# Retrieve the payload's signature from the request headers
298+
# Reference https://developer.github.com/webhooks/#delivery-headers
299+
$t_signature = null;
300+
if( array_key_exists( 'HTTP_X_HUB_SIGNATURE', $_SERVER ) ) {
301+
$t_signature = explode( '=', $_SERVER['HTTP_X_HUB_SIGNATURE'] );
302+
if( $t_signature[0] != 'sha1' ) {
303+
# Invalid hash - as per docs, only sha1 is supported
304+
return;
305+
}
306+
$t_signature = $t_signature[1];
307+
}
308+
309+
# Validate payload against webhook secret: checks OK if
310+
# - Webhook secret not defined and no signature received from GitHub, OR
311+
# - Payload's SHA1 hash salted with Webhook secret matches signature
312+
$t_secret = $t_repo->info['hub_webhook_secret'];
313+
$t_valid = ( !$t_secret && !$t_signature )
314+
|| $t_signature == hash_hmac('sha1', $f_payload, $t_secret);
315+
if( !$t_valid ) {
316+
# Invalid signature
317+
return;
318+
}
319+
282320
return array( 'repo' => $t_repo, 'data' => $t_data );
283321
}
284322
}

SourceGithub/lang/strings_english.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ $s_plugin_SourceGithub_hub_reponame = 'GitHub Repository Name<br/><span class="s
1313
$s_plugin_SourceGithub_hub_app_client_id = 'GitHub Application Client ID<br><span class="small">This is required for private repositories and also allows to get around the <a href="https://developer.github.com/v3/#rate-limiting">Rate Limit</a> when importing data.<br>Create a new <a href="https://github.com/settings/applications">GitHub Application</a> if needed.</span>';
1414
$s_plugin_SourceGithub_hub_app_secret = 'GitHub Application Secret';
1515
$s_plugin_SourceGithub_hub_app_access_token = 'GitHub Application Access Token';
16+
$s_plugin_SourceGithub_hub_webhook_secret = 'GitHub Webhook Secret';
1617
$s_plugin_SourceGithub_master_branch = 'Primary Branches<br/><span class="small">(comma-separated list or "*" for all branches)</span>';
1718

1819
$s_plugin_SourceGithub_hub_app_client_id_secret_missing = '<span class="small">You must first enter the GitHub Application <em>Client ID</em> &amp; <em>Secret</em> and update the repository before you can authorize.</span>';

0 commit comments

Comments
 (0)