GithubHelp home page GithubHelp logo

mozilla / django-csp Goto Github PK

View Code? Open in Web Editor NEW
532.0 26.0 98.0 299 KB

Content Security Policy for Django.

Home Page: https://django-csp.readthedocs.io/en/latest/

License: BSD 3-Clause "New" or "Revised" License

Python 100.00%

django-csp's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-csp's Issues

Decorators cannot be chained

The implementation of the csp_* decorators is such that they can't be chain, this is unfortunate when using class based views with mixins, for example I had something like:

class SomeMixin(View):
    @csp_update(FRAME_SRC=("https://someothersite.com",))
    def get(self, *args, **kwargs):
        return super(SomeMixin, self).get(*args, **kwargs)

class SomeView(SomeMixin, View):
    @csp_update(IMG_SRC=("https://someothersite.com",))
    def get(self, *args, **kwargs):
        return super(SomeView, self).get(*args, **kwargs)

Only the decorator from SomeView was actually applied. This doesn't work because csp_update overrides _csp_update on the response. I'm not sure if this is a design decision or an implementation flaw. I can put up a PR to fix this if it's wanted!

FWIW I'd expect the outer-most decorator to update anything inside of it.

Allow certain URLs to be exempted from 'strict-dynamic'

In a Django application, there are often certain views that are not controlled by the developer (such as the Django admin). For those of us using 'strict-dynamic' in our CSP policies, the only real option currently is to whitelist these URLs (which is very undesirable).

It is also common to have fallback CSP policies for when a user agent doesn't support strict-dynamic. An example policy would be 'strict-dynamic' 'unsafe-inline' 'self' 'http:' 'https'. With this policy, a CSP 3.x compatible browser would ignore unsafe-inline, self, http:, and https: and only obey strict-dynamic while older browsers would ignore strict-dynamic and follow the policy in the other directives.

It would be nice to define some sort of settings.CSP_BYPASS_STRICT_DYNAMIC value that would exclude views from having strict-dynamic applied to their CSP policy while leaving the other fallback directives alone. That way, views that the developer does not control (like Django admin) would have at least some benefit from CSP.

@csp_override decorator

