Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use nonce-based Content Security Policy #8598

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cfgov/agreements/jinja2/agreements/base_agreements.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
{{ super() }}
<script src="{{ static( 'agreements/js/jquery-3.5.1.min.js' ) }}"></script>
<script src="{{ static( 'agreements/js/chosen.jquery.js' ) }}"></script>
<script>
<script nonce="{{request.csp_nonce}}">
$(document).ready(function () {
$("#issuer_select").chosen();
$("#issuer_select").chosen().change( function(e){
Expand Down
4 changes: 3 additions & 1 deletion cfgov/ask_cfpb/jinja2/ask-cfpb/landing-page.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,7 @@

{% block javascript scoped %}
{{ super() }}
<script src="{{ static('apps/ask-cfpb/js/main.js') }}"></script>
<script nonce="{{request.csp_nonce}}">
jsl(["{{ static('apps/ask-cfpb/js/main.js') }}"])
</script>
{% endblock javascript %}
110 changes: 11 additions & 99 deletions cfgov/cfgov/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -463,117 +463,29 @@
"HOSTNAMES": environment_json("CLOUDFRONT_PURGE_HOSTNAMES")
}

# CSP Allowlists
# CSP
#
# Please note: Changing these lists will change the value of the
# Content-Security-Policy header Django returns. Django does NOT include
# header values when calculating the response hash returned in the ETag
# header.
# Our Akamai cache uses the ETag header to know whether a cached copy of a
# page has been updated after it expires or after an invalidation purge.
#
# Together, this means that any changes to these CSP values WILL NOT BE
# RETURNED by Akamai until a page's non-header content changes, or a
# delete-purge is performed.
# See https://web.dev/articles/strict-csp

# These specify what is allowed in <script> tags
CSP_SCRIPT_SRC = (
"'self'",
"'strict-dynamic'",
"https:",
"'unsafe-inline'",
"'unsafe-eval'",
"*.consumerfinance.gov",
"dap.digitalgov.gov",
"*.googleanalytics.com",
"*.google-analytics.com",
"*.googletagmanager.com",
"*.googleoptimize.com",
"optimize.google.com",
"api.mapbox.com",
"js-agent.newrelic.com",
"bam.nr-data.net",
"gov-bam.nr-data.net",
"*.youtube.com",
"*.ytimg.com",
"*.mouseflow.com",
"*.geo.census.gov",
"about:",
"www.federalregister.gov",
"*.qualtrics.com",
"www.ssa.gov/accessibility/andi/",
"ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js", # needed for ANDI accessibility tool
)

# These specify valid sources of CSS code
CSP_STYLE_SRC = (
"'self'",
"'unsafe-inline'",
"*.consumerfinance.gov",
"*.googletagmanager.com",
"optimize.google.com",
"fonts.googleapis.com",
"api.mapbox.com",
"www.ssa.gov/accessibility/andi/",
"https:",
)

# These specify valid image sources
CSP_IMG_SRC = (
"'self'",
"*.consumerfinance.gov",
"www.ecfr.gov",
"s3.amazonaws.com",
"img.youtube.com",
"*.google-analytics.com",
"*.googletagmanager.com",
"optimize.google.com",
"api.mapbox.com",
"*.tiles.mapbox.com",
"blob:",
"*",
"data:",
"www.gravatar.com",
"*.qualtrics.com",
"*.mouseflow.com",
"i.ytimg.com",
"www.ssa.gov/accessibility/andi/",
)

# These specify what URL's we allow to appear in frames/iframes
CSP_FRAME_SRC = (
"'self'",
"*.consumerfinance.gov",
"*.googletagmanager.com",
"*.google-analytics.com",
"*.googleoptimize.com",
"optimize.google.com",
"www.youtube.com",
"*.qualtrics.com",
"mailto:",
)

# These specify where we allow fonts to come from
CSP_FONT_SRC = ("'self'", "fonts.gstatic.com")

# These specify hosts we can make (potentially) cross-domain AJAX requests to
CSP_CONNECT_SRC = (
"'self'",
"*.consumerfinance.gov",
"*.google-analytics.com",
"*.googleoptimize.com",
"*.tiles.mapbox.com",
"api.mapbox.com",
"bam.nr-data.net",
"gov-bam.nr-data.net",
"s3.amazonaws.com",
"public.govdelivery.com",
"n2.mouseflow.com",
"*.qualtrics.com",
"raw.githubusercontent.com",
)

# These specify valid media sources (e.g., MP3 files)
CSP_MEDIA_SRC = (
"'self'",
"*.consumerfinance.gov",
"blob:",
)
CSP_OBJECT_SRC = ("'none'")
CSP_BASE_URI = ("'none'")
CSP_INCLUDE_NONCE_IN = ["script-src"]
CSP_EXCLUDE_URL_PREFIXES = ("/admin")

# FEATURE FLAGS
# Flags can be declared here with an empty list, which will evaluate as false
Expand Down
2 changes: 0 additions & 2 deletions cfgov/cfgov/settings/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,6 @@
f"//{_placeholder_domain}/{{width}}x{{height}}/addc91/1fa040"
)

CSP_IMG_SRC += (_placeholder_domain,)

# Add django-cprofile-middleware to enable lightweight local profiling.
# The middleware's profiling is only available if DEBUG=True
MIDDLEWARE += ("django_cprofile_middleware.middleware.ProfilerMiddleware",)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ <h1>{{ page.page_header }}</h1>

{% block javascript scoped %}
{{ super() }}
<script>
<script nonce="{{request.csp_nonce}}">
jsl(['{{ static("apps/filing-instruction-guide/js/fig-init.js") }}']);
</script>
{% endblock javascript %}
4 changes: 2 additions & 2 deletions cfgov/housing_counselor/jinja2/housing_counselor/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ <h2 class="h4">
{% block javascript %}
{{ super() }}

<script>
<script nonce="{{request.csp_nonce}}">
// Store backend settings to pass to front-end scripts.
window.cfpbHudSettings = {};
window.cfpbHudSettings.hud_data = {};
Expand All @@ -325,7 +325,7 @@ <h2 class="h4">
window.cfpbHudSettings.mapbox_access_token = "{{ mapbox_access_token }}";
</script>

<script>
<script nonce="{{request.csp_nonce}}">
jsl(['{{ static("apps/find-a-housing-counselor/js/common.js") }}']);
</script>
{% endblock javascript %}
2 changes: 1 addition & 1 deletion cfgov/jinja2/ccdb-complaint/ccdb-search.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

{% block javascript scoped %}
{{ super() }}
<script>
<script nonce="{{request.csp_nonce}}">
jsl([
'https://files.consumerfinance.gov/ccdb/metadata.js',
'{{ static("apps/ccdb-search/js/main.js") }}'
Expand Down
2 changes: 1 addition & 1 deletion cfgov/jinja2/owning-a-home/explore-rates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ <h3 class="subhead">About our data source for this tool</h3>

{% block javascript scoped %}
{{ super() }}
<script>
<script nonce="{{request.csp_nonce}}">
jsl([
'{{ static("apps/owning-a-home/js/common.js") }}',
'{{ static("apps/owning-a-home/js/explore-rates/index.js") }}'
Expand Down
2 changes: 1 addition & 1 deletion cfgov/jinja2/rural-or-underserved/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

{% block javascript scoped %}
{{ super() }}
<script>
<script nonce="{{request.csp_nonce}}">
window.cfpbMapboxAccessToken = '{{ mapbox_access_token }}';
jsl(['{{ static("apps/rural-or-underserved-tool/js/common.js") }}']);
</script>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ <h1 style="display:none">Your financial path to graduation</h1>

{% block javascript scoped %}
{{ super() }}
<script>
<script nonce="{{request.csp_nonce}}">
jsl(['{{ static("apps/paying-for-college/js/college-costs.js") }}']);
</script>
{% endblock javascript %}
Original file line number Diff line number Diff line change
Expand Up @@ -3332,7 +3332,7 @@ <h2 class="step__heading">

{% block javascript scoped %}
{{ super() }}
<script>
<script nonce="{{request.csp_nonce}}">
jsl(['{{ static("apps/paying-for-college/js/disclosures/index.js") }}']);
</script>
{% endblock javascript %}
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ <h2 class="m-slug-header__heading">

{% block javascript scoped %}
{{ super() }}
<script>
<script nonce="{{request.csp_nonce}}">
jsl(['{{ static("js/routes/data-research/prepaid-accounts/search-agreements/index.js") }}']);
</script>
{% endblock javascript %}
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ <h3 class="h4 u-mb5">Search within</h3>

{% block javascript %}
{{ super() }}
<script>
<script nonce="{{request.csp_nonce}}">
jsl(['{{ static("apps/prepaid-agreements/js/common.js") }}']);
</script>
{% endblock javascript %}
2 changes: 1 addition & 1 deletion cfgov/privacy/jinja2/privacy/disclosure-consent-form.html
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ <h2>Consent for disclosure of records</h2>

{% block javascript %}
{{ super() }}
<script>
<script nonce="{{request.csp_nonce}}">
jsl(['{{ static("js/routes/on-demand/privacy-forms.js") }}']);
</script>
{% endblock javascript %}
2 changes: 1 addition & 1 deletion cfgov/privacy/jinja2/privacy/records-access-form.html
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ <h2>Consent for release of records</h2>

{% block javascript %}
{{ super() }}
<script>
<script nonce="{{request.csp_nonce}}">
jsl(['{{ static("js/routes/on-demand/privacy-forms.js") }}']);
</script>
{% endblock javascript %}
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ <h1>{{ page.title }}</h1>

{% block javascript scoped %}
{{ super() }}
<script>
<script nonce="{{request.csp_nonce}}">
jsl([
'{{ static("apps/regulations3k/js/index.js") }}',
'{{ static("apps/regulations3k/js/permalinks.js") }}'
Expand Down
2 changes: 1 addition & 1 deletion cfgov/regulations3k/jinja2/regulations3k/landing-page.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@

{% block javascript scoped %}
{{ super() }}
<script>
<script nonce="{{request.csp_nonce}}">
jsl([
'{{ static("apps/regulations3k/js/index.js") }}',
'{{ static("apps/regulations3k/js/recent-notices.js") }}'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

{% block javascript scoped %}
{{ super() }}
<script>
<script nonce="{{request.csp_nonce}}">
jsl(['{{ static("js/routes/on-demand/secondary-nav.js") }}']);
</script>
{% endblock javascript %}
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ <h3>Refine results</h3>

{% block javascript scoped %}
{{ super() }}
<script>
<script nonce="{{request.csp_nonce}}">
jsl([
'{{ static("apps/regulations3k/js/index.js") }}'
{%- if page.results.search_query -%}
Expand Down
2 changes: 1 addition & 1 deletion cfgov/retirement_api/jinja2/retirement_api/claiming.html
Original file line number Diff line number Diff line change
Expand Up @@ -988,7 +988,7 @@ <h5>{{ _("Legal Disclaimer:") }}</h5>

{% block javascript scoped %}
{{ super() }}
<script>
<script nonce="{{request.csp_nonce}}">
jsl(['{{ static("apps/retirement/js/index.js") }}']);
</script>
{% endblock javascript %}
5 changes: 0 additions & 5 deletions cfgov/v1/jinja2/v1/layouts/404.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,3 @@ <h1>404: Page not found</h1>
</p>
</div>
{% endblock %}

{% block javascript %}
{# Include site-wide JavaScript. #}
<script type='text/javascript' src="{{ static('js/routes/common.js') }}"></script>
{% endblock javascript %}
5 changes: 0 additions & 5 deletions cfgov/v1/jinja2/v1/layouts/500.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,3 @@ <h1>500: Server error</h1>
</p>
</div>
{% endblock %}

{% block javascript %}
{# Include site-wide JavaScript. #}
<script type='text/javascript' src="{{ static('js/routes/common.js') }}"></script>
{% endblock javascript %}
14 changes: 7 additions & 7 deletions cfgov/v1/jinja2/v1/layouts/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@
href="{{ static('fonts/627fbb5a-3bae-4cd9-b617-2f923e29d55e.woff2') }}"
as="font"
type="font/woff2" crossorigin>
<link rel="preload" href="{{ static('js/routes/common.js') }}" as="script">
<link rel="preload" nonce="{{request.csp_nonce}}" href="{{ static('js/routes/common.js') }}" as="script">

{# Preconnecting comes from the 3rd best practice in
https://developer.mozilla.org/en-US/docs/Web/Performance/dns-prefetch#best_practices #}
Expand Down Expand Up @@ -184,7 +184,7 @@
{# Begin Google Optimize #}
{# Optimize anti-flicker snippet. #}
<style>.async-hide { opacity: 0 !important} </style>
<script>(function(a,s,y,n,c,h,i,d,e){s.className+=' '+y;h.start=1*new Date;
<script nonce="{{request.csp_nonce}}">(function(a,s,y,n,c,h,i,d,e){s.className+=' '+y;h.start=1*new Date;
h.end=i=function(){s.className=s.className.replace(RegExp(' ?'+y),'')};
(a[n]=a[n]||[]).hide=h;setTimeout(function(){i();h.end=null},c);h.timeout=c;
})(window,document.documentElement,'async-hide','dataLayer',4000,
Expand All @@ -197,7 +197,7 @@
{% endif %}

{# Begin Google Tag Manager #}
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
<script nonce="{{request.csp_nonce}}">(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;
Expand All @@ -209,7 +209,7 @@
{% endif -%}

{% block javascript_loader %}
<script>
<script nonce="{{request.csp_nonce}}">
{# Minified dynamic JavaScript loader that injects a script tag in the head of the page. #}
function jsl(a){
if(window.fetch){
Expand All @@ -219,7 +219,7 @@
</script>
{% endblock javascript_loader %}

<script>
<script nonce="{{request.csp_nonce}}">
if(window.fetch){
document.documentElement.className = document.documentElement.className.replace('no-js', 'js')
}
Expand Down Expand Up @@ -308,7 +308,7 @@

{% block javascript scoped %}

<script>
<script nonce="{{request.csp_nonce}}">
if ( window.fetch ) {
!function(){
{# Include site-wide JavaScript. #}
Expand Down Expand Up @@ -361,7 +361,7 @@
</script>

{% if flag_enabled('PATH_MATCHES_FOR_QUALTRICS') %}
<script type='text/javascript'>
<script nonce="{{request.csp_nonce}}" type='text/javascript'>
(function(){var g=function(e,h,f,g){
this.get=function(a){for(var a=a+"=",c=document.cookie.split(";"),b=0,e=c.length;b<e;b++){for(var d=c[b];" "==d.charAt(0);)d=d.substring(1,d.length);if(0==d.indexOf(a))return d.substring(a.length,d.length)}return null};
this.set=function(a,c){var b="",b=new Date;b.setTime(b.getTime()+6048E5);b="; expires="+b.toGMTString();document.cookie=a+"="+c+b+"; path=/; "};
Expand Down
2 changes: 1 addition & 1 deletion cfgov/v1/jinja2/v1/layouts/layout-1-3.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

{% block javascript scoped %}
{{ super() }}
<script>
<script nonce="{{request.csp_nonce}}">
jsl(['{{ static("js/routes/on-demand/secondary-nav.js") }}']);
</script>
{% endblock javascript %}
Loading
Loading