Skip to content
This repository has been archived by the owner on Apr 3, 2019. It is now read-only.

fix(client): All template writes are by default HTML escaped. #4296

Merged
merged 1 commit into from
Oct 25, 2016

Conversation

shane-tomlinson
Copy link

A new Mustache helper function unsafeTranslate, has been added
for unsafe writes, to be used when inserting HTML.

All interpolation variables passed to unsafeTranslate must be
prefixed with escaped or else an exception is thrown. This is
to remind the developer to escape the variable in the most
appropriate way.

The t helper function now HTML escapes by default.

Rename some function/variable names for consistency:

  • displaySuccessUnsafe => unsafeDisplaySuccess
  • displayErrorUnsafe => unsafeDisplayError
  • successUnsafe => unsafeSuccess

*/
unsafeTranslate (text, context = this.getContext()) {
if (Strings.hasUnsafeVariables(text)) {
throw new Error(`Unsafe string to translate: ${text}`);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of a hard exception, maybe just log these for a train to see if we missed any?

@shane-tomlinson shane-tomlinson self-assigned this Oct 18, 2016
@shane-tomlinson shane-tomlinson force-pushed the shane-tomlinson/unsafe-html-in-templates branch 3 times, most recently from be82ecd to 9a6ad53 Compare October 19, 2016 10:58
* @returns {Boolean} true if string has HTML, false otw.
*/
function hasHTML(string) {
if (/&\D+;/i.test(string)) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extract these regexp"s into constants

*/
unsafeTranslate (text, context = this.getContext()) {
if (Strings.hasUnsafeVariables(text)) {
const err = AuthErrors.toError('UNSAFE_VARIABLE_NAME');
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe rename the error to UNSAFE_INTERPOLATION_VARIABLE_NAME

@@ -75,7 +75,7 @@ define(function (require, exports, module) {

if (email && isOpenWebmailButtonVisible) {
_.extend(context, {
unsafeWebmailLink: this.getWebmailLink(email),
escapedWebmailLink: this.getWebmailLink(email),
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don"t see where this is escaped!

@@ -19,8 +19,7 @@ define(function (require, exports, module) {
const TOOLTIP_MESSAGES = {
FOCUS_PROMPT_MESSAGE: t('8 characters minimum, but longer if you plan to sync passwords.'),
INITIAL_PROMPT_MESSAGE: t('A strong, unique password will keep your Firefox data safe from intruders.'),
WARNING_PROMPT_MESSAGE: t('This is a common password; please consider another one.'),
WARNING_PROMPT_MESSAGE_WITH_LINK: t('This is a common password; please consider another one.')
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the _WITH_LINK variant didn"t have a link, so I consolidated the two messages.

@@ -551,6 +597,14 @@ define(function (require, exports, module) {
});
});

describe('unsafeDisplaySuccess', () => {
it('allows HTML in messages', () => {
const expected = 'a message<div>with html</div>';
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use HTML_MESSAGE instead.

view.unsafeTranslate(HTML_MESSAGE), UNESCAPED_HTML_TRANSLATION);
assert.isFalse(view.logError.called);

view.unsafeTranslate('%(unsafeVariableName)s');
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extract this string to a constant.

@shane-tomlinson shane-tomlinson force-pushed the shane-tomlinson/unsafe-html-in-templates branch 2 times, most recently from 3a94829 to 3e085e5 Compare October 19, 2016 11:53
@shane-tomlinson shane-tomlinson changed the title WIP: fix(client): All template writes are by default HTML escaped. fix(client): All template writes are by default HTML escaped. Oct 19, 2016
@shane-tomlinson shane-tomlinson removed their assignment Oct 19, 2016
@shane-tomlinson
Copy link
Author

@mozilla/fxa-devs - who wants it?

Copy link
Contributor

@seanmonstar seanmonstar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I absolutely love the explicit naming: unsafeTranslate and escapedFoo. This PR just gives me a warm fuzzy feeling inside. Thank you!

if (Strings.hasHTML(text)) {
const err = AuthErrors.toError('HTML_WILL_BE_ESCAPED');
err.string = text;
this.logError(err);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In production does this error get sent to us, like sentry or something?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, exactly, the string itself will be part of the message displayed in Sentry.

var t = function (msg) {
return msg;
};
const HTML_CHAR_CODE_REGEXP = /&\D+;/i;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won"t catch when the escape code is numeric. &gt; and &#63; are equivalent, this regex won"t catch the latter.

* @returns {Boolean} true if has unsafe variables, false otw.
*/
function hasUnsafeVariables(string) {
if (UNNAMED_VARIABLE_REGEXP.test(string)) {
Copy link
Contributor

@seanmonstar seanmonstar Oct 19, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could use || instead:

return UNNAMED_VARIABLE_REGEXP.test(string) || UNSAFE_VARIABLE_REGEXP.test(string);

If you feel the ifs read more easily, ignore me.

const NAMED_VARIABLE_REGEXP = /\%\(([a-zA-Z]+)\)s/g;
const UNNAMED_VARIABLE_REGEXP = /%s/g;
// safe variables have an `escaped` prefix.
const UNSAFE_VARIABLE_REGEXP = /\%\(((?!escaped)[a-zA-Z]+)\)s/g;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We"ve been moving away from a postfix-Hungarian notation for RegExps in the auth server. I don"t know if that"s desirable here as well.

@shane-tomlinson shane-tomlinson force-pushed the shane-tomlinson/unsafe-html-in-templates branch from 3e085e5 to 8aaa194 Compare October 21, 2016 08:59
@shane-tomlinson
Copy link
Author

@seanmonstar - updated!

@shane-tomlinson shane-tomlinson force-pushed the shane-tomlinson/unsafe-html-in-templates branch from 8aaa194 to 47b1317 Compare October 21, 2016 13:11
Copy link
Contributor

@seanmonstar seanmonstar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All tidy! Looks good from here, except that Travis went red. It might be because of the DNS outage, so I just gave it a kick. Merge when travis is green!

@shane-tomlinson shane-tomlinson force-pushed the shane-tomlinson/unsafe-html-in-templates branch from 47b1317 to fd6a8d0 Compare October 24, 2016 11:46
A new Mustache helper function `unsafeTranslate`, has been added
for unsafe writes, to be used when inserting HTML.

All interpolation variables passed to `unsafeTranslate` must be
prefixed with `escaped` or else an exception is thrown. This is
to remind the developer to escape the variable in the most
appropriate way.

The `t` helper function now HTML escapes by default.

Rename some function/variable names for consistency:

* `displaySuccessUnsafe` => `unsafeDisplaySuccess`
* `displayErrorUnsafe` => `unsafeDisplayError`
* `successUnsafe` => `unsafeSuccess`
@shane-tomlinson shane-tomlinson force-pushed the shane-tomlinson/unsafe-html-in-templates branch from fd6a8d0 to 06d994f Compare October 25, 2016 12:00
@shane-tomlinson shane-tomlinson merged commit 4329101 into master Oct 25, 2016
@shane-tomlinson shane-tomlinson deleted the shane-tomlinson/unsafe-html-in-templates branch October 25, 2016 14:57
@rfk rfk added this to the FxA-0: quality milestone Nov 8, 2016
@rfk
Copy link
Contributor

rfk commented Nov 8, 2016

@shane-tomlinson does this fix the issue reported by cure53?

@shane-tomlinson
Copy link
Author

shane-tomlinson commented Nov 8, 2016

@rfk - yes
screen shot 2016-11-08 at 12 06 28

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants