Skip to content

Commit

Permalink
Merge pull request #78 from alphagov/add-csp-support
Browse files Browse the repository at this point in the history
Add support for content security policy
  • Loading branch information
rubenarakelyan authored Apr 5, 2019
2 parents ad121f5 + 1359663 commit 5149c7a
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Unreleased

* Add content security policy support.

# 1.13.1

* Remove formating from the Logstasher logger, used by default for the
Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Adds the basics of a GOV.UK application:
- Error reporting with Sentry
- Statsd client for reporting stats
- Rails logging
- Content Security Policy generation for frontend apps

## Installation

Expand Down Expand Up @@ -115,6 +116,19 @@ check docs](docs/healthchecks.md) for more information on how to use it.
In Rails applications, the application will be configured to send JSON-formatted
logs to `STDOUT` and unstructed logs to `STDERR`.

## Content Security Policy generation

For frontend apps, configuration can be added to generate and serve a
content security policy header. The policy is report only when the Rails
environment is set to "production", and enforced otherwise.

To enable this feature, create a file at `config/initializers/csp.rb` in the
app with the following content:

```ruby
GovukContentSecurityPolicy.configure
```

## License

[MIT License](LICENSE.md)
1 change: 1 addition & 0 deletions lib/govuk_app_config.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require "govuk_app_config/version"
require "govuk_app_config/govuk_content_security_policy"
require "govuk_app_config/govuk_statsd"
require "govuk_app_config/govuk_error"
require "govuk_app_config/govuk_logging"
Expand Down
138 changes: 138 additions & 0 deletions lib/govuk_app_config/govuk_content_security_policy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
module GovukContentSecurityPolicy
# Generate a Content Security Policy (CSP) directive.
#
#
# Extracted in a separate module to allow comments.
#
# See https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP for more CSP info.
#
# The resulting policy should be checked with:
#
# - https://csp-evaluator.withgoogle.com
# - https://cspvalidator.org

GOVUK_DOMAINS = "'self' *.publishing.service.gov.uk localhost".freeze

GOOGLE_ANALYTICS_DOMAINS = "www.google-analytics.com ssl.google-analytics.com".freeze

def self.build
policies = []

# By default, only allow HTTPS connections, and allow loading things from
# the publishing domain
#
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/default-src
policies << [
"default-src https",
GOVUK_DOMAINS
]

# Allow images from the current domain, Google Analytics (the tracking pixel),
# and publishing domains.
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/img-src
policies << [
"img-src",

# Allow `data:` images for Base64-encoded images in CSS like:
#
# https://github.com/alphagov/service-manual-frontend/blob/1db99ed48de0dfc794b9686a98e6c62f8435ae80/app/assets/stylesheets/modules/_search.scss#L106
"data:",

GOVUK_DOMAINS,
GOOGLE_ANALYTICS_DOMAINS,

# Some content still links to an old domain we used to use
"assets.digital.cabinet-office.gov.uk",
]

# script-src determines the scripts that the browser can load
#
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src
policies << [
# Allow scripts from publishing domains
"script-src",
GOVUK_DOMAINS,
GOOGLE_ANALYTICS_DOMAINS,

# Allow JSONP call to Verify to check whether the user is logged in
# https://www.staging.publishing.service.gov.uk/log-in-file-self-assessment-tax-return/sign-in/prove-identity
# https://github.com/alphagov/government-frontend/blob/71aca4df9b74366618a5a93acdb5cd2715f94f49/app/assets/javascripts/modules/track-radio-group.js
"www.signin.service.gov.uk",

# Allow YouTube Embeds (Govspeak turns YouTube links into embeds)
"*.ytimg.com",
"www.youtube.com",

# Allow all inline scripts until we can conclusively document all the inline scripts we use,
# and there's a better way to filter out junk reports
"'unsafe-inline'"
]

# Allow styles from own domain and publishing domains.
#
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/style-src
policies << [
"style-src",
GOVUK_DOMAINS,

# Also allow "unsafe-inline" styles, because we use the `style=""` attribute on some HTML elements
"'unsafe-inline'"
]

# Allow fonts to be loaded from data-uri's (this is the old way of doing things)
# or from the publishing asset domains.
#
# https://www.staging.publishing.service.gov.uk/apply-for-a-licence/test-licence/westminster/apply-1
#
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/font-src
policies << [
"font-src data:",
GOVUK_DOMAINS
]

# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/connect-src
policies << [
# Scripts can only load data using Ajax from Google Analytics and the publishing domains
"connect-src",
GOVUK_DOMAINS,
GOOGLE_ANALYTICS_DOMAINS,

# Allow connecting to web chat from HMRC contact pages like
# https://www.staging.publishing.service.gov.uk/government/organisations/hm-revenue-customs/contact/child-benefit
"www.tax.service.gov.uk",

# Allow connecting to Verify to check whether the user is logged in
# https://github.com/alphagov/government-frontend/blob/71aca4df9b74366618a5a93acdb5cd2715f94f49/app/assets/javascripts/modules/track-radio-group.js
# https://www.staging.publishing.service.gov.uk/log-in-file-self-assessment-tax-return/sign-in/prove-identity
"www.signin.service.gov.uk",
]

# Disallow all <object>, <embed>, and <applet> elements
#
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/object-src
policies << [
"object-src 'none'"
]

policies << [
"frame-src",

# Allow YouTube embeds
"www.youtube.com",
]

policies.map { |str| str.join(" ") }.join("; ") + ";"
end

def self.configure
# In test and development, use CSP for real to find issues. In production we only
# report violations to Sentry (https://sentry.io/govuk/govuk-frontend-csp) via an
# AWS Lambda function that filters out junk reports.
if Rails.env.production?
reporting = "report-uri https://jhpno0hk6b.execute-api.eu-west-2.amazonaws.com/production"
Rails.application.config.action_dispatch.default_headers['Content-Security-Policy-Report-Only'] = GovukContentSecurityPolicy.build + " " + reporting
else
Rails.application.config.action_dispatch.default_headers['Content-Security-Policy'] = GovukContentSecurityPolicy.build
end
end
end

0 comments on commit 5149c7a

Please sign in to comment.