A decorator to set an entire policy for a specific view. Unlike @csp_patch (#11) this would completely override the site-wide policy and only include the directives mentioned. It would also cause policy-uri to be removed and the complete policy to be sent.

Reporting should use the django logging framework

https://docs.djangoproject.com/en/dev/topics/logging/

"A logger can have multiple handlers, and each handler can have a different log level. In this way, it is possible to provide different forms of notification depending on the importance of a message. For example, you could install one handler that forwards ERROR and CRITICAL messages to a paging service, while a second handler logs all messages (including ERROR and CRITICAL messages) to a file for later analysis."

Rather than hardcoded email support, use the standard logging framework

Improve Docs

After updating to the current spec + firefox foibles, we need to write better docs, including a note about the report URL: if it redirects (e.g. because of LocaleURLMiddleware) reports don't get posted.

Allow enforced CSP and Report-Only at the same time

The CSP 1.0 specification allows this explicitly in the sixth paragraph of Section 3.3: http://www.w3.org/TR/CSP/#processing-model
An example is given, too: "For example, if a server operator is using one policy but wishes to experiment with a stricter policy, the server operator can monitor the stricter policy while enforcing the original policy."

This would require bigger changes to the way the middleware works (maybe a flag as a parameter to the decorators? ... something like only_report=True). If this is in scope for the middleware, I am willing to propose an implementation soon.

Code coverage through coveralls?

Something I didn't add into my earlier contribution was coveralls or some similar tool. But I forgot to raise the issue beforehand, so I'm doing it now.

I usually like to look at the code coverage of projects, but since this project lacks it, I was thinking about suggesting adding it. Thoughts?

nonce support

There's a lack of support for this feature.
I think that {% csp_nonce %} in conjunction with some kind of random string generation in headers might do the trick.

What do you think?

Exempt django admin from CSP

The django admin relies on a fair amount of inline Javascript, which CSP breaks. It'd be nice to be able to specify that the admin interface shouldn't use CSP.

support using with urlmiddleware or similar

At the moment there can only be one root level config for all of a project. But it would be nice to define this per app or per url

This is possible with https://urlmiddleware.readthedocs.org/en/latest/ and being able to configure the middleware using arguments

config = {
    'DEFAULT_SRC': ("'self'",),
    'STYLE_SRC': ("'self'", "'unsafe-inline'")
}

middlewarepatterns = mpatterns('',
    middleware(r'^accounts/', CSPMiddeware(config=config)),
)

Feature request: allow use of '{host}' in directives, replaced by `request.get_host()`

Hi,

I want to use CSP with a directive that matches a script path and whatever the current request's host is, instead of having to explicitly list all the possible hosts.

So in your Django settings you could have:

CSP_DEFAULT_SRC = ["'none'"]
CSP_SCRIPT_SRC = ['{host}/app.js']

And at runtime this would be transformed by django-csp, substituting the host name from the request. A request to a server at example.com would generate a response with a header like:

Content-Security-Policy: default-src 'none'; script-src example.com/app.js

While a request to the same application running on localhost:8000 would generate a response with a header like:

Content-Security-Policy: default-src 'none'; script-src localhost:8000/app.js

On Google App Engine, a site is available at potentially any number of different host names, because every version of a deployed application can have its own link. For example if I upload 3 versions called "v1", "v2", and "foo-bar-baz" to an app called "my-app", then all of these would be valid host names:

  • my-app.appspot.com
  • v1-dot-my-app.appspot.com
  • v2-dot-my-app.appspot.com
  • foo-bar-baz-dot-my-app.appspot.com

When writing a CSP directive, this means you cannot know all the host names that the site will use, so while you could use script-src 'self', there's no way of writing a directive that includes a path that covers all host names. E.g. you can't do script-src 'self'/app.js, you need to do script-src my-app.appspot.com/app.js v1-dot-my-app.appspot.com/app.js v2-dot-my-app.appspot.com/app.js foo-bar-baz-dot-my-app.appspot.com/app.js.

In addition, you don't want to use a wildcard like script-src *.appspot.com/app.js because there are many other sites on appspot.com which you don't want to whitelist.

So what would be nice would be a way to substitute the host name from the request, and combine that with the path in a directive. I was thinking to allow a special string in "CSP_*_SRC" settings, {host}, which the middleware would replace with the host name taken from the request.

Another nice thing about this is it makes it easy to support requests to the local development server on "localhost:8000" without needing to add that explicitly to directives.

I have a proof of concept middleware which should help explain what on earth I am on about.

Any interest in having a feature like this in django-csp itself?

Thanks,

David B.

Pip install not updated

Installation with Pip has no recent changes. For example, in from_settings from file utils.py the policies 'base-uri', 'child-src', 'form-action' and 'frame-ancestors' do not exist.

Emit warnings on misspelled keywords

The middleware could parse keywords in debug mode (in development phase) and log Django warnings if keywords were misspelled, such as 'noen' or similar. This mechanism could be generalized to check for the possible source expressions.

However, I believe that missing single quotes cannot be reliably detected. (Maybe there is a host on the network with the domain name none?) I'd like to be wrong here...

Remove last mentions of report processing

There are a few places that still imply the report processing feature exists, even though it was removed in #30.

and a CSP report processing facility to Django.

-> https://github.com/mozilla/django-csp/blame/e5dc7f65b332d73c1ef8361500146e78bd282f88/README.rst#L5-L6

If you are not using the built in report processor

-> https://github.com/mozilla/django-csp/blame/e5dc7f65b332d73c1ef8361500146e78bd282f88/docs/installation.rst#L19-L20

It may also be worth mentioning on the "CSP Violation Reports" docs page that you'll now need to set up some other service for capturing the reports (and perhaps a link to https://developer.mozilla.org/en-US/docs/Web/Security/CSP/Using_CSP_violation_reports), if only since old blog posts about django-csp still mention the report processing feature, so this would make it much clearer.

I'll try to open a PR for this if I get a moment :-)

Allow url when added to a model in the admin.

I have a blogpost app that allows a url link in the admin.
On the frontend this is display in a popup which will display the Content Security Policy directive error.

Note the frontend is a django flatpage using blogpost template tag
to show the post.

Is there a way to allow a url when it is added in the admin for a model ?

Thanks

CSP_*_SRC as tuples do not play well with string decorators

Given the project setting:
CSP_SCRIPT_SRC = ("'self'", "'unsafe-inline'")

and a single view, decorated as:
@csp_update(SCRIPT_SRC="'unsafe-eval'")

yields a TypeError

Traceback:
File "/PATH/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  188.                 response = middleware_method(request, response)
File "/PATH/lib/python2.7/site-packages/csp/middleware.py" in process_response
  43.                                         replace=replace)
