Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

ember-cli-content-security-policy

rwjblue47.3kMIT2.0.3

This addon adds the Content-Security-Policy header to response sent from the Ember CLI Express server.

ember-addon

readme

ember-cli-content-security-policy

This addon makes it easy to use Content Security Policy (CSP) in your project. The policy can be delivered either via a Content-Security-Policy HTTP response header or as a meta tag in the index.html file.

If configured to deliver the CSP using a HTTP response header, the header is set automatically if served with Ember CLI's express server in development or via FastBoot in production. If FastBoot is not used to serve the app in production, the web server must be configured to set the CSP header. The configured CSP could be exported with a provided Ember CLI command.

If configured to deliver the CSP using the meta tag no additional configuration of the web server serving the application in production is needed.

In any case, using this addon helps keeping CSP in the forefront of your thoughts while developing an Ember application.

Compatibility

  • Ember.js v2.18 or above
  • Ember CLI v3.4 or above
  • Node.js v12 or above

Installation

ember install ember-cli-content-security-policy

Configuration

This addon is configured via config/content-security-policy.js file.

type directiveName =
  // Fetch Directives
  | 'child-src'
  | 'connect-src'
  | 'default-src'
  | 'font-src'
  | 'frame-src'
  | 'image-src'
  | 'manifest-src'
  | 'media-src'
  | 'object-src'
  | 'prefetch-src'
  | 'script-src'
  | 'script-src-elem'
  | 'script-src-attr'
  | 'style-src'
  | 'style-src-elem'
  | 'style-src-attr'
  | 'worker-src'
  // Document Directives
  | 'base-uri'
  | 'plugin-types'
  | 'sandbox'
  // Navigation Directives
  | 'form-action'
  | 'frame-ancestors'
  | 'navigate-to'
  // Reporting Directives
  | 'report-uri'
  | 'report-to'
  // Directives Defined in Other Documents
  | 'block-all-mixed-content'
  | 'upgrade-insecure-requests'
  | 'require-sri-for';

interface EmberCLIContentSecurityPolicyConfig {
  // CSP is delivered via HTTP Header if delivery includes `"header"` and via
  // meta element if it includes `"meta"`.
  delivery?: string;

  // Controls if addon is enabled at all.
  enabled?: boolean;

  // Controls if addon causes tests to fail if they violate configured CSP
  // policy.
  failTests: true;

  // A hash of options representing a Content Security Policy. The key must be
  // a CSP directive name as defined by spec. The value must be an array of
  // strings that form a CSP directive value, most likely a source list, e.g.
  // {
  //   'default-src': ["'none'"],
  //   'style-src': ["'self'", 'examples.com']
  // }
  // Please refer to CSP specification for details on valid CSP directives:
  // https://w3c.github.io/webappsec-csp/#framework-directives
  policy?: {[key: directiveName]: string[]};

  // Controls if CSP is used in report only mode. For delivery mode `"header"`
  // this causes `Content-Security-Policy-Report-Only` HTTP header to be used.
  // Can not be used together with delivery mode `"meta"` as this is not
  // supported by CSP spec.
  reportOnly?: boolean;
}

If you omit some or all of the keys, the default configuration will be used, which is:

// config/content-security-policy.js

module.exports = function (environment) {
  return {
    delivery: ['header'],
    enabled: true,
    failTests: true,
    policy: {
      'default-src': ["'none'"],
      'script-src': ["'self'"],
      'font-src': ["'self'"],
      'connect-src': ["'self'"],
      'img-src': ["'self'"],
      'style-src': ["'self'"],
      'media-src': ["'self'"],
    },
    reportOnly: true,
  };
};

Keywords such as self, none, unsafe-inline, nonces and digests must be wrapped in single quotes (') as shown above. Please find more details about valid source expression in § 2.3.1. Source Lists of CSP specification.

Changes to the configuration require a restart of a running Ember development server instance.

Example

If your site uses Google Fonts, Mixpanel, a custom API at custom-api.local and you want to deliver the CSP using a meta element:

// config/content-security-policy.js

module.exports = function (environment) {
  return {
    delivery: ['meta'],
    policy: {
      // Deny everything by default
      'default-src': ["'none'"],
      // Allow scripts at https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js
      'script-src': ["'self'", 'https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js'],
      // Allow fonts to be loaded from http://fonts.gstatic.com
      'font-src': ["'self'", 'http://fonts.gstatic.com'],
      // Allow data (xhr/websocket) from api-js.mixpanel.com and custom-api.local
      'connect-src': ["'self'", 'https://api-js.mixpanel.com', 'https://custom-api.local'],
      // Allow images from the origin itself (i.e. current domain)
      'img-src': ["'self'"],
      // Allow CSS loaded from https://fonts.googleapis.com
      'style-src': ["'self'", 'https://fonts.googleapis.com'],
      // Omit `media-src` from policy
      // Browser will fallback to default-src for media resources (which is 'none', see above)
      'media-src': null,
    },
    reportOnly: false,
  };
};

FastBoot Integration

This addon sets the CSP HTTP response header in FastBoot if it's enabled for the used environment and delivery contains "header". It does not override existing CSP headers.

If using reportOnly mode you must provide a valid reportUri directive pointing to an endpoint that accepts violation reports. As reportUri directive is deprecated you should additionally provide a reportTo directive, even so it's only supported by Google Chrome so far.

If you don't want the addon to inject the CSP header in FastBoot on production (e.g. cause CSP header should be set by a reverse proxy in front of FastBoot App Server), you should either remove "header" from delivery option or disable the addon entirely.

// config/content-security-policy.js

module.exports = function (environment) {
  return {
    enabled: environment !== 'production',
    delivery: ['header'],
  };
};

External Configuration

In order to configure your production web server, you can use the csp-headers Ember CLI command to obtain the configured Content Security Policy:

$ ember csp-headers --environment production --report-uri /csp-report

# Content Security Policy Header Configuration
#
# for Apache: Header set Content-Security-Policy-Report-Only "..."
# for Nginx : add_header Content-Security-Policy-Report-Only "...";

default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self'; report-uri /csp-report;

Development Support

Ember CLI's live reload feature requires a Web Socket connection. If live reload is used with ember serve or ember test --server the URL used for that Web Socket connection is injected into connect-src and script-src directives automatically.

Test Support

The addon helps you to ensure that your app or addon is compliant with a specific Content Security Policy by providing test support. It causes tests to fail if the code triggers a violation of the configured CSP.

It's recommended to test your project for CSP compliance. But you could disable it nevertheless by setting enabled option to false for test environment:

// config/content-security-policy.js

module.exports = function (environment) {
  return {
    enabled: environment !== 'test',
  };
};

Compatibility with other addons

Some addons are not compatible with a strict Content Security Policy. If you face any CSP violations caused by a third-party addon please report at their side. Often it's only a small change to required to make it compliant with a strict CSP. You may want to suggest adding this addon to test for compliance with a strict CSP.

For some addons compliance with a strict CSP requires a custom configuration. This documentation lists required configuration for some famous once.

Ember Auto Import

Ember Auto Import uses the eval function by default in development builds. This violates the default CSP policy. It's recommended to set Ember Auto Import's forbidEval option to true if using Content Security Policy. You should not add 'unsafe-eval' to script-src directive as this disalbes main security provided by CSP.

Embroider

Webpack, which is used by Embroider, uses the eval function by default in development builds to generate a source map. This violates the default CSP policy. It's recommended to configure Webpack to use 'source-map' strategy to generate source maps. To do so, add the following Embroider configuration:

return require('@embroider/compat').compatBuild(app, Webpack, {
  packagerOptions: {
    // other configuration
    webpackConfig: {
      devtool: 'source-map',
    },
  },
});

For addons using maybeEmbroider utility provided by @embroider/test-setup the configuration looks like this:

const { maybeEmbroider } = require('@embroider/test-setup');
return maybeEmbroider(app, {
  // other configuration
  packagerOptions: {
    webpackConfig: {
      devtool: 'source-map',
    },
  },
});

ember-cli-code-coverage

Ember-cli-code-coverage uses Istanbul, which injects new Function('return this') by default into the app. This requires 'unsafe-eval' to be allowed by the script directive. Currently there isn't any other option than either adding 'unsafe-eval' to script directive if code coverage is enabled or disable CSP at all. Details could be found in this issue.

Deprecations

Please find detailed information about deprecations in deprecation guide.

changelog

Changelog

v2.0.3 (2022-01-02)

:bug: Bug Fix

Committers: 1

v2.0.2 (2021-12-20)

:bug: Bug Fix

  • #271 Fastboot instance initializer throws if reportOnly config is false (@JoeyBG)

Committers: 1

v2.0.1 (2021-12-13)

:bug: Bug Fix

:house: Internal

  • #272 use a recent fastboot version in tests (@jelhan)

Committers: 2

v2.0.0 (2021-11-12)

v2.0.0 is the same as last pre-release (v2.0.0-5). It does not include any additional changes.

v2.0.0-5 (2021-10-28)

:boom: Breaking Change

:bug: Bug Fix

  • #249 use environment from appConfig instead of deriving it ourselves (@jelhan)

:memo: Documentation

:house: Internal

Committers: 3

v2.0.0-4 (2021-05-06)

:bug: Bug Fix

  • #201 Support Ember CLI >= 3.26.0 and match injected script element by all supported Ember CLI versions with same RegExp (@snewcomer)

Committers: 1

v2.0.0-3 (2021-04-16)

:bug: Bug Fix

:memo: Documentation

  • #195 Fix typo form-ancestors -> frame-ancestors in readme (@nicomihalich)
  • #188 remove duplicated entry in config interface documentation (@jelhan)

Committers: 4

v2.0.0-2 (2021-01-09)

:bug: Bug Fix

  • #172 remove report-uri from policy delivered through meta (@jelhan)
  • #152 append frame-src config in test mode (@chbonser)
  • #158 Support live reload and add optional debug log (@jelhan)
  • #156 Remove existing 'none' keyword when applying to source list (@jelhan)

:memo: Documentation

:house: Internal

Committers: 4

v2.0.0-1 (2020-04-15)

:bug: Bug Fix

  • #143 development server should use config for test if serving /tests/ (@jelhan)

Committers: 1

v2.0.0-0 (2020-04-13)

This releases cumulates the work of 1 1/2 years. Main changes are:

  • It allows projects to test for CSP compliance.
  • It integrates with Ember FastBoot to set CSP header in FastBoot App Server.
  • It moves it's own configuration to config/content-security-policy.js and avoids injecting unnecessary configuration into run-time.
  • It introduces tests for it's own implementation to avoid regressions and increase stability.

The existing configuration syntax in config/environment.js is still supported but deprecated. You are recommended to migrate your configuration to config/content-security-policy.js as soon as possible. The deprecation guide contains migration instructions.

:boom: Breaking Change

  • #135 Do not set X-Content-Security-Policy header (@jelhan)
  • #107 Ensure csp-headers command emits to standard out (to allow for piping into other programs) (@Exelord)
  • #130 Drop Node 8, 9, and 11 support. (@rwjblue)
  • #87 Drop Ember CLI < 2.13 and Node 4 support (@loganrosen)

:rocket: Enhancement

  • #91 Add ability to fail application / addon tests when a CSP violation is detected. (@jelhan)
  • #113 Set CSP header in FastBoot (@jelhan)
  • #104 Move config to config/content-security-policy.js (@jelhan) Previous Iterations:
    • #94 Refactor configuration to use ember-cli-content-security-policy (instead of contentSecurityPolicy) (@jelhan)
    • #97 Allow configuration to be specified in ember-cli-build.js (@jelhan)
  • #101 Avoid merging policies in build time configuration (@jelhan)
  • #84 Add option to output raw CSP (Closes #81) (@YoranBrondsema)
  • #121 Inject runtime config only if needed (if FastBoot dependency exists) (@jelhan)

:bug: Bug Fix

  • #122 Consistent test results regardless of environment (@jelhan)
  • #134 Prevent unnecessary meta + reportOnly warning (@reidab)
  • #136 Do not override existing CSP headers in fastboot (@jelhan)
  • #129 Set status-code to 204 (no content) (@sandstrom)
  • #128 Don't add nonce to script-src when it already contains 'unsafe-inline' (@joukevandermaas)
  • #109 Fix support for --live-reload-host option (@jelhan)
  • #107 Ensure csp-headers command emits to standard out (to allow for piping into other programs) (@Exelord)
  • #96 Fix inconsistency between meta element and HTTP header regarding live reload support (@jelhan)
  • #95 Remove trailing whitespace from generated CSP string (@jelhan)

:memo: Documentation

:house: Internal

Committers: 8