Skip to content
This repository has been archived by the owner on Dec 29, 2022. It is now read-only.

Commit

Permalink
Fix XSS issue with email in signup form.
Browse files Browse the repository at this point in the history
  • Loading branch information
GUI committed Dec 9, 2016
1 parent faa3ee3 commit 486950b
Showing 1 changed file with 27 additions and 13 deletions.
40 changes: 27 additions & 13 deletions source/assets/javascripts/_signup_embed/setup.js.erb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,20 @@ bootbox.setDefaults({
container: options.containerSelector
});

var htmlEscapes = {
'&': '&',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;',
};

function escapeHtml(string) {
return String(string).replace(/[&<>"']/g, function(s) {
return htmlEscapes[s];
});
}

var signupFormTemplate = '<p>Sign up for an application programming interface (API) key to access and use web services available on the Data.gov developer network.</p>' +
'<p class="required-fields"><abbr title="Required" class="required"><span class="abbr-required">*</span></abbr> Required fields</p>' +
'<form id="api_umbrella_signup_form" class="form-horizontal" role="form">' +
Expand Down Expand Up @@ -71,7 +85,7 @@ if(options.termsCheckbox) {
signupFormTemplate += '<div class="form-group">' +
'<div class="col-sm-offset-4 col-sm-8">' +
'<div class="checkbox">' +
'<label><input id="user_terms_and_conditions" name="user[terms_and_conditions]" type="checkbox" value="1" required data-parsley-error-message="You must agree to the terms and conditions to signup" />I have read and agree to the <a href="' + options.termsUrl + '" onclick="window.open(this.href, &#x27;api_umbrella_terms&#x27;, &#x27;height=500,width=790,menubar=no,toolbar=no,location=no,personalbar=no,status=no,resizable=yes,scrollbars=yes&#x27;); return false;" title="Opens new window to terms and conditions">terms and conditions</a>.</label>' +
'<label><input id="user_terms_and_conditions" name="user[terms_and_conditions]" type="checkbox" value="1" required data-parsley-error-message="You must agree to the terms and conditions to signup" />I have read and agree to the <a href="' + escapeHtml(options.termsUrl) + '" onclick="window.open(this.href, &#x27;api_umbrella_terms&#x27;, &#x27;height=500,width=790,menubar=no,toolbar=no,location=no,personalbar=no,status=no,resizable=yes,scrollbars=yes&#x27;); return false;" title="Opens new window to terms and conditions">terms and conditions</a>.</label>' +
'</div>' +
'</div>' +
'</div>';
Expand All @@ -81,7 +95,7 @@ if(options.termsCheckbox) {

signupFormTemplate += '<div class="form-group">' +
'<div class="col-sm-offset-4 col-sm-8">' +
'<input type="hidden" name="user[registration_source]" value="' + options.registrationSource + '" />' +
'<input type="hidden" name="user[registration_source]" value="' + escapeHtml(options.registrationSource) + '" />' +
'<button type="submit" class="btn btn-lg btn-primary" data-loading-text="Loading...">Signup</button>' +
'</div>' +
'</div>' +
Expand Down Expand Up @@ -120,25 +134,25 @@ form.submit(function(event) {
crossDomain: true,
}).done(function(response) {
var user = response.user;
var exampleApiUrl = options.exampleApiUrl.replace('{{api_key}}', user.api_key);
var formattedExampleApiUrl = options.exampleApiUrl.replace('api_key={{api_key}}', '<strong>api_key=' + user.api_key + '</strong>');
var exampleApiUrl = escapeHtml(options.exampleApiUrl).replace('{{api_key}}', user.api_key);
var formattedExampleApiUrl = escapeHtml(options.exampleApiUrl).replace('api_key={{api_key}}', '<strong>api_key=' + escapeHtml(user.api_key) + '</strong>');

var confirmationTemplate = '';
if(options.verifyEmail) {
confirmationTemplate += '<p>Your API key for <strong>' + user.email + '</strong> has been e-mailed to you. You can use your API key to begin making web service requests immediately.</p>';
confirmationTemplate += '<p>If you don\'t receive your API Key via e-mail within a few minutes, please <a href="' + options.contactUrl + '">contact us</a>.</p>';
confirmationTemplate += '<p>Your API key for <strong>' + escapeHtml(user.email) + '</strong> has been e-mailed to you. You can use your API key to begin making web service requests immediately.</p>';
confirmationTemplate += '<p>If you don\'t receive your API Key via e-mail within a few minutes, please <a href="' + escapeHtml(options.contactUrl) + '">contact us</a>.</p>';
} else {
confirmationTemplate += '<p>Your API key for <strong>' + user.email + '</strong> is:</p>' +
'<code class="signup-key">' + user.api_key + '</code>' +
confirmationTemplate += '<p>Your API key for <strong>' + escapeHtml(user.email) + '</strong> is:</p>' +
'<code class="signup-key">' + escapeHtml(user.api_key) + '</code>' +
'<p>You can start using this key to make web service requests. Simply pass your key in the URL when making a web request. Here\'s an example:</p>' +
'<pre class="signup-example"><a href="' + exampleApiUrl + '">' + formattedExampleApiUrl + '</a></pre>';
}

confirmationTemplate += options.signupConfirmationMessage +
'<div class="signup-footer">' +
'<p>For additional support, please <a href="' + options.contactUrl + '">contact us</a>. When contacting us, please tell us what API you\'re accessing and provide the following account details so we can quickly find you:</p>' +
'Account Email: ' + user.email + '<br>' +
'Account ID: ' + user.id +
'<p>For additional support, please <a href="' + escapeHtml(options.contactUrl) + '">contact us</a>. When contacting us, please tell us what API you\'re accessing and provide the following account details so we can quickly find you:</p>' +
'Account Email: ' + escapeHtml(user.email) + '<br>' +
'Account ID: ' + escapeHtml(user.id) +
'</div>';

$(options.containerSelector).html(confirmationTemplate);
Expand All @@ -153,15 +167,15 @@ form.submit(function(event) {
if (xhr.responseJSON && xhr.responseJSON.errors) {
$.each(xhr.responseJSON.errors, function(idx, error) {
if (error.message) {
messages.push(error.message);
messages.push(escapeHtml(error.message));
}
});
}
if (messages) {
messageStr = '<br><ul><li>' + messages.join('</li><li>') + '</li></ul>';
}

bootbox.alert('API key signup unexpectedly failed.' + messageStr + '<br>Please try again or <a href="' + options.contactUrl + '">contact us</a> for assistance.');
bootbox.alert('API key signup unexpectedly failed.' + messageStr + '<br>Please try again or <a href="' + escapeHtml(options.contactUrl) + '">contact us</a> for assistance.');
}).always(function() {
submit.button('reset');
});
Expand Down

0 comments on commit 486950b

Please sign in to comment.