File "/PATH/lib/python2.7/site-packages/csp/utils.py" in build_policy
  32.                 config[k] += v

Exception Type: TypeError at /page/
Exception Value: can only concatenate tuple (not "list") to tuple

which is in contrast to the documentation, which says the project settings may be a tuple or list (or None), while the decorators may be are either strings, lists or tuples.

The issue is likely this line, and changing it to (v,) seems to fix it, though I don't know if that could be considered a complete fix.

Add deprecation notice for frame-src

Relates to #50

This needs to be done carefully because since support for child-src is only hitting in FF45 (according to MDN) running both child-src and frame-src will be needed for maximum compatibility.

Sample rate

A high traffic site may generate a vast quantity of reports, especially if there's a violation on a main page. We should include the ability to store only a sample of reports. This sample rate should be recorded when the report is stored so metrics can later take it into account.

Drop report processing

Report processing is overly-complicated and will never really serve enough need will staying sufficiently generic. Drop it. (Per conversations with @dstufft (at least I think it was @dstufft).)

Do something better with CSP reports

Looked at Sentry but that's probably not a good requirement. We should collect and aggregate these and provide a better way of notifying admins than just sending them every report.

Add probably two models, csp.Report and csp.Group, and a couple of settings, including a sample rate.

class Group(Model):
    name = CharField()  # This is probably a combination of the document-uri and the violated-directive, and possibly blocked-uri.
    hash = CharField()  # Or this is where we combine all 3 and the name is just more human-readable.

class Report(Model):
    group = ForeignKey(Group)
    document_uri = CharField()
    blocked_uri = CharField()
    referrer = CharField()
    violated_directive = CharField()
    original_policy = TextField()
    date = DateTimeField()
    sample_rate = FloatField()

    def get_hash(self):
        """Some combination of the above attributes to group these things by."""

And I think we want a couple of signals hooked up:

  • When a violation report comes in, we should try to add it to a group.
  • If the group doesn't exist, create it and email the admins (or another setting of who to email).
  • If the group has a sudden increase in frequency, we probably want to email people about that. Not sure how to calculate that but I'll ask Lonnen.

Then a great thing would be a fancy admin view to let us look at reports and groups in a better way than the default Django admin, but hopefully with no additional requirements over the default admin.

support report-to header and directive

https://www.w3.org/TR/CSP/#directive-report-to
http://wicg.github.io/reporting/#examples

Still in draft and not in caniuse yet: Fyrd/caniuse#2375

This is a separate spec and might belong in a separate package.

A possible config format like the following could add the report-to header and report-to=endpoint-1 to the CSP header:

REPORT_ENDPOINTS = (
    { "url": "https://example.com/reports",
       "group": "endpoint-1",
       "max-age": 10886400 },
     { "url": "https://backup.com/reports",
     "group": "endpoint-1",
     "max-age": 10886400 }
)  # could also be set statically by in the reverse/proxy or webserver config

CSP_REPORT_TO =  "endpoint-1"

We'd also need to define how this behaves with respect to CSP_REPORT_URI.

Trailing slash in urls.py

Trailing slash for report URL is missing. I know this is stylistic issue, but there should at least be a way to have both.

Missing report fields

Current way of saving JSON directly to the database is error prone. If JSON contains any additional field saving of the report fails. For example, for Firefox 16 I had to add those fields:

    source_file = models.CharField(max_length=400, null=True, blank=True)
    line_number = models.IntegerField(null=True, blank=True)
    script_sample = models.TextField(null=True, blank=True)

Include X-WebKit-CSP in response for Safari

Currently, only the final header Content-Security-Policy is sent by django-csp. However, looking at http://caniuse.com/contentsecuritypolicy, it seems many current, and after that many slightly older browsers, still only support webkit's X-WebKit-CSP form.

