Skip to content

Commit

Permalink
Merge pull request #1882 from usdoj-crt/kk/1934/fix-django-csp
Browse files Browse the repository at this point in the history
Update django CSP config for django-csp 4.0
  • Loading branch information
okkays committed Aug 6, 2024
2 parents 7001b80 + 5463d53 commit dadde78
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 75 deletions.
17 changes: 13 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -511,11 +511,11 @@ We use OWASP ZAP for security scans. Here is an [intro to OWASP ZAP](https://res

You can run and pull down the container to use locally:

docker pull owasp/zap2docker-weekly
docker pull softwaresecurityproject/zap-stable

Run OWASP ZAP security scans with docker using the GUI:

docker run -u zap -p 8080:8080 -p 8090:8090 -i owasp/zap2docker-weekly zap-webswing.sh
docker run -u zap -p 8080:8080 -p 8090:8090 -i softwaresecurityproject/zap-stable zap-webswing.sh

you can see the GUI at http://localhost:8080/zap/

Expand All @@ -531,8 +531,17 @@ Then you can stop the container with:

Run OWASP ZAP security scans with docker using the command line. Here is an example of running the baseline, passive scan locally targeting the development site:

docker run -v $(pwd):/zap/wrk/:rw -t owasp/zap2docker-weekly zap-baseline.py \
-t https://crt-portal-django-dev.app.cloud.gov/report/ -c .circleci/zap.conf -z "-config rules.cookie.ignorelist=django_language"
```
docker run -v $(pwd):/zap/wrk/:rw -t softwaresecurityproject/zap-stable zap-baseline.py -t https://crt-portal-django-dev.app.cloud.gov/report/ -c .circleci/zap.conf --autooff -z "-config rules.cookie.ignorelist=django_language"
```

And here's targeting a local devserver (note that "--net=host" allows it to connect to reach the devserver at localhost):

Note that the devserver serves Django 404 pages when DEBUG=True is enabled, and these pages will fail some security (such as CSP).

```
docker run --net=host -v $(pwd):/zap/wrk/:rw -t softwaresecurityproject/zap-stable zap-baseline.py -t http://localhost:8000/report/ -c .circleci/zap.conf --autooff -z "-config rules.cookie.ignorelist=django_language"
```

That will produce a report locally that you can view in your browser. It will give you a list of things that you should check. Sometimes there are things at the low or informational level that are false positives or are not worth the trade-offs to implement. The report will take a minute or two to generate.

Expand Down
151 changes: 80 additions & 71 deletions crt_portal/crt_portal/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import django.conf.locale
from django.utils.log import DEFAULT_LOGGING
from django.utils.translation import gettext_lazy as _
from csp.constants import SELF, NONCE


# Are we in a test environment?
Expand Down Expand Up @@ -100,6 +101,7 @@
'compressor_toolkit',
'storages',
'formtools',
'csp',
# 'django_auth_adfs' in production only
'crequest',
'rest_framework',
Expand All @@ -123,6 +125,7 @@
'django.middleware.locale.LocaleMiddleware',
'crt_portal.locale_middleware.LanguageParamMiddleware',
'crequest.middleware.CrequestMiddleware',
'csp.middleware.CSPMiddleware',
]


Expand Down Expand Up @@ -390,9 +393,8 @@
else:
env_csp_sources = []

