papandreou / seespee

Create a Content-Security-Policy for a website based on the statically detectable relations
BSD 3-Clause "New" or "Revised" License
75 stars 4 forks source link

Support for CSP 3 #96

Closed siMs0n closed 1 year ago

siMs0n commented 1 year ago

This seems like a really interesting tool to add to our pipeline to test our CSP with. I notice it doesn't seem to support CSP 3, with for example the strict-dynamic keyword. It would also be interesting if it would support require-trusted-types-for.

Do you have any plans to add support for this?

papandreou commented 1 year ago

CSP 3 is still a working draft, but I guess we can look into adding support for the parts of it that have been implemented in browsers. How are you using those keywords/directives?

siMs0n commented 1 year ago

We've followed the guides for implementing a strict CSP policy and a trusted types policy. It resulted in a policy that is very similar to the sample safe policy in Google's CSP Evaluator, although we have a Single Page Application so we use a hash-based policy.

papandreou commented 1 year ago

Right, I guess adopting those would mostly be a matter of outputting a policy that's as safe as possible. I don't think they would require a lot of changes to the logic -- the main job would still be to hash inline scripts/stylesheets and track down origins by following relations.

Note that those directives are already "supported" with the --include switch and with a meta tag:

$ seespee --include "default-src 'none'; script-src 'strict-dynamic'; require-trusted-types-for 'script'" page-with-inline-script.html 
Content-Security-Policy:
  default-src 'none';
  script-src 'sha256-WOdSzz11/3cpqOdrm89LBL2UPwEU9EhbDtMy2OciEhs=' 'strict-dynamic'
    'unsafe-inline';
  require-trusted-types-for 'script';
siMs0n commented 1 year ago

Okay thanks! I'm looking to use the --validate flag in CI to verify our build. Tell me if I can help with something.

papandreou commented 1 year ago

Ah, I thought you were talking about the generation of CSPs, not the validation mode. What should the validation mode specifically do to meet your needs wrt. CSP3? Bear in mind that it has to be statically verifiable, as seespee doesn't use a headless browser, and doesn't run your JS. I guess require-sri-for would be easy to validate, but I don't know about the other ones you mention.

siMs0n commented 1 year ago

I think strict-dynamic could be checked by validating the hashes or the nonces in the CSP against what scripts are present in the HTML. Trusted Types would be much harder, I'm not sure how it can be validated except warning for syntax errors in the CSP

papandreou commented 1 year ago

Hmm, aren't the hashes already validated?

papandreou commented 1 year ago

If I have badpage.html with:

<!DOCTYPE html>
<html>
    <head>
      <meta http-equiv="Content-Security-Policy" content="script-src 'strict-dynamic' 'self'">
    </head>
    <body>
      <script>alert('foo');</script>
    </body>
</html>

Then it does complain about the missing hash:

ARMYELITENEAR:seespee andreas.lind$ ./lib/cli.js --validate badpage.html 
 ✘ ERROR: Validation failed: The Content-Security-Policy does not whitelist the following resources:
            script-src 'sha256-WOdSzz11/3cpqOdrm89LBL2UPwEU9EhbDtMy2OciEhs=';
              inline JavaScript in badpage.html
Content-Security-Policy:
  script-src 'strict-dynamic' 'self';

But it doesn't complain if I add script-src 'unsafe-inline' as well (the CSP 1 fallback strategy) unless I also add at least one hash to it. Maybe the action would be to have the presence of 'strict-dynamic' put it into a mode where hashes or nonces are required, effectively ignoring 'unsafe-inline' like it does when there's at least one hash or nonce 😅

siMs0n commented 1 year ago

Oh okay! I think that sounds reasonable :) So then it's just a matter of doing that update and update the README surrounding CSP 3 a bit?

papandreou commented 1 year ago

Yeah, at least as far as that one thing is concerned. Should be fine to take the CSP 3 stuff one step at a time 😇

papandreou commented 1 year ago

Fixed in 3.1.0.

papandreou commented 1 year ago

Let's open separate issues if we come up with ideas for how to handle the other CSP3 directives in validation and generation mode.