Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

amp-bind: Throw user error when replacing non-whitelisted URL vars #13081

Merged
merged 12 commits into from
Feb 1, 2018

Conversation

dreamofabear
Copy link

@dreamofabear dreamofabear commented Jan 27, 2018

Step 1 for #12498.

  • Throw user error when performing non-whitelisted URL var replacement via amp-bind
  • Default to no replacement with new optional param opt_urlReplacement
  • Add test-batched-json.js file
  • Rename fetchBatchedJsonFor to batchFetchJsonFor

Aside: I think we should merge batched-json.js into batched-xhr.js. It'll also make stubbing the function possible.

@dreamofabear
Copy link
Author

/to @aghassemi @alabiaga

* @return {!Promise<!Array<string>>}
*/
collectUnwhitelistedVars(element) {
const url = element.getAttribute('src');
Copy link
Contributor

Choose a reason for hiding this comment

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

const url only used once, just inline?

Copy link
Author

Choose a reason for hiding this comment

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

I'd prefer this for readability and debuggability.

const url = element.getAttribute('src');
return this.collectVars(url).then(vars => {
const whitelist = this.getWhitelistForElement_(element);
return Object.keys(vars).filter(v => !whitelist[v]);
Copy link
Contributor

Choose a reason for hiding this comment

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

just inline?

Copy link
Author

Choose a reason for hiding this comment

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

Had to change this to account for whitelist == undefined case.

return fetchBatchedJsonFor(this.getAmpDoc(), this.element, itemsExpr);
// Require opt-in for URL variable replacements on fetches triggered
// by [src] mutation. @see spec/amp-var-substitutions.md
const policy = (this.element.getAttribute('src') == this.initialSrc_)
Copy link
Contributor

@aghassemi aghassemi Jan 30, 2018

Choose a reason for hiding this comment

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

Can we just compare the origin's and allow path and hash to differ? That would make it less of a breaking change and I don't see particular security concerns if origins match, but I might be wrong.

Copy link
Author

Choose a reason for hiding this comment

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

You're right that this only matters for requests to non-pub-origins but I thought that would too specific to message gracefully. I'll try it out though.

Copy link
Author

Choose a reason for hiding this comment

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

This is done.

/**
* @enum {number}
*/
export const UrlReplacementPolicy = {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Maybe FetchUrlReplacementPolicy since the policy does not apply to other cases?

Copy link
Author

Choose a reason for hiding this comment

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

I think we don't need to disambiguate here since none/opt-in/all does fit the system in general. E.g. <input> and <a> tags currently require opt-in, and some URL attributes don't support substitutions at all.


// Replace vars in URL if desired.
const urlReplacements = Services.urlReplacementsForDoc(ampdoc);
const srcPromise = (opt_urlReplacement >= UrlReplacementPolicy.OPT_IN)
Copy link
Contributor

Choose a reason for hiding this comment

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

In the none case, should they be replaced with ``? leaving them as is would generate strange and wrong Urls.

Copy link
Author

Choose a reason for hiding this comment

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

Leaving it unmodified is the default behavior for other opt-ins, e.g. <a>.

@cramforce
Copy link
Member

This pull request introduces 1 alert - view on lgtm.com

new alerts:

  • 1 for Syntax error

Comment posted by lgtm.com

@cramforce
Copy link
Member

This pull request introduces 1 alert - view on lgtm.com

new alerts:

  • 1 for Syntax error

Comment posted by lgtm.com

Copy link
Author

@dreamofabear dreamofabear left a comment

Choose a reason for hiding this comment

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

Thanks for the comments everyone.

* @return {!Promise<!Array<string>>}
*/
collectUnwhitelistedVars(element) {
const url = element.getAttribute('src');
Copy link
Author

Choose a reason for hiding this comment

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

I'd prefer this for readability and debuggability.

const url = element.getAttribute('src');
return this.collectVars(url).then(vars => {
const whitelist = this.getWhitelistForElement_(element);
return Object.keys(vars).filter(v => !whitelist[v]);
Copy link
Author

Choose a reason for hiding this comment

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

Had to change this to account for whitelist == undefined case.

return fetchBatchedJsonFor(this.getAmpDoc(), this.element, itemsExpr);
// Require opt-in for URL variable replacements on fetches triggered
// by [src] mutation. @see spec/amp-var-substitutions.md
const policy = (this.element.getAttribute('src') == this.initialSrc_)
Copy link
Author

Choose a reason for hiding this comment

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

This is done.


// Replace vars in URL if desired.
const urlReplacements = Services.urlReplacementsForDoc(ampdoc);
const srcPromise = (opt_urlReplacement >= UrlReplacementPolicy.OPT_IN)
Copy link
Author

Choose a reason for hiding this comment

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

Leaving it unmodified is the default behavior for other opt-ins, e.g. <a>.

/**
* @enum {number}
*/
export const UrlReplacementPolicy = {
Copy link
Author

Choose a reason for hiding this comment

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

I think we don't need to disambiguate here since none/opt-in/all does fit the system in general. E.g. <input> and <a> tags currently require opt-in, and some URL attributes don't support substitutions at all.

@dreamofabear dreamofabear requested a review from a user February 1, 2018 19:39
@@ -48,7 +48,7 @@ The following table lists the features that enable variable substitutions, as we
<tr>
<td width="25%"><code>amp-list</code><br><a href="https://github.com/ampproject/amphtml/blob/master/extensions/amp-list/amp-list.md#substitutions">Detailed documentation</a></td>
<td width="25%">Requests must be HTTPS URLs (not a requirement specific to variable substitutions)</td>
<td width="25%">No</td>
<td width="25%">Yes, if fetching cross-origin resources via <code>[src]</code> <a href="https://www.ampproject.org/docs/reference/components/amp-bind#element-specific-attributes">attribute binding</a>. Otherwise, no. Read more about <a href="#per-use-opt-in">per-use opt-in</a></td>
Copy link
Author

Choose a reason for hiding this comment

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

@bpaduch Would like your input on whether this is confusing or not.

user().error(TAG, 'URL variable substitutions in CORS fetches ' +
'triggered by amp-bind will soon require opt-in. Please add ' +
`data-amp-replace="${unwhitelisted.join(' ')}" to the ` +
`<${TAG}> element. See "bit.ly/amp-var-subs" for details.`);
Copy link
Author

Choose a reason for hiding this comment

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

@bpaduch Ditto.

@dreamofabear
Copy link
Author

@ericlindley-g FYI adding a user error for new opt-in requirement in preparation for two-way amp-frame messaging.

Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

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

Docs are good.

@ericlindley-g
Copy link
Contributor

Thanks for the heads up! Could you refresh my memory on the end-to-end path for this to give developers notice before an error is triggered that invalidates the page or breaks functionality? (e.g. Validation warning -> error)

@dreamofabear
Copy link
Author

#12498 lists all the steps you suggested. This PR will only show a user error in dev console but retain current functionality. After deployment, we'll see how common this is in the wild via our error logs and can decide next steps from there.

@ericlindley-g
Copy link
Contributor

Perfect — thanks! (I knew I had seen those somewhere :)

@dreamofabear dreamofabear merged commit 2bfb03b into ampproject:master Feb 1, 2018
@dreamofabear dreamofabear deleted the bind-opt-in-error branch February 1, 2018 20:42
RanAbram pushed a commit to RanAbram/amphtml that referenced this pull request Mar 12, 2018
…mpproject#13081)

* first pass at user().error for future opt-in requirement

* url replacements unit test

* rename to batchFetchJsonFor and add test-batched-json

* lint fixes, use enum for replacement policy

* refine docs

* fix lint

* use opt-in policy for amp-bind mutations only, fix types

* more lint fixes

* only require opt-in for CORS

* fix collectUnwhitelistedVars for elements with no whitelist

* refine error message

* fix string error, thanks lgtm
protonate pushed a commit to protonate/amphtml that referenced this pull request Mar 15, 2018
…mpproject#13081)

* first pass at user().error for future opt-in requirement

* url replacements unit test

* rename to batchFetchJsonFor and add test-batched-json

* lint fixes, use enum for replacement policy

* refine docs

* fix lint

* use opt-in policy for amp-bind mutations only, fix types

* more lint fixes

* only require opt-in for CORS

* fix collectUnwhitelistedVars for elements with no whitelist

* refine error message

* fix string error, thanks lgtm
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants