Checkout icon

Manage script security for PCI DSS v4.0.1 compliance

Learn to implement script security on your payment page to comply with the PCI DSS v4.0.1 requirements.

Adyen has the following recommendations on how to comply with the PCI DSS requirements 6.4.3 and 11.6.1. If they are applicable to your integration, follow the instructions we provide.

If you are eligible for Self-Assessment Questionnaire A (SAQ A), you are exempt from these requirements.

When creating these guidelines, Adyen considered implementations advised by the PCI Security Standards Council (PCI SSC) in their formal guidance document: Payment Page Security and Preventing E-Skimming - Guidance for PCI DSS Requirements 6.4.3 and 11.6.1.

Authorize and assure the integrity of scripts for PCI DSS requirement 6.4.3

We recommend that you implement a Content Security Policy (CSP) on your payment page, because it allows you to authorize scripts before loading them on your page.
You can modify the CSP in your page header to do the following:

  • Allow all internally-loaded scripts by default.
  • Expressly allow scripts from non-internal domains to be loaded.

Additionally, we provide guidance on the options for reporting and alerting from your implemented CSP.

To ensure the integrity of scripts, we recommend implementing Subresource Integrity (SRI) to confirm that the files you load from Adyen have not been manipulated or tampered with by malicious actors.

Build your CSP

Following our guidance to build your CSP.

Start with a report-only CSP HTTP header.

This type of header causes no issues with how your integration works because it does not block any resources from loading.

By using the Content-Security-Policy-Report-Only header instead of the Content-Security-Policy header, the browser only logs the violation. It does not block any content from being loaded.

Add the following HTTP header to your page.

Report-only header
Expand view
Copy link to code block
Copy code
Copy code
Content-Security-Policy-Report-Only: default-src 'self'; font-src 'self'; img-src 'self'; script-src 'self'; style-src 'self'

After you implement it, you can see the violations that show up when visiting your website. The report-only policy shows you the following.

Field Description
default-src This CSP directive tells the browser which domains or subdomains scripts may be loaded from.
In all of our examples, we use 'self' as a trusted source, telling the browser to only load resources that are hosted on the same domain or subdomain.
If sources are not defined in any other directives, they apply this default policy.
font-src What fonts may be loaded.
img-src What images may be loaded.
script-src What scripts may be loaded.
style-src What styles/css may be loaded.

Allow scripts and iframes from external sources

Your CSP header can allow either of the following:

  • Anything, like images, scripts, media, and more, to be loaded from an external domain or subdomain.
  • Only things that you specify to be loaded from an external domain or subdomain.

We recommend that you implement the following blocking policy.

  1. Change the header to Content-Security-Policy. This is a blocking policy. You can add some defined exemptions.

  2. Allow specific domains and subdomains. When you define specific sources for scripts (script-src) and iframes (frame-src) they only allow loading resources from the specified domains, and everything else is blocked.

    For Adyen integrations, we recommend that you apply the following CSP configuration:

    Recommended CSP configuration
    Expand view
    Copy link to code block
    Copy code
    Copy code
    Content-Security-Policy:
    default-src 'self';
    script-src: *.adyen.com pay.google.com *.payments-amazon.com *.paypal.com *.ratepay.com *.cash.app
    font-src: cash-f.squarecdn.com
    style-src: *.cash.app
    frame-src: *
    img-src: *
    connect-src:*
    form-action:*

    If you have other third party integrations loading additional scripts, you must explicitly add them to the script-src directive.

Scripts and images that are loaded from other domains violate this policy and are included in the report that you configure for the CSP.

We suggest that you use the wildcard (*) for the iframe elements in this policy, for the following reasons:

  • Adyen loads only 3D Secure (3DS) authentication iframes. According to the PCI SSC, the 3DS script validation process is exempted from the scope of PCI DSS Requirement 6.4.3, because the trust relationship with the 3DS service provider is established through due diligence, onboarding, and business agreements of the entities involved. Because it is not possible to list all issuer domains loading iframes for 3DS authentication, a more stringent CSP might block 3DS iframes from loading.
  • Not using any frame-src definition might be functional but not stable. It would lead the CSP to use the default value, which is usually defined as blocking none. Therefore, some definition needs to be made. With our recommended CSP header setup, we make it possible to use CSP, but still allow loading all 3DS iframes which are exempted from the requirements.
  • This recommended implementation could allow any iframes to be loaded. However, iframes from Adyen are sandboxed and iframes that come from 3DS issuer banks are also sandboxed. By sandboxing, issues such as cross-site scripting are prevented, not adding any additional risk.

    Web Browser Sandboxing allows running web applications in isolation to prevent browser-based malware from spreading to the rest of the webpage or network. Most modern browsers already have a sandbox by default to enhance the protection of the user's computer.

