FirefoxOS/New security model/Packaging
Privileged Content
This page details implementation of signed privileged content for FxOS. The basic properties of privileged content is that:
- they are enumerated in a manifest
- signed to prevent modification
- loaded into a unique origin which is granted special permissions(separate from other web content on the same domain)
Background: Packaged Content
bug 1036275 introduced packaged HTML content to Firefox. Packages must be served with "Content-Type: application/package" mime type.
An example of a regular package is shown below:
--gc0pJq0M:08jU534c0p
Content-Location: /index.html
Content-Type: text/html
<html>
<head>
<script src="scripts/app.js"></script>
...
</head>
...
</html>
--gc0pJq0M:08jU534c0p
Content-Location: /scripts/app.js
Content-Type: text/javascript
module Math from '/scripts/helpers/math.js';
...
--gc0pJq0M:08jU534c0p
Content-Location: /scripts/helpers/math.js
Content-Type: text/javascript
export function sum(nums) { ... }
...
--gc0pJq0M:08jU534c0p--
Privileged Packages
The Signed Manifest
A packaged is denoted by setting two packages headers. The first points to the manifest for the package (contains a list of files and digests of these files) and a signature of manifest content in JWS format:
manifest: /someapp.webmanifest manifest-signature: MRjdkly.... (Base64 JWS Signature over manifest content)
Package headers are specified by the w3c format and are headers which are sent inside the package, but prior to the first data part. Modifiying the above example, we get something like:
manifest: /someapp.webmanifest
manifest-signature: MRjdkly.... (Base64 JWS Signature)
--gc0pJq0M:08jU534c0p
Content-Location: /someapp.webmanifest
Content-Type: application/manifest
{
"name": "My App",
"description":"A great app!"
...
App Manifest Extensions
We add a resources section to the app manifest which enumerates content which needs to have integrity check.
{
"name": "My App",
"scope": "/",
"start_url": "/index.html",
"permissions": [
{
"systemXHR": {
"description": "Needed to download stuff"
},
"devicestorage:pictures": {
"description": "Need to load pictures"
}
}
],
"resources": [
{
"src": "/index.html",
"integrity": "sha256-kass...eoirW-e"
},
{
"src": "/page2.html",
"integrity": "sha256-kasguie...ngeW-e"
},
{
"src": "/script.js",
"integrity": "sha256-agjdia2...wgda"
},
{
"src": "https://libraries.com/library.js",
"integrity": "sha256-geijfi...ae3W"
}
]
}
- Question: Do ALL resources need to live INSIDE the package? If we support arbitrary loads this would allow support for non-packaged privileged apps too, but I don't know what complexity this would add to the loading/verification process.
Processing Model
The normal loading process is:
- Gecko loads the manifest
- Gecko checks the signature of the manifest
- If signature verifies, a privileged child process is launched
- Web page is loaded as a normal web page inside this privileged process
- Although the _process_ is privileged, permission are restricted until verification is complete
The verification process is as follows:
- After the manifest signature checks out, gecko starts downloading all files enumerated in the manifest
- Each resource has is checked against a digest from the manifest
- If the integrity check passes, the resource is cached
- Once all the resources have been cached, only then is content considered privileged and permissions available to it
To update a privileged app:
2.2. Update
- GET manifest, If-Modified-Since
- Look for what files have changed, by addition/deletion/integrity
- Update changed files
Verification failures are generally treated as network failures. See "Error Recovery" below for the approach to dealing with loading errors and partially loaded apps.
Security Restrictions
- Only signed scripts may be loaded
- Only signed entry points can be navigated to
- All privileged content must be served over a secure network connection.
- No framing privileged content
- Resources enumerated in the manifest must have their integrity checked prior to loading
Note:
- Not all HTML must be signed. There is little value in making this a firm requirement since it isn't possible to prevent dynamic HTML changes (this risk is unchanged from previous packaged approach)
- The resources which MUST be signed are:
- scripts (CSP enforces that only signed scripts can be loaded in the origin)
- entry points (entry point restrictions enforce that only signed entry points can be navigated to)
- Developers should be encouraged to sign all static resources to prevent tampering
Loading an app
When an app-manifest is encountered, while the page is loaded as normal, additional steps are initiated in parallel. Two main processes are started: - populating cache with app enumerated resources - verification of signed resources and granting of permissions
Cache population
TODO (initial thoughts only)
- For all signed resources we should only cache them if the integrity check passes
- We want to somehow keep track of the resources that have been integrity checked (if we adhere to the previous rule, can we assume that if cached, then the resource passed the integrity check?
Verification of resources & Permission Granting
TODO
- We only want to grant permissions after ALL resources in the manifest have been verified
- But we want to launch the process earlier to speed up performance
- We'll need some kind of verifier worker that keeps track of loading, and link this to the PermissionManager (and apps manager, at least while we have an apps manager)
- The delay here shouldn't be a problem for most privileged APIs, since MOST permissions are user granted, and therefore asynchronous by their nature. There will be a some complexity though as there are a number of APIs which are st to null if a permission is not present when the window(?) is created. We are going to need to make ALL permissions grant-able at any stage.