Although I can understand the argument that we should only be using the final Content-Security-Policy, it would improve security for users to also include X-WebKit-CSP, at least for some time to come. An alternative would be to make this an optional feature.

I'm happy to create a pull request for either option, but wanted to wait to see whether anyone agrees with me.

Make an exception for Django debug view

Django page debug view uses inline JavaScript which does not work if CSP is enabled that page. When Django debug view is displayed instead of original page, CSP should be disabled (or at least allow inline script and other things necessary for Django debug view).

(By Django debug view I have in mind the error page which is displayed on exception or similar.)

example of iframe

can someone please add an example of iframe in a template pointing to yahoo.com or google.com

I want to add an iframe in my django template, pointing to an external application or website, and I am having hard time using django-csp , setting all its headers.

Send the right header

Firefox uses X-Content-Security-Policy, Chrome uses X-Webkit-CSP. We should do some basic UA-detection, and send the right header. And probably set Vary: User-Agent.

Create a new release

Hi all,

We'd like to take advantage of some new functionality added to django-csp. Is there any way that you could create a new release since it seems like there have been numerous changes since the last release?

Thanks! ๐Ÿ˜„

@csp_patch decorator

A decorator to modify the site-wide security policy for a specific view. This would not change any directives not mentioned, except it would cause policy-uri to be removed and the entire policy to be sent.

Fallback for CSP_EXCLUDE_URL_PREFIXES is hardcoded

The default value for CSP_EXCLUDE_URL_PREFIXES is currently hardcoded as ('/admin',)

I think it would make more sense to to do something like:

prefixes = getattr(settings, 'CSP_EXCLUDE_URL_PREFIXES', None)
if prefixes is None:
    try:
        prefixes = (reverse('admin:index'),)
    except NoReverseMatch:
        prefixes = ()

As this guarantees that the path to the standard Django admin (which I'm assuming was the target for /admin in the first place) is correct if used, and doesn't allow any of these words (and whatever variants one might use) to accidentally be CSP free because of no trailing slash (which the Django admin would provide, being conceptually a URL namespace)

CSP configuration decorator for views do not have the 'report-uri' directive.

I am trying CSP in my project. For the entire application i have some config setting and for a selected view i have decorated with a different setting. Here are my observations and where I believe django_csp seems to work oddly.

a) Application views:
i) All the violations outside the whitelist is blocked - As expected
ii) All the violations get reported on each occurence ie if the view is called 10 times with same or different violations each occurence is reported through the report-uri - As expected

b) Decorated view:
I used the django_csp.csp.csp decorator to completely define a new csp setting for the view.
i) All the violations outside the whitelist is blocked - As expected
ii) If i made 10 calls to the URL which is using this view, only in the first instance it gets reported and no subsequent call is reported, even though the content is blocked. Strangely if all these 10 calls have different violations, only the first gets reported - Not expected

I did some research around this behaviour and could see that the 'report-uri' directive is not available in the 'Content-Security-Policy' response header for the subsequent calls Is this expected or an issue ?

Signal on report creation

We should have a signal set up on report creation, like group_created, so that 3rd party code can listen in and do things like send data to Graphite. This should be really easy.

Setting a lazy-evaluated string to CSP_REPORT_URI no longer works

Traceback (most recent call last):
  File "/app/sitepackages/django/core/handlers/base.py", line 235, in get_response
    response = middleware_method(request, response)
  File "/app/sitepackages/csp/middleware.py", line 43, in process_response
    replace=replace)
  File "/app/sitepackages/csp/utils.py", line 58, in build_policy
    policy.append('report-uri %s' % ' '.join(report_uri))
TypeError: sequence item 0: expected string, __proxy__ found

With CSP_REPORT_URI = reverse_lazy('report_csp')

CSP 1.1 directives

This may be a meta issue, but there are a number of new directives in the CSP 1.1 draft that need to be added.

Custom group ID processing

The current Group/Report ID is generated based on fields directly in the report. But, for example, someone might care more about the specific view function than the actual URL, or not at all about which content was blocked.

We should make it easy to override Report.get_identifier without having to monkeypatch. This shouldn't be too hard.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.