Create an inventory of scripts

Following PCI DSS Requirement 6.4.3, all scripts added to your page must be in an inventory. This means that you must keep a list, including the ones required for Adyen integrations, with the business reason to use them.

Furthermore, you must have a simple periodical authorization sign-off. Ensuring that all scripts have been explicitly authorized reduces the risk of unnecessary scripts being added to the payment page without appropriate approval. However, for some cases, it can be impractical for such authorization to occur before a script is changed or a new script is loaded to the page. In these cases, the authorization should be confirmed as soon as a change is reported.

Adyen loads scripts from the following domain sources. Include them in your inventory for your Adyen integration:

Source Description
*.adyen.com Adyen-authorized domain for scripts loaded for payment-processing-associated services.
pay.google.com Allows integration with the Google Pay payment method.
*.payments-amazon.com Allows integration with the Amazon Pay payment method.
*.paypal.com Allows integration with the PayPal payment method.
*.ratepay.com Allows integration with the Ratepay payment method.
*.cash.app Allows integration with the Cash App service.

Check the integrity of scripts

We recommend implementing Subresource Integrity (SRI) to ensure that the files you load from Adyen have not been manipulated or tampered with by malicious actors. Use the SRI hash by doing the following.

  1. To the <script> or <link>elements, add the integrity attribute.
  2. Add the crossorigin attribute. Browsers also check to ensure that the origin allows Cross-Origin Resource Sharing (CORS). If the browser detects that the file's hash does not match the specified hash, the browser does not load the resource. Find out which browsers support SRI.

    For each version of Adyen Web Drop-in/Components, we provide the SRI hashes that you include as the integrity attribute for the JavaScript and CSS files. In the release notes, go to the Updating to this version section for the version that you use.

    The following example shows how include SRI hashes for the adyen.js and adyen.css resources for v5.59.1:

    SRI hashes for v5.59.1
    Expand view
    Copy link to code block
    Copy code
    Copy code
    <script src="https://checkoutshopper-live.adyen.com/checkoutshopper/sdk/5.59.0/adyen.js"
    integrity="sha384-O8p0CLZyOw1jkmYN7ZwJxWzd+sDYRFGpLEffqc+dKye24gFImbU72did4PC7ysTY"
    crossorigin="anonymous"></script>
    <link rel="stylesheet"
    href="https://checkoutshopper-live.adyen.com/checkoutshopper/sdk/5.59.0/adyen.css"
    integrity="sha384-zgFNrGzbwuX5qJLys75cOUIGru/BoEzhGMyC07I3OSdHqXuhUfoDPVG03G+61oF4"
    crossorigin="anonymous">

Implement change and tamper detection mechanisms to comply with PCI DSS Requirement 11.6.1

A functional CSP implementation can provide authorization and alerting in case of attempts to introduce unknown scripts or changes to currently authorized scripts. These events are considered valid alerts and "indicators of compromise", for the purpose of requirement 11.6.1.

You must collect all CSP alerts in a practical manner. This can be done by implementing the report-to directive, which sends you a report of alerts. This can help to meet the requirements included in 11.6.1, such as "alerting personnel of unauthorized modification".

  1. Create an endpoint on your server you want the browser to use for reporting CSP violations. If a CSP violation occurs, a report is generated. It contains a serialized CSPViolationReportBody object instance. Using the mechanisms of the Reporting API, the browser sends the report to your endpoint URL.

  2. Specify the mapping between endpoint names and URLs by adding the Reporting-Endpoints response header to your CSP. You can use any name for your endpoints.

    Example of Reporting-Endpoints response header
    Expand view
    Copy link to code block
    Copy code
    Copy code
    Reporting-Endpoints: your_endpoint_name="https://example.com/csp-reports"
  3. Add report-to, specifying the endpoint URL on your server that you want the browser to use for reporting CSP violations.

    Example of report-to directive
    Expand view
    Copy link to code block
    Copy code
    Copy code
    report-to your_endpoint_name
  4. When a CSP violation occurs, you get a report with CSP violations.