How to Secure Axios with Content Security Policy

This guide provides a straightforward walkthrough on configuring the Axios HTTP client to comply with strict security standards, specifically focusing on Content Security Policy (CSP) rules and security headers. You will learn how browser CSP directives govern Axios requests, how to configure instance-level security defaults, how to implement request interceptors for dynamic security tokens, and how to inspect response headers for compliance.

Understanding CSP and Axios

Content Security Policy (CSP) is a browser-enforced security layer designed to prevent attacks like Cross-Site Scripting (XSS) and data injection. For Axios running in a browser environment, CSP directly limits the endpoints your application can communicate with via the connect-src directive.

If an Axios request targets a domain not explicitly allowed in the page's CSP header (or <meta> tag), the browser blocks the request before it executes.

Example CSP directive allowing Axios requests to a specific API domain:

Content-Security-Policy: default-src 'self'; connect-src 'self' https://api.example.com;

Configuring Axios Instances with Security Defaults

To prevent configuration drift and enforce consistent security policies, create a dedicated Axios instance instead of using the global Axios object.

import axios from 'axios';

const secureApiClient = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 10000,
  withCredentials: true, // Ensures cookies and authorization headers are sent only to allowed origins
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json',
    'X-Requested-With': 'XMLHttpRequest', // Helps protect against CSRF attacks
  }
});

export default secureApiClient;

Dynamically Injecting CSP Nonces and CSRF Tokens

When strict CSP policies require tokens or nonces for API verification, use Axios request interceptors to dynamically fetch and attach these values before each request is dispatched.

secureApiClient.interceptors.request.use(
  (config) => {
    // Retrieve a CSP nonce or CSRF token from the DOM or secure storage
    const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
    
    if (csrfToken) {
      config.headers['X-CSRF-Token'] = csrfToken;
    }

    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

Validating Security Headers on Incoming Responses

In environments like Node.js or edge workers, you may want Axios to actively inspect response headers and reject payloads from servers that fail to provide strict security headers such as Content-Security-Policy, Strict-Transport-Security (HSTS), or X-Content-Type-Options.

secureApiClient.interceptors.response.use(
  (response) => {
    const cspHeader = response.headers['content-security-policy'];
    const hstsHeader = response.headers['strict-transport-security'];

    // Optional validation: Log or reject responses lacking critical headers
    if (!hstsHeader && process.env.NODE_ENV === 'production') {
      console.warn('Security Warning: Missing HSTS header on response from', response.config.url);
    }

    return response;
  },
  (error) => {
    // Handle network or CSP policy violation errors
    if (error.message === 'Network Error' && !error.response) {
      console.error('Request may have been blocked by the browser Content Security Policy.');
    }
    return Promise.reject(error);
  }
);

Best Practices for Secure Axios Usage