MIDDLEWARE.append('csp.middleware.CSPMiddleware')
allowed_sources = (
"'self'",
SELF,
'www.civilrights.justice.gov',
'civilrights.justice.gov',
'https://touchpoints.app.cloud.gov',
Expand All @@ -414,76 +416,83 @@
X_FRAME_OPTIONS = "DENY"
# If this is set to True, client-side JavaScript will not be able to access the language cookie.
SESSION_COOKIE_HTTPONLY = True
# see settings options https://django-csp.readthedocs.io/en/latest/configuration.html#configuration-chapter
CSP_DEFAULT_SRC = allowed_sources
# See https://django-csp.readthedocs.io/en/latest/configuration.html
# Note we are on 4.0+

CONTENT_SECURITY_POLICY = {
'EXCLUDE_URL_PREFIXES': ('/admin'), # Allow admin panel functionality (which is trusted content that uses inline sources)
'DIRECTIVES': {
'default-src': allowed_sources,
'script-src': (
SELF,
NONCE,
'www.civilrights.justice.gov',
'civilrights.justice.gov',
'https://dap.digitalgov.gov',
'https://www.google-analytics.com',
'https://stats.g.doubleclick.net',
'https://touchpoints.app.cloud.gov',
'https://www.googletagmanager.com/',
'https://cdnjs.cloudflare.com/',
'https://challenges.cloudflare.com/',
'https://www.google.com/',
'a.tile.openstreetmap.org', # For loading image tiles in map data
'b.tile.openstreetmap.org', # For loading image tiles in map data
'c.tile.openstreetmap.org', # For loading image tiles in map data
*env_csp_sources,
),
'connect-src': (
SELF,
'www.civilrights.justice.gov',
'civilrights.justice.gov',
'https://dap.digitalgov.gov',
'https://www.google-analytics.com',
'https://stats.g.doubleclick.net',
'https://touchpoints.app.cloud.gov',
'https://www.googletagmanager.com/',
'https://cdnjs.cloudflare.com/',
'https://challenges.cloudflare.com/',
'https://www.google.com/',
'a.tile.openstreetmap.org', # For loading image tiles in map data
'b.tile.openstreetmap.org', # For loading image tiles in map data
'c.tile.openstreetmap.org', # For loading image tiles in map data
*env_csp_sources,
),
'img-src': (
*allowed_sources,
'data:',
'a.tile.openstreetmap.org', # For loading image tiles in map data
'b.tile.openstreetmap.org', # For loading image tiles in map data
'c.tile.openstreetmap.org', # For loading image tiles in map data
),
'media-src': allowed_sources,
'frame-src': allowed_sources,
'worker-src': (
*allowed_sources,
'blob:'
),
'frame-ancestors': allowed_sources,
'style-src': (
SELF,
'www.civilrights.justice.gov',
'civilrights.justice.gov',
"'unsafe-inline'",
'https://fonts.googleapis.com',
*env_csp_sources,
),
'font-src': (
SELF,
'www.civilrights.justice.gov',
'civilrights.justice.gov',
"'unsafe-inline'",
'https://fonts.gstatic.com',
*env_csp_sources,
),
}
}

SESSION_COOKIE_SAMESITE = 'Lax'
CSP_SCRIPT_SRC = (
"'self'",
'www.civilrights.justice.gov',
'civilrights.justice.gov',
'https://dap.digitalgov.gov',
'https://www.google-analytics.com',
'https://stats.g.doubleclick.net',
'https://touchpoints.app.cloud.gov',
'https://www.googletagmanager.com/',
'https://cdnjs.cloudflare.com/',
'https://challenges.cloudflare.com/',
'https://www.google.com/',
'a.tile.openstreetmap.org', # For loading image tiles in map data
'b.tile.openstreetmap.org', # For loading image tiles in map data
'c.tile.openstreetmap.org', # For loading image tiles in map data
*env_csp_sources,
)
CSP_CONNECT_SRC = (
"'self'",
'www.civilrights.justice.gov',
'civilrights.justice.gov',
'https://dap.digitalgov.gov',
'https://www.google-analytics.com',
'https://stats.g.doubleclick.net',
'https://touchpoints.app.cloud.gov',
'https://www.googletagmanager.com/',
'https://cdnjs.cloudflare.com/',
'https://challenges.cloudflare.com/',
'https://www.google.com/',
'a.tile.openstreetmap.org', # For loading image tiles in map data
'b.tile.openstreetmap.org', # For loading image tiles in map data
'c.tile.openstreetmap.org', # For loading image tiles in map data
*env_csp_sources,
)
CSP_IMG_SRC = (
*allowed_sources,
'data:',
'a.tile.openstreetmap.org', # For loading image tiles in map data
'b.tile.openstreetmap.org', # For loading image tiles in map data
'c.tile.openstreetmap.org', # For loading image tiles in map data
)
CSP_MEDIA_SRC = allowed_sources
CSP_FRAME_SRC = allowed_sources
CSP_WORKER_SRC = (
*allowed_sources,
'blob:'
)
CSP_FRAME_ANCESTORS = allowed_sources
CSP_STYLE_SRC = (
"'self'",
'www.civilrights.justice.gov',
'civilrights.justice.gov',
"'unsafe-inline'",
'https://fonts.googleapis.com',
*env_csp_sources,
)
CSP_FONT_SRC = (
"'self'",
'www.civilrights.justice.gov',
'civilrights.justice.gov',
"'unsafe-inline'",
'https://fonts.gstatic.com',
*env_csp_sources,
)
CSP_INCLUDE_NONCE_IN = ['script-src']
# Allow admin panel functionality (which is trusted content that uses inline sources):
CSP_EXCLUDE_URL_PREFIXES = ('/admin')


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
Expand Down

0 comments on commit dadde78

Please sign in to comment.