Movatterモバイル変換


[0]ホーム

URL:


  1. Web
  2. HTTP
  3. Guides
  4. Content Security Policy (CSP)

Content Security Policy (CSP)

Content Security Policy (CSP) is a feature that helps to prevent or minimize the risk of certain types of security threats. It consists of a series of instructions from a website to a browser, which instruct the browser to place restrictions on the things that the code comprising the site is allowed to do.

The primary use case for CSP is to control which resources, in particular JavaScript resources, a document is allowed to load. This is mainly used as a defense againstcross-site scripting (XSS) attacks, in which an attacker is able to inject malicious code into the victim's site.

A CSP can have other purposes as well, including defending againstclickjacking and helping to ensure that a site's pages will be loaded over HTTPS.

In this guide we'll start by describing how a CSP is delivered to a browser and what it looks like at a high level.

Then we'll describe how it can be used tocontrol which resources are loaded to protect against XSS, and then other use cases such asclickjacking protection andupgrading insecure requests. Note that there's no dependency between the different use cases: if you want to add clickjacking protection but not XSS mitigation, you can just add the directives for that use case.

Finally we'll describestrategies for deploying a CSP and tools that can help to make this process easier.

CSP overview

A CSP should be delivered to the browser in theContent-Security-Policy response header. It should be set on all responses to all requests, not just the main document.

You can also specify it using thehttp-equiv attribute of your document's<meta> element, and this is a useful option for some use cases, such as a client-side-renderedsingle page app which has only static resources, because you can then avoid relying on any server infrastructure. However, this option does not support all CSP features.

The policy is specified as a series ofdirectives, separated by semi-colons. Each directive controls a different aspect of the security policy. Each directive has a name, followed by a space, followed by a value. Different directives can have different syntaxes.

For example, consider the following CSP:

http
Content-Security-Policy: default-src 'self'; img-src 'self' example.com

It sets two directives:

  • thedefault-src directive is set to'self'
  • theimg-src directive is set to'self' example.com.

A CSP broken into its directives.

The first directive,default-src, tells the browser to load only resources that are same-origin with the document, unless other more specific directives set a different policy for other resource types. The second,img-src, tells the browser to load images that are same-origin or that are served fromexample.com.

In the next section, we'll look at the tools available to control resource loads, which is the main function of a CSP.

Controlling resource loading

A CSP can be used to control the resources that a document is allowed to load. This is primarily used for protection against cross-site scripting (XSS) attacks.

In this section we'll first see how controlling resource loads can help protect against XSS, then at the tools CSP provides to control what resources are loaded. Finally we'll describe one particular recommended strategy, which is called a "Strict CSP".

XSS and resource loading

A cross-site scripting (XSS) attack is one in which an attacker is able to execute their code in the context of the target website. This code is then able to do anything that the website's own code could do, including, for example:

  • access or modify the content of the site's loaded pages
  • access or modify content in local storage
  • make HTTP requests with the user's credentials, enabling them to impersonate the user or access sensitive data

An XSS attack is possible when a website accepts some input which might have been crafted by an attacker (for example, URL parameters, or a comment on a blog post) and then includes it in the page withoutsanitizing it: that is, without ensuring that it can't be executed as JavaScript.

Websites should protect themselves against XSS by sanitizing this input before including it in the page. A CSP provides a complementary protection, which can protect the website even if sanitization fails.

If sanitization does fail, there are various forms the injected malicious code can take in the document, including:

  • A<script> tag that links to a malicious source:

    html
    <script src="https://evil.example.com/hacker.js"></script>
  • A<script> tag that includes inline #"You've been hacked!");</script>

  • An inline event handler:

    html
    <img  onmouseover="console.log(`You've been hacked!`)"  src="thumbnail.jpg"  alt="" />
  • A#"#"></iframe>

  • A string argument to an unsafe API likeeval():

    js
    eval("console.log(`You've been hacked!`)");
  • A CSP can provide protection against all of these. With a CSP, you can:

    Theunsafe-inline keyword can be used to override this restriction. For example, the following directive requires all resources to be same-origin, but allows inline #"/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval">eval() itself:

    js
    eval('console.log("hello from eval()")');
  • TheFunction() constructor:

    js
    const sum = new Function("a", "b", "return a + b");
  • The string argument tosetTimeout() andsetInterval():

    js
    setTimeout("console.log('hello from setTimeout')", 1);
  • Theunsafe-eval keyword can be used to override this behavior, and as withunsafe-inline, and for the same reasons:developers should avoidunsafe-eval.

    Sometimes it can be difficult to remove usages ofeval() and the other methods: in these situations, theTrusted Types API can make it safer, by ensuring that the input meets a defined policy.Thetrusted-types-eval keyword should be used to override the behavior in this case.Unlikeunsafe-inline it only overrides the behavior in browser when trusted types are supported and enabled; which ensures that the methods will remain blocked on browsers that don't support trusted types.

    Unlikeunsafe-inline, theunsafe-eval keyword does still work in a directive that contains nonce or hash expressions.

    Strict CSP

    To control script loading as a mitigation against XSS, recommended practice is to usenonce- orhash- based fetch directives. This is called astrict CSP. This type of CSP has two main advantages over a location-based CSP (usually called anallowlist CSP):

    A nonce-based strict CSP looks like this:

    http
    Content-Security-Policy:  script-src 'nonce-{RANDOM}';  object-src 'none';  base-uri 'none';

    In this CSP, we:

    A hash-based strict CSP is the same, except it uses hashes instead of nonces:

    http
    Content-Security-Policy:  script-src 'sha256-{HASHED_SCRIPT}';  object-src 'none';  base-uri 'none';

    Nonce-based directives are easier to maintain if you can generate responses, including the content itself, dynamically. Otherwise, you need to use hash-based directives. The problem with hash-based directives is that you need to recalculate and reapply the hash if any change is made to the script contents.

    Thestrict-dynamic keyword

    As presented above, the strict CSP is difficult to implement when you use scripts which are not under your control. If a third-party script loads any additional scripts, or uses any inline scripts, then this will fail, because the third-party script won't pass the nonce or hash through.

    Thestrict-dynamic keyword is provided to help with this problem. It is a keyword that can be included in a fetch directive, and it has the effect that if a script has a nonce or a hash attached to it, then that script will be allowed to load further scripts which do not themselves have nonces or hashes. That is, the trust placed in a script by a nonce or hash is passed on to scripts that the original script loads (and scripts thatthey load, and so on).

    For example, consider a document like this:

    html
    <html lang="en-US">  <head>    <script      src="./main.js"      integrity="sha256-gEh1+8U9S1vkEuQSmmUMTZjyNSu5tIoECP4UXIEjMTk="></script>  </head>  <body>    <h1>Example page!</h1>  </body></html>

    It includes a script "main.js", which creates and adds another script, "main2.js":

    js
    console.log("hello");const scriptElement = document.createElement("script");scriptElement.src = `main2.js`;document.head.appendChild(scriptElement);

    We serve our document with a CSP like this:

    http
    Content-Security-Policy:  script-src 'sha256-gEh1+8U9S1vkEuQSmmUMTZjyNSu5tIoECP4UXIEjMTk='

    The "main.js" script will be allowed to load, because its hash matches the value in the CSP. But its attempt to load "main2.js" will fail.

    If we add'strict-dynamic' to the CSP, then "main.js" will be allowed to load "main2.js":

    http
    Content-Security-Policy:  script-src 'sha256-gEh1+8U9S1vkEuQSmmUMTZjyNSu5tIoECP4UXIEjMTk='  'strict-dynamic'

    The'strict-dynamic' keyword makes it much easier to create and maintain nonce- or hash-based CSPs, especially when a website uses third-party scripts. It does make your CSP less secure, though, because if the scripts you include create<script> elements based on potential sources of XSS, then the CSP will not protect them.

    Refactoring inline JavaScript andeval()

    We've seen above that inline JavaScript is disallowed by default in a CSP. With nonces or hashes, a developer can use inline<script> tags, but you'll still need to refactor code to remove other disallowed patterns, including inline event handlers,#"/en-US/docs/Web/API/EventTarget/addEventListener" title="addEventListener()">addEventListener():

    html
    <p>click me</p>
    html
    <!-- served with the following CSP: `script-src 'sha256-AjYfua7yQhrSlg807yyeaggxQ7rP9Lu0Odz7MZv8cL0='` --><p>click me</p><script>  const hello = document.querySelector("#hello");  hello.addEventListener("click", () => {    console.log("Hello from an inline script");  });</script>

    Clickjacking protection

    Theframe-ancestors directive can be used to control which documents, if any, are allowed to embed this document in a nested browsing context such as an<iframe>. This is an effective protection against clickjacking attacks, because these attacks depend on embedding the target site in a site controlled by the attacker.

    The syntax offrame-ancestors is a subset of the fetch directive syntax: you can provide the single keyword value'none' or one or more source expressions. However, the only source expressions you can use are schemes, hostnames, or the'self' keyword value.

    Unless you need your site to be embeddable, you should setframe-ancestors to'none':

    http
    Content-Security-Policy: frame-ancestors 'none'

    This directive is a more flexible replacement for theX-Frame-Options header.

    Upgrading insecure requests

    Web developers are strongly encouraged to serve all their content over HTTPS. In the process of upgrading a site to HTTPS, a site sometimes serves the main document over HTTPS but serves its resources over HTTP, for example, using markup like this:

    html
    <script src="http://example.org/my-cat.js"></script>

    This is calledmixed content, and the presence of insecure resources greatly weakens the protection afforded by HTTPS. Under themixed content algorithm that browsers implement, if a document is served over HTTPS, insecure resources are categorized into "upgradable content" and "blockable content". Upgradable content is upgraded to HTTPS, and blockable content is blocked, potentially breaking the page.

    The ultimate solution to mixed content is for developers to load all resources over HTTPS. However, even if a site is actually able to serve all content over HTTPS, it can still be very difficult (or even effectively impossible, where archived content is concerned) for a developer to rewrite all the URLs the site uses to load resources.

    Theupgrade-insecure-requests directive is intended to solve this problem. This directive doesn't have any value: to set it, just include the directive name:

    http
    Content-Security-Policy: upgrade-insecure-requests

    If this directive is set on a document, then the browser will automatically upgrade to HTTPS any HTTP URLs in the following cases:

    However, top-level navigation requests whose target is a different origin will not be upgraded.

    For example, suppose the document athttps://example.org is served with a CSP containing theupgrade-insecure-requests directive, and the document contains markup like this:

    html
    <script src="http://example.org/my-cat.js"></script><script src="http://not-example.org/another-cat.js"></script>

    The browser will automatically upgrade both of these requests to HTTPS.

    Suppose the document also contains this:

    html
    <a href="http://example.org/more-cats">See some more cats!</a><a href="http://not-example.org/even-more-cats">More cats, on another site!</a>

    The browser will upgrade the first link to HTTPS, but not the second, as it is navigating to a different origin.

    This directive is not a substitute for theStrict-Transport-Security header (also known as HSTS), because it does not upgrade external links to a site. Sites should include this directive and theStrict-Transport-Security header.

    Testing your policy

    To ease deployment, CSP can be deployed in report-only mode.The policy is not enforced, but any violations are sent to the reporting endpoint specified in the policy. Additionally, a report-only header can be used to test a future revision to a policy without actually deploying it.

    You can use theContent-Security-Policy-Report-Only HTTP header to specify your policy, like this:

    http
    Content-Security-Policy-Report-Only: policy

    If both aContent-Security-Policy-Report-Only header and aContent-Security-Policy header are present in the same response, both policies are honored.The policy specified inContent-Security-Policy headers is enforced while theContent-Security-Policy-Report-Only policy generates reports but is not enforced.

    Note that unlike a normal content security policy, a report-only policy cannot be delivered in a<meta> element.

    Violation reporting

    The recommended method for reporting CSP violations is to use theReporting API, declaring endpoints inReporting-Endpoints and specifying one of them as the CSP reporting target using theContent-Security-Policy header'sreport-to directive.

    Warning:You can also use the CSPreport-uri directive to specify a target URL for CSP violation reports.This sends a slightly different JSON report format via aPOST operation with aContent-Type ofapplication/csp-report.This approach is deprecated, but you should declare both untilreport-to is supported in all browsers.For more information about the approach see thereport-uri topic.

    A server can inform clients where to send reports using theReporting-Endpoints HTTP response header.This header defines one or more endpoint URLs as a comma-separated list.For example, to define a reporting endpoint namedcsp-endpoint which accepts reports athttps://example.com/csp-reports, the server's response header could look like this:

    http
    Reporting-Endpoints: csp-endpoint="https://example.com/csp-reports"

    If you want to have multiple endpoints that handle different types of reports, you would specify them like this:

    http
    Reporting-Endpoints: csp-endpoint="https://example.com/csp-reports",                     hpkp-endpoint="https://example.com/hpkp-reports"

    You can then use theContent-Security-Policy header'sreport-to directive to specify that a particular defined endpoint should be used for reporting.For example, to send CSP violation reports tohttps://example.com/csp-reports for thedefault-src, you might send response headers that look like the following:

    http
    Reporting-Endpoints: csp-endpoint="https://example.com/csp-reports"Content-Security-Policy: default-src 'self'; report-to csp-endpoint

    When a CSP violation occurs, the browser sends the report as a JSON object to the specified endpoint via an HTTPPOST operation, with aContent-Type ofapplication/reports+json.The report is a serialized form of theReport object containing atype property with a value of"csp-violation", and abody that is the serialized form of aCSPViolationReportBody object.

    A typical object might look like this:

    json
    {  "age": 53531,  "body": {    "blockedURL": "inline",    "columnNumber": 39,    "disposition": "enforce",    "documentURL": "https://example.com/csp-report",    "effectiveDirective": "script-src-elem",    "lineNumber": 121,    "originalPolicy": "default-src 'self'; report-to csp-endpoint-name",    "referrer": "https://www.google.com/",    "sample": "console.log(\"lo\")",    "sourceFile": "https://example.com/csp-report",    "statusCode": 200  },  "type": "csp-violation",  "url": "https://example.com/csp-report",  "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"}

    You need to set up a server to receive reports with the given JSON format and content type.The server handling these requests can then store or process the incoming reports in a way that best suits your needs.

    See also

    Help improve MDN

    Learn how to contribute

    This page was last modified on byMDN contributors.

    View this page on GitHubReport a problem with this content

    [8]ページ先頭

    ©2009-2025 Movatter.jp