-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
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
Implement referrer policy #10311
Comments
Tests: |
The goal of this specification is to allow webpages to control the behaviour of the The basic pieces here are the following:
|
I'm going to work on this issue! |
I've added some file pointers to my previous comment. Let us know if anything's unclear! |
I'm a little confused on scope - the spec refers to the "settings object" as having a referrer policy - is this specific to the Document? What do you mean above by "global environment"? Also, I've worked with the document file a little, but not workerglobalscope - can you give a quick explanation of what that file is and how that and document interact (if they interact). |
A "global environment" refers to the root object for executing JavaScript code. You can think of this as a per-tab global object. The "settings object" is a concept that we don't have an equivalent for in Servo yet, so we'll treat it as "data that resides in the global object". |
On the policy propagation piece - I'm not totally clear what has access to what. Looking at the files, what seems to be happening is that when you click on a link that should load a new page, the document_loader 'prepare_async_load' method gets called, and that, in theory, is where things can be passed between the document and the http_loader methods (most notably, load). If I have a document with some referrer policy, the load method would need both the current document's referrer policy and the current document's URL (and maybe some other stuff) in order to properly set the referer header. Right now, load doesn't have any access to the current doc(?). Is this right? |
That is correct; the desired referrer policy would need to be passed as part of the LoadData. Passing it to the PendingAsyncLoad constructor via the methods in Document that invoke the DocumentLoader code would make sense to me. |
But beyond that, if I just have the referrer policy, I still cant set the header because I also need the previous document's URL to populate it - the loaddata currently just has the url to be loaded, right? |
Yep. We should probably add that to LoadData as well! |
Alright, so just wanna confirm I'm on the right track here: rebstar6@8c91f8a I added Option for referrer policy and referrer URL to both PendingAsyncLoad and LoadData. From document, they get passed 1st to PendingAsyncLoad which passes them forward to LoadData (where they will be picked up by the http_loader when setting headers). With the exception of the prepare_async_load/load_async methods, these are None. Just to confirm - document.rs has both prepare_async_load and load_async, each of which call their respective methods in document_loader...but the document_loader's load_async calls prepare_async_load. Is the prepare getting called twice? What is the point of prepare_async_load within the document class? |
Yes, that looks like it's on the right track. The LoadData constructors in XMLHttpRequest and ScriptThread::start_page_load should have non-None values, but those can be dealt with later as long as there's a TODO marking them. As for the second question, prepare doesn't get called twice for the same value. The difference between prepare_async_load and async_load is that the former returns a structure that encapsulates a network request that can be started at some point in the future, while the second initiates a network request immediately. |
Alright cool. Also, where does fetch come into play (and what is it, exactly?)? The next thing I was going to try was to set the referer header within modify_request_headers based on the policy and urls. However, unsure if this should actually go into the fetch code instead (or both if theyre separate things)? |
The code in |
@SimonSapin - I mentioned this in IRC but I don't think you were on then. At some point for this issue, I will need to strip the username/password, fragment, and in some cases path and query from a URL (see https://w3c.github.io/webappsec-referrer-policy/#strip-url). I was told that you wrote (and are working on) rust-url. Do you have any suggestions about the best way to approach this? Are there changes to the crate that might make some of this easier? Any help appreciated! |
The image loader code isn't providing a referrer because the current design of the image cache makes it impossible to do so correctly. We can ignore any failures to do with images, accordingly. The failure for the top-level Document is start_page_load, as you correctly intuited. |
@rebstar6 Yes I’m the main author and maintainer of rust-url. You can find the API documentation for the As you can see there, each component is stored separately. You can reset them with code like: if let Some(relative) = url.relative_scheme_data_mut() {
// String::clear sets the length of a string to zero, effectively removing its content.
relative.username.clear();
relative.password = None;
}
url.fragment = None; I also have PR #9840 that updates Servo to a version of rust-url where the url.set_fragment(None);
let _ = url.set_password(None);
let _ = url.set_username(""); Since strings are contiguous in memory, touching something in the middle that changes the length mean the rest of the string afterwards needs to be moved. For that reason it’s slightly more efficient to remove components at the end of the URL first.
Feel free to ask more questions here or on IRC. I’m in the central Europe time zone, but if you mention my nickname on IRC while I’m away I’ll still see it later and can answer then (or maybe someone else can answer), so leave your IRC client online if you can. |
@jdm a few more questions...
|
|
Gotcha. I'm definitely to the point where having some tests to code from would be helpful. If you could give me a little more guidance on how to edit what we have (or create new?), that would be great. I think I have the Referer header setting piece mostly in place (read: http-loader will set the referer header given the some policy and url provided by the calling document). This assumes some policy given though, I'm not yet pulling the policy from anywhere. I could, at a minimum, write some unit tests for this to verify it, but those will be moot if we can get the full html tests working. Also, thinking in terms of eventual review, is there any way you want me split this up for PRs? I don't want it to get too big and stuck in review. (code at https://github.com/rebstar6/servo/tree/referrerPolicy) |
Whoops, didn't get back to you earlier. Window.load_URL looks like a fine choke point. |
In terms of tests, we can't write unit tests for network code that interacts with code in script, so the best we can do there is write tests for the network code given LoadData with certain characteristics. Those would be tests in unit/net/http_loader.rs that verify that the expected Referer header is present in the request that would be sent to the server. For those iframe WPT tests, I'll take a look and see if there's a way to copy and rewrite some of them to not timeout. |
As for reviewing, if you'd like to split it up like:
That should make each part straightforward to review. |
So I guess the question is, is there any point in writing some unit tests and PR-ing what I have now so I can get an early review on it? That would include:
The unit tests, as you suggested, would actually validate what I have so far - given a policy, does http-loader set the right header?. The iframe tests that we want to edit become necessary only in the next piece, which is setting the policy as delivered by: https://w3c.github.io/webappsec-referrer-policy/#referrer-policy-delivery |
Awesome! PR out - #11238 |
FYI - once meta referrer is in, the tests definitely need more changes for the other delivery policies (more so than we thought...). Referrer-Policy header is the obvious next step, but the tests use Content-Security-Policy, which seems to have been the old way of things at some point. Not sure how easy a switch this is - I may be able to just change referrer_policy/generic/tools/generate.py for http-csp to add Referrer-Policy not Content-Security-Policy, but that feels hacky. Hrmm. |
That is likely the best way to do it, assuming that w3c/webappsec-referrer-policy@fc55d91#commitcomment-17717693 is correct. We should make changes like that in the upstream repository to make sure the right eyes see it. |
Implement meta referrer policy delivery (3) <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #10311 (github issue number if applicable). <!-- Either: --> - [X] There are tests for these changes OR - [ ] These changes do not require tests because _____ <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/11468) <!-- Reviewable:end -->
Implement meta referrer policy delivery (3) <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #10311 (github issue number if applicable). <!-- Either: --> - [X] There are tests for these changes OR - [ ] These changes do not require tests because _____ <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/11468) <!-- Reviewable:end -->
@rebstar6 @jdm once meta referrer PR (3) lands, is it enough to ask the duckduckgo folks to set servo as "trusted"? See what they say here: #10309 (comment) |
@paulrouget - I think? You can certainly ask, and if they want more, hopefully they'll say so (and looks like you have anyway). To summarize, thus far we have implemented the meta-referrer delivery piece of this for Documents only (not workers), and using the policies in the w3c tests (and spec at the time the DuckDuckGo issue happened). The spec changed, so there is an issue to update the policies to the latest, which should be trivial once the tests are changed (#11384). FWIW, we maintain a default of 'No-Referrer' (rather than blank) for now, so that the Referer header isn't sent unless a policy is specified in the right meta element - this is safer than the alternative, since we have not implemented the other delivery methods. Other delivery types are a TODO, though those also require test changes (seems like those are pretty out of date). |
Test change for header delivery: web-platform-tests/wpt#3116 Not sure what review is like on w3c, but those are in there. Once the 1st is approved, work can start on referrer policy delivery via the Referrer-Policy header |
This set of more manageable issues should cover the remaining work (at least, as of today's spec):
There may also be some fetch work when the other delivery policies are implemented (?). I'm stepping off this as much with my job starting Monday, so these issues are free for the taking! I can definitely answer questions though for whoever picks it up :) |
…r=jdm PR1 for servo/servo#10311 This puts the code and data structures in place to set the Referer header based on the Referrer Policy for a given document. Note that document:: get_referrer_policy() always returns the 'No Referrer' option, so for now, this should have no impact on production code, and that policy requires that the Referer header is not added. Later PRs will determine the policy and edit that get_referrer_policy() accordingly. Source-Repo: https://github.com/servo/servo Source-Revision: 34900814fca3b21fbb27bed58d4f4af8a8e307e9 UltraBlame original commit: d088446dcbc0a71d1b2cade87d0ec28deb233de1
…r=jdm PR1 for servo/servo#10311 This puts the code and data structures in place to set the Referer header based on the Referrer Policy for a given document. Note that document:: get_referrer_policy() always returns the 'No Referrer' option, so for now, this should have no impact on production code, and that policy requires that the Referer header is not added. Later PRs will determine the policy and edit that get_referrer_policy() accordingly. Source-Repo: https://github.com/servo/servo Source-Revision: 34900814fca3b21fbb27bed58d4f4af8a8e307e9 UltraBlame original commit: d088446dcbc0a71d1b2cade87d0ec28deb233de1
…r=jdm PR1 for servo/servo#10311 This puts the code and data structures in place to set the Referer header based on the Referrer Policy for a given document. Note that document:: get_referrer_policy() always returns the 'No Referrer' option, so for now, this should have no impact on production code, and that policy requires that the Referer header is not added. Later PRs will determine the policy and edit that get_referrer_policy() accordingly. Source-Repo: https://github.com/servo/servo Source-Revision: 34900814fca3b21fbb27bed58d4f4af8a8e307e9 UltraBlame original commit: d088446dcbc0a71d1b2cade87d0ec28deb233de1
|
See https://w3c.github.io/webappsec-referrer-policy/
Necessary for #10309 (comment)
The text was updated successfully, but these errors were encountered: