Adding CSP Header- Allowing inline script using 'nonce' - Java example.

How to add nonce in Content Security Policy header dynamically to inline scripts in a Java/J2EE application with Spring framework.

To add a nonce to the Content Security Policy (CSP) header dynamically for inline scripts using Java J2EE and the Spring framework, you need to follow these steps:

 

*The provided code snippets are for reference only. Developers should implement their own solutions based on their application's existing design. 

 

1. Generate a Unique Nonce and add it to the header using a Custom Filter.

Generate a unique nonce for each HTTP request. This nonce should be included in the CSP header and made available to your views.

Example Filter to Generate Nonce in Spring:

First, create a filter to generate the nonce and add it to the response headers.

import org.springframework.stereotype.Component;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.Base64;

@Component
public class ContentSecurityPolicyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String nonce = generateNonce();
        httpServletRequest.setAttribute("cspNonce", nonce);
        httpServletResponse.setHeader("Content-Security-Policy", "script-src 'self' 'nonce-" + nonce + "';");
        chain.doFilter(request, response);
    }
    @Override
    public void destroy() {
    }
    private String generateNonce() {
        SecureRandom secureRandom = new SecureRandom();
        byte[] nonceBytes = new byte[16];
        secureRandom.nextBytes(nonceBytes);
        return Base64.getEncoder().encodeToString(nonceBytes);
    }
}

 

2. Configure the Filter in Spring

Register the filter in your Spring configuration.

Example Configuration:

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class WebConfig {
    @Bean
    public FilterRegistrationBean<ContentSecurityPolicyFilter> cspFilter() {
        FilterRegistrationBean<ContentSecurityPolicyFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new ContentSecurityPolicyFilter());
        registrationBean.addUrlPatterns("/*");
        return registrationBean;
    }
}

 

3. Pass the Nonce to the View

Pass the nonce to your views so it can be used in inline scripts. This can be done in the controller.

Example Controller:

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import javax.servlet.http.HttpServletRequest;
@Controller
public class HomeController {
    @GetMapping("/")
    public String index(HttpServletRequest request, Model model) {
        String nonce = (String) request.getAttribute("cspNonce");
        model.addAttribute("nonce", nonce);
        return "index";
    }
}

 

4. Use the Nonce in the View

In your view, use the nonce in your inline scripts and dynamically added scripts.

Example: index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <meta name="csp-nonce" content="${nonce}">
</head>
<body>
    <script>
        // Make the nonce available to all scripts
        window.cspNonce = document.querySelector('meta[name="csp-nonce"]').getAttribute('content');
        document.addEventListener('DOMContentLoaded', function () {
            var nonce = window.cspNonce;

            // Add Google Analytics script
            var gaScript = document.createElement('script');
            gaScript.setAttribute('async', 'async');
            gaScript.setAttribute('src', 'https://www.googletagmanager.com/gtag/js?id=YOUR_TRACKING_ID');
            gaScript.setAttribute('nonce', nonce);
            document.head.appendChild(gaScript);

            // Add inline script for Google Analytics
            var inlineScript = document.createElement('script');
            inlineScript.setAttribute('nonce', nonce);
            inlineScript.text = `
                window.dataLayer = window.dataLayer || [];
                function gtag(){dataLayer.push(arguments);}
                gtag('js', new Date());
                gtag('config', 'YOUR_TRACKING_ID');
            `;
            document.head.appendChild(inlineScript);

            // Example for dynamically adding scripts with jQuery
            $.getScript('https://example.com/your-script.js', function () {
                // Your script loaded and executed
            }).attr('nonce', nonce);
        });
    </script>
</body>
</html>

 

5. Dynamically Add Nonce to Existing Script Elements

If you need to add a nonce to existing script elements that are added by some other means, you can iterate through the script elements and add the nonce.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <meta name="csp-nonce" content="${nonce}">
</head>
<body>
    <!-- Your content here -->
    <script>
        // Make the nonce available to all scripts
        window.cspNonce = document.querySelector('meta[name="csp-nonce"]').getAttribute('content');

        document.addEventListener('DOMContentLoaded', function () {
            var nonce = window.cspNonce;

            // Add Google Analytics script
            var gaScript = document.createElement('script');
            gaScript.setAttribute('async', 'async');
            gaScript.setAttribute('src', 'https://www.googletagmanager.com/gtag/js?id=YOUR_TRACKING_ID');
            gaScript.setAttribute('nonce', nonce);
            document.head.appendChild(gaScript);

            // Example for adding an external script
            var externalScript = document.createElement('script');
            externalScript.setAttribute('src', 'https://example.com/external-script.js');
            externalScript.setAttribute('nonce', nonce);
            document.head.appendChild(externalScript);

            // Apply nonce to all existing scripts
            var scripts = document.getElementsByTagName('script');
            for (var i = 0; i < scripts.length; i++) {
                scripts[i].setAttribute('nonce', nonce);
            }
        });
    </script>
</body>
</html>

 

By following these steps, you can ensure that the nonce is added to all your externally referenced JavaScripts dynamically using Java J2EE and the Spring framework.

 

Page 1 of this article:

https://community.veracode.com/s/article/How-to-fix-CWE-829-Add-CSP-header-correctly

Page 3 : Dot Net example.

Topics (0)

Related Topics

    Ask the Community

    Get answers, share a use case, discuss your favorite features, or get input from the Community.