Re: [w3c/webcomponents] HTML, CSS, and JSON modules shouldn't solely rely on MIME type to change parsing behavior (#839)

> What if someone was not even aware of CSP? Or someone had limitation on server configurations they can change? Again, most websites don't deploy CSP correctly

This is still something I say is kinda weak. Ideally new features should be developed in tandem with their available security policies which have strong defaults.

The fact CSP is misused is because of complexities with the policies. Things like hashes and stuff are difficult to set up and get right. I feel that this could be resolved by having stricter defaults (e.g. not allowing JSON modules by default) and safer configuration that doesn't encourage unsecure things.

> Or someone had limitation on server configurations they can change?

To address this point specifically, a strict default ensures no JSON modules can be used at all so the upgrade thing isn't a concern. Instead the concern becomes allowing JSON modules in such an environment where configuration is not allowed.

>  The idea of using file extension has been rejected multiple times: see #839 (comment) for example.
> Please be mindful of others' time and read the whole thread before making a proposal that has known issues.

I'm not saying use file extensions on the web, I'm saying people use file extensions, they will use their tools to convert `import foo from './foo.json';` into `import foo from './foo.json' as json` (or whatever syntax) regardless.

So if they're going to do this mapping automatically anyway why not allow them to configure it in the browser for their sites rather than adding pre-processing steps.

This is what my proposal does, it doesn't make browsers understand extensions. Instead it gives a way to make assertions about expected properties of resources (just content-type above but I think more is necessary for a concrete proposal) and means that people can be confident that content received is what is expected.

Note that my proposal is wider reaching than just imports, but this because the issue that imports have is that a resource might be served with an unexpected type. This is widely applicable not just to imports but to all fetch sites.

> For example, a service I created a while ago relies on JSON files being served by Apache inside a special directory. This directory is the only writable directory that's also publicly accessible in the entire service. All files in this directory are JSON and therefore are not executable (either in client or server side). If we started loading JSON files from this directory in the said service as JSON modules, it would be a strict security regression because now those JSON files could execute scripts if there were some bugs which allowed attackers to write to this directory.

My proposal still wouldn't allow this, but maybe I'm not being concrete enough to make that clear. I'll try to create a tangible algorithm that would be executed in relation to these policies such that the only way `.json` could be executed as a script is if the policy explicitly allowed it.

---

**More concrete proposal:**

Before JSON modules are introduced a new security policy is introduced that allows configuring both allowed content-type and destination of particular resources.

An example policy might look something like:

```
Content-Security-Policy:
  content-restrictions
  api/**/* content-type application/json; destination fetch,
  *.worker.js content-type text/javascript; destination worker
  *.js content-type text/javascript; destination script-like,
  */ content-type text/html; destination document,
  **/*.html text/html; destination script document,
  **/*.json content-type application/json; destination fetch script,
  https://weather.tld/api.json content-type application/json; destination fetch script
```

(Q?: Should `module` be a separate destination to `script`?)

Some examples of applying this policy to some files:

url | response content type | destination | first matched policy | blocked | blocked reason
--------|-------|------|---------|-------|----
foo.json | application/json | fetch | **/*.json | no | -
foo.json | text/javascript | fetch | **/*.json | yes | Content type isn't `application/json`
foo.json | application/json | script | **/*.json | no | -
foo.json | appplication/json | document | **/*.json | yes | Destination is not `fetch` or `script`
|||||
script.js | text/javascript | script  | **/*.js | no | -
script.js | text/javascript | worker | **/*.js | no | -
script.js | text/html | document | **/*.js | yes | wrong content type and destination
https://weather.tld/api.json | application/json | script | https://weather.tld/api.json | no | -
https://weather.tld/api/json | text/javascript | script | yes | content type is unexpected
```

(Q?: 

If a resource is not in the policy then it is rejected. This ensures the web can add new targets and resources without large concern.

**Json Modules:**

Now in order for this to work for JSON modules we should have a default policy that rejects all resources entering the `script` destination that not have content type `text/javscript`.

For example a web-compatible default policy might roughly be:

```
Content-Security-Policy:
  content-restrictions
    // Restricts script to Javascript modules only across all domains
    *:*/**/* content-type text/javascript, destination script-like
    // Anything else is allowed currently, as new features are added
    // we would want to strengthen the default policy across all domains
    *:*
```

(Q?: Allow wasm/html modules in such a default policy?)
(Q?: Is the status quo more strict?)

**New Features:**

When new features (not just JSON modules) are added that add/use new destinations/content-types(/(Q?: Other metadata?)) they could be added to a default policy.

**Footnote:**

Hopefully this a bit more concrete than the vague hand-wavy things from above. It's still by no means a complete proposal and has some problems of its own that would need to be worked out. However I think it solves the problems of JSON modules without introducing new syntax, preventing use cases like `import foo from './foo';` (where `./foo` is resolved to `.wasm` or `.js` on server side when it doesn't matter), non-redundancy with node.js, consistency with CSP and improves the complexities of CSP for both JSON modules and other use cases.

---

**Alternative proposal:**

This is similar to above but it might be worth super-ceding `Content-Security-Policy` with something similar to the above proposal but more consistent and unifies things more e.g. something like import maps but for security.

<details>
  <summary>Sub strawman</summary>
  
  ```html
  <script type="security-policy">
    {
      "patterns": [
        {
          "match": ["**/*.json", "https://weather.tld/*.json"],
          "allowed-content-type": ["application/json"],
          "allowed-destination": ["fetch", "script"]
        },
        {
          "match": ["**/*.js"],
          "allowed-content-type": ["text/javascript"],
          "allowed-destination": ["script-like"],
        },
        {
          "match": ["**/*.webcomponent"],
          "allowed-content-type": ["text/html", "text/javascript"],
          "allowed-destination": ["script"]
        },
        {
          "match": ["https://www.third-party.com/component.js"],
          "allowed-content-type": ["text/javascript"], 
          "integrity": "asdf1234"
        }
      ]
    }
  </script>
  ```
</details>

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/w3c/webcomponents/issues/839#issuecomment-555358837

Received on Tuesday, 19 November 2019 06:44:35 UTC