Confirmed users
620
edits
Ptheriault (talk | contribs) (csp section done) |
Ethantseng (talk | contribs) (Adjust format.) |
||
| (35 intermediate revisions by 5 users not shown) | |||
| Line 12: | Line 12: | ||
==New Security Model | ==New Security Model== | ||
=== Signing - {{Bug|1153420}}=== | === Signing - {{Bug|1153420}}=== | ||
| Line 37: | Line 26: | ||
♦ '''Issue:''' Decide on exact signature format. Should we require that the signature-files live at the start of the package. That way we'd always have the signature available before the file contents covered by the signature. | ♦ '''Issue:''' Decide on exact signature format. Should we require that the signature-files live at the start of the package. That way we'd always have the signature available before the file contents covered by the signature. | ||
=== Verifying signatures - {{Bug|1153422}} === | === Verifying signatures - {{Bug|1153422}} === | ||
| Line 59: | Line 39: | ||
Another thing that needs to be done before any content is served by the network layer is to look in the manifest and populate the nsIPermissionManager database with any permissions enumerated in the manifest. After having checked that the manifest properly matches the signature of course. | Another thing that needs to be done before any content is served by the network layer is to look in the manifest and populate the nsIPermissionManager database with any permissions enumerated in the manifest. After having checked that the manifest properly matches the signature of course. | ||
=== CSP - {{Bug|1153423}} === | === CSP - {{Bug|1153423}} === | ||
We need to make sure that it can't load scripts from outside of the signed package. And we need to make sure that it can't use inline scripts. | We need to make sure that it can't load scripts from outside of the signed package. And we need to make sure that it can't use inline scripts. | ||
The plan is to use the CSP code to accomplish this. We can mainly leverage existing code which enables applying a default CSP policy to certain content. We'll use this to apply a default CSP to all signed content similarly to how we currently apply a default CSP to all privileged apps. | The plan is to use the CSP code to accomplish this. We can mainly leverage existing code which enables applying a default CSP policy to certain content. We'll use this to apply a default CSP to all signed content similarly to how we currently apply a default CSP to all privileged apps. | ||
| Line 82: | Line 52: | ||
Hopefully this is a restriction we can eventually relax, for example by allowing pages in a signed package to opt in to being iframe-able. But this will require out-of-process <iframe>s and so will have to wait. | Hopefully this is a restriction we can eventually relax, for example by allowing pages in a signed package to opt in to being iframe-able. But this will require out-of-process <iframe>s and so will have to wait. | ||
=== Process isolation - {{Bug|1153428}} === | |||
=== Process isolation | |||
In order to ensure that only signed content can access the APIs that it has been signed for, we want to always use separate child processes to run such content. | In order to ensure that only signed content can access the APIs that it has been signed for, we want to always use separate child processes to run such content. | ||
This means that when a user navigates from an unsigned page to a signed page, that we need to switch which process render the pages. Right now this can only be done by creating a new <iframe mozbrowser>. | This means that when a user navigates from an unsigned page to a signed page, that we need to switch which process render the pages. Right now this can only be done by creating a new <iframe mozbrowser>. | ||
| Line 107: | Line 64: | ||
We also need to change security checks that currently are done in the parent process. Currently many of them are heavily based on app-ids and installed apps. This may need to be changed. | We also need to change security checks that currently are done in the parent process. Currently many of them are heavily based on app-ids and installed apps. This may need to be changed. | ||
=== Installing and updating - {{Bug|1153432}} === | |||
=== Installing and updating | |||
Issue: How can we register web activities when we pin a page. And update those registries when the pinned manifest is updated. | Issue: How can we register web activities when we pin a page. And update those registries when the pinned manifest is updated. | ||
| Line 120: | Line 70: | ||
Signed packages follow normal http semantics. I.e. if the package still exists in our http cache when the user revisits a signed page, but the cache headers indicate that the content needs to be updated, we do a normal GET request to see if a new version needs to be downloaded. | Signed packages follow normal http semantics. I.e. if the package still exists in our http cache when the user revisits a signed page, but the cache headers indicate that the content needs to be updated, we do a normal GET request to see if a new version needs to be downloaded. | ||
If a new version of the package is being sent, we follow the same behavior as when visiting a package for the first time. I.e. we need to reverify signatures as well as update any permissions in the nsIPermissionManager database. | If a new version of the package is being sent, we follow the same behavior as when visiting a package for the first time. I.e. we need to reverify signatures as well as update any permissions in the nsIPermissionManager database. | ||
| Line 132: | Line 78: | ||
Gecko can then use the diff to patch the existing package. | Gecko can then use the diff to patch the existing package. | ||
Note that sending a diff is entirely the server's choice. If the server doesn't support this newly created diff mechanism, then it will simply serve a full package. Likewise if the user is on a very old version which the server doesn't have a diff for or if the diff has bigger size than the resulting package, the server can simply serve a full package. | Note that sending a diff is entirely the server's choice. If the server doesn't support this newly created diff mechanism, then it will simply serve a full package. Likewise if the user is on a very old version which the server doesn't have a diff for or if the diff has bigger size than the resulting package, the server can simply serve a full package. | ||
| Line 143: | Line 87: | ||
Installing a signed package mainly consists of pinning it in the http cache such that it doesn't get evicted. We still need to check for updates according to normal "app update" scheduling. | Installing a signed package mainly consists of pinning it in the http cache such that it doesn't get evicted. We still need to check for updates according to normal "app update" scheduling. | ||
=== Service Workers - {{Bug|1153433}} === | |||
=== Service Workers | |||
One of the central pieces of the new Gaia architecture is the use of service workers. This isn't just to support offline for gaia apps, but also to support dynamic generation of page markup, and the ability to run logic in order to decide what resource to return for a given URL. | One of the central pieces of the new Gaia architecture is the use of service workers. This isn't just to support offline for gaia apps, but also to support dynamic generation of page markup, and the ability to run logic in order to decide what resource to return for a given URL. | ||
In order to make service workers work with the package update logic we should couple package update with service worker update. When the ServiceWorker spec require the browser to check for updates of, or download updates of, the ServiceWorker script, we instead update the full signed package. | In order to make service workers work with the package update logic we should couple package update with service worker update. When the ServiceWorker spec require the browser to check for updates of, or download updates of, the ServiceWorker script, we instead update the full signed package. | ||
This means that both when we do an "automatic" ServiceWorker update check, such as when the user visit a page which uses the ServiceWorker, and when the ServiceWorkerRegistration.update() function is called, that we update the full package rather than just the ServiceWorker script. | This means that both when we do an "automatic" ServiceWorker update check, such as when the user visit a page which uses the ServiceWorker, and when the ServiceWorkerRegistration.update() function is called, that we update the full package rather than just the ServiceWorker script. | ||
Once a new package has been downloaded, we go through the normal ServiceWorker update cycle. I.e. Gecko fire both "install" and "activate" events on the ServiceWorker. This will happen any time that a package is updated, even if the contents of the ServiceWorker script hasn't changed. | Once a new package has been downloaded, we go through the normal ServiceWorker update cycle. I.e. Gecko fire both "install" and "activate" events on the ServiceWorker. This will happen any time that a package is updated, even if the contents of the ServiceWorker script hasn't changed. | ||
Gecko need to still serve the previous package content until the "activate" event for the new ServiceWorker version fires. I.e. until the new version has been installed, the old version of the package needs to be served for any network requests. | Gecko need to still serve the previous package content until the "activate" event for the new ServiceWorker version fires. I.e. until the new version has been installed, the old version of the package needs to be served for any network requests. | ||
♦ '''Issue:''' How do we enable the newly installing serviceworker to load content from the new package version, even though the previous package version is the one pinned in the cache. | ♦ '''Issue:''' How do we enable the newly installing serviceworker to load content from the new package version, even though the previous package version is the one pinned in the cache. | ||
| Line 170: | Line 103: | ||
♦ '''Issue:''' Does CSP allow putting limits on where serviceworkers can be loaded from? We need to restrict ServiceWorkers scopes as well as script-urls to be from inside the package. | ♦ '''Issue:''' Does CSP allow putting limits on where serviceworkers can be loaded from? We need to restrict ServiceWorkers scopes as well as script-urls to be from inside the package. | ||
=== Origins and cookie jars - {{Bug|1153435}} === | |||
The biggest change here is that we should stop always using different cookie jars for different apps. In particular normal unsigned content should always use the same cookie jar no matter where it was loaded. | |||
However signed packages will get their own cookies and IndexedDB data. Content inside a signed package will not share cookies, IndexedDB data, etc with unsigned content from the same domain. It will also not share data with content from other signed packages from the same domain. This is to ensure that unsigned content from the same domain can't read for example sensitive data that the signed content has cached in IndexedDB. And to prevent unsigned content from writing into the localStorage that signed content uses and thereby tricking the signed content into performing unintended actions. | |||
However when pages from inside a signed package makes network requests to other websites, it should still use the normal cookies from those websites. And if a page from a signed package creates an <iframe> containing an unsigned website, then that website will be loaded with its normal cookies and will have access to its normal IndexedDB data. | |||
In other words, each signed package acts like a separate website. They do not act like a separate "world"/"context". | |||
The way that we will implement this is by generalizing the current <tt>appId</tt> and <tt>isInBrowserElement</tt> mechanism. We will introduce a <tt>OriginAttributes</tt> struct which will hold the "cookie jar" that is used for a given web page. We can then write policies for which parts of this struct is inherited into iframes, and which parts do not. The nsIPrincipal interface will contain one of these structs. We will also have functions for serializing this struct to a string, and for parsing such a string back into a struct. | |||
Most code will treat this OriginAttributes struct as an opaque value. When we store data we store, as part of the key, the serialization of the OriginAttributes. | |||
Two pages will only be considered same-origin if they have the same scheme+host+port, but also if all of the values inside the OriginAttributes of their nsIPrincipal have the exact same values. | |||
We will then add a 'signedPkg' member to OriginAttributes. When a page is loaded from inside a signed package, we will read a package-identifier from inside the package and set it in the OriginAttributes of the nsIPrincipal of the page. | |||
However when we | However, when we do the network request for the package itself, this is treated like other network requests to the webserver. I.e. the network request is considered as an unsigned request and so the normal cookies of the webserver is sent. We have to do it this way since when we fetch a signed package the first time, we don't know that the package is signed, and so we use the normal cookie jar for that domain. | ||
The effect of this is that when we are making network requests, these are never affected by package signing. As mentioned above, requests for the package itself are not affected, and requests for pages inside the package don't send any cookies at all since they are simply loaded from the package. | |||
However, when a page from a signed package access the document.cookies API, the cookies returned *do* use the full OriginAttributes. I.e. the document.cookies API is treated like other storage APIs like IndexedDB and localStorage. | |||
♦ '''Issue:''' | ♦ '''Issue:''' Verify with Honza that this is is doable and not complex. It should hopefully be the most natural way to write the cookie code. | ||
If any page does a XHR request to a URL inside a signed package this is treated like any other network request and is permitted. This doesn't expose any user-private information and simply returns content that resides on the server. | |||
== Implementation == | |||
Search for all the open nsec bugs: http://mzl.la/1SLAWum | |||
* P1: Milestone 1 (Sept 4) | |||
* P2: Milestone 2 (Oct 2) | |||
* P3: Feature complete (Nov 2) | |||
* P4: Post-2.5 release | |||
=== Signing - {{Bug|1153420}}=== | |||
<bugzilla> | |||
{ | |||
"blocks": 1153420, | |||
"resolution": "---", | |||
"include_fields": "id, priority, summary, status, assigned_to,resolution,milestone", | |||
"order": "bug_id " | |||
} | |||
</bugzilla> | |||
=== Verifying signatures - {{Bug|1153422}} === | |||
<bugzilla> | |||
{ | |||
"blocks": 1153422, | |||
"include_fields": "id, priority, summary, status, assigned_to,resolution,milestone", | |||
"order": "bug_id" | |||
} | |||
</bugzilla> | |||
=== CSP - {{Bug|1153423}} === | |||
<bugzilla> | |||
{ | |||
"blocks": 1153423, | |||
"include_fields": "id, priority, summary, status, assigned_to,resolution,milestone", | |||
"order": "bug_id" | |||
} | |||
</bugzilla> | |||
=== Process isolation - {{Bug|1153428}} === | |||
<bugzilla> | |||
{ | |||
"blocks": 1153428, | |||
"include_fields": "id, priority, summary, status, assigned_to,resolution,milestone", | |||
"order": "bug_id" | |||
} | |||
</bugzilla> | |||
=== Installing and updating - {{Bug|1153432}} === | |||
<bugzilla> | |||
{ | |||
"blocks": 1153432, | |||
"include_fields": "id, priority, summary, status, assigned_to,resolution,milestone", | |||
"order": "bug_id" | |||
} | |||
</bugzilla> | |||
=== Service Workers - {{Bug|1153433}} === | |||
<bugzilla> | |||
{ | |||
"blocks": 1153433, | |||
"include_fields": "id, priority, summary, status, assigned_to,resolution,milestone", | |||
"order": "bug_id" | |||
} | |||
</bugzilla> | |||
=== Origins and cookie jars - {{Bug|nsec-origins}} === | |||
<bugzilla> | |||
{ | |||
"blocks": "1153435,1163254,1179985", | |||
"include_fields": "id, priority, summary, status, assigned_to,resolution,milestone", | |||
"order": "bug_id" | |||
} | |||
</bugzilla> | |||
== 2.5 Sprint Status == | |||
*[https://wiki.mozilla.org/FirefoxOS/New_security_model/FxOS_2.5_Scrum FxOS 2.5 Scrum Status] | |||
*[https://wiki.mozilla.org/FirefoxOS/New_security_model/2.5_Status 2.5 Status] | |||
== Meeting Note == | |||
*[https://wiki.mozilla.org/FirefoxOS/New_security_model/Meetings Meeting Notes] | |||
== References == | |||
*[https://wiki.mozilla.org/FirefoxOS/New_security_model/Getting_Started_with_Signed_Packages Getting Started with Signed Packages] | |||