When using axios for HTTP requests, you need to pay attention to various security issues, including XSS, CSRF, sensitive information leakage, etc.
1. XSS (Cross-Site Scripting) Protection
Problem Description
XSS attacks may inject malicious scripts through axios response data.
Protection Measures
javascript// 1. Response data escaping import DOMPurify from 'dompurify'; axios.interceptors.response.use( (response) => { // XSS filtering for response data if (response.data && typeof response.data === 'object') { response.data = sanitizeData(response.data); } return response; } ); function sanitizeData(data) { if (typeof data === 'string') { return DOMPurify.sanitize(data); } if (Array.isArray(data)) { return data.map(sanitizeData); } if (typeof data === 'object' && data !== null) { return Object.keys(data).reduce((acc, key) => { acc[key] = sanitizeData(data[key]); return acc; }, {}); } return data; } // 2. Set secure Content-Type axios.defaults.headers.common['Content-Type'] = 'application/json; charset=utf-8'; // 3. Prevent JSON injection axios.interceptors.request.use( (config) => { if (config.data && typeof config.data === 'object') { // Ensure sending JSON, not executable JavaScript config.data = JSON.stringify(config.data); } return config; } );
2. CSRF (Cross-Site Request Forgery) Protection
Problem Description
Attackers induce users to perform unintended actions on authenticated websites.
Protection Measures
javascript// 1. Use CSRF Token const api = axios.create({ xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN', withCredentials: true // Allow carrying cookies }); // 2. Manually add CSRF Token api.interceptors.request.use((config) => { // Get from meta tag const token = document.querySelector('meta[name="csrf-token"]')?.content; if (token) { config.headers['X-CSRF-Token'] = token; } // Or get from cookie const csrfToken = getCookie('csrfToken'); if (csrfToken) { config.headers['X-CSRF-Token'] = csrfToken; } return config; }); // 3. Double Cookie Verification api.interceptors.request.use((config) => { const sessionId = getCookie('sessionId'); const csrfToken = getCookie('csrfToken'); if (sessionId && csrfToken) { config.headers['X-CSRF-Token'] = csrfToken; // Verify token and session association } return config; }); // 4. SameSite Cookie Setting // Server setting: Set-Cookie: sessionId=xxx; SameSite=Strict; Secure; HttpOnly
3. Sensitive Information Protection
Token Secure Storage
javascript// ❌ Don't store directly in localStorage (XSS risk) localStorage.setItem('token', token); // ✅ Use httpOnly cookie (recommended) // Server setting: Set-Cookie: token=xxx; HttpOnly; Secure; SameSite=Strict // ✅ If must use localStorage, add additional security measures const secureStorage = { set(key, value) { // Add timestamp and signature const data = { value, timestamp: Date.now(), signature: generateSignature(value) }; localStorage.setItem(key, JSON.stringify(data)); }, get(key) { const item = localStorage.getItem(key); if (!item) return null; try { const data = JSON.parse(item); // Verify signature if (data.signature !== generateSignature(data.value)) { this.remove(key); return null; } // Check expiration (e.g., 24 hours) if (Date.now() - data.timestamp > 24 * 60 * 60 * 1000) { this.remove(key); return null; } return data.value; } catch { return null; } }, remove(key) { localStorage.removeItem(key); } }; function generateSignature(value) { // Use simple hash or HMAC return btoa(value + SECRET_KEY); }
Sensitive Information in Request Headers
javascript// 1. Avoid passing sensitive information in URL // ❌ Wrong axios.get(`/api/user?password=${password}`); // ✅ Correct axios.post('/api/user', { password }); // 2. Request header encryption import CryptoJS from 'crypto-js'; axios.interceptors.request.use((config) => { // Encrypt sensitive headers if (config.headers.Authorization) { config.headers['X-Encrypted'] = '1'; // Or use custom encryption // config.headers.Authorization = encrypt(config.headers.Authorization); } return config; }); // 3. Limit header exposure // Server setting: Access-Control-Expose-Headers: limited-headers
4. HTTPS and Certificate Verification
javascript// 1. Force HTTPS const api = axios.create({ baseURL: 'https://api.example.com', // Must use HTTPS }); // 2. Certificate verification in Node.js environment const https = require('https'); const fs = require('fs'); const api = axios.create({ httpsAgent: new https.Agent({ // Don't set to false in production rejectUnauthorized: true, // Use custom CA certificate ca: fs.readFileSync('path/to/ca-cert.pem') }) }); // 3. Certificate Pinning const httpsAgent = new https.Agent({ checkServerIdentity: (host, cert) => { const expectedFingerprint = 'AA:BB:CC:DD:EE:FF:...'; const actualFingerprint = cert.fingerprint256; if (actualFingerprint !== expectedFingerprint) { throw new Error('Certificate fingerprint mismatch'); } } });
5. Request Parameter Validation
javascriptimport Joi from 'joi'; // 1. Request parameter validation const requestSchema = Joi.object({ email: Joi.string().email().required(), password: Joi.string().min(8).max(32).required(), age: Joi.number().integer().min(0).max(150) }); axios.interceptors.request.use((config) => { if (config.data) { const { error } = requestSchema.validate(config.data); if (error) { return Promise.reject(new Error(`Validation error: ${error.message}`)); } } return config; }); // 2. URL parameter encoding axios.interceptors.request.use((config) => { if (config.params) { config.params = Object.keys(config.params).reduce((acc, key) => { acc[key] = encodeURIComponent(config.params[key]); return acc; }, {}); } return config; }); // 3. Prevent SQL injection (frontend level) function sanitizeInput(input) { if (typeof input !== 'string') return input; // Remove or escape dangerous characters return input .replace(/[;\"']/g, '') .replace(/--/g, '') .replace(/\/\*/g, '') .replace(/\*\//g, ''); } axios.interceptors.request.use((config) => { if (config.data) { config.data = Object.keys(config.data).reduce((acc, key) => { acc[key] = sanitizeInput(config.data[key]); return acc; }, {}); } return config; });
6. Response Security Verification
javascript// 1. Verify response content type axios.interceptors.response.use( (response) => { const contentType = response.headers['content-type']; // Ensure response is JSON if (!contentType || !contentType.includes('application/json')) { return Promise.reject(new Error('Invalid content type')); } return response; } ); // 2. Verify response data signature axios.interceptors.response.use( (response) => { const signature = response.headers['x-response-signature']; const data = JSON.stringify(response.data); if (signature && !verifySignature(data, signature)) { return Promise.reject(new Error('Invalid response signature')); } return response; } ); function verifySignature(data, signature) { const expectedSignature = CryptoJS.HmacSHA256(data, SECRET_KEY).toString(); return signature === expectedSignature; }
7. Security Header Settings
javascript// Send security-related request headers const secureApi = axios.create({ headers: { // Prevent MIME type sniffing 'X-Content-Type-Options': 'nosniff', // Enable XSS filter 'X-XSS-Protection': '1; mode=block', // Clickjacking protection 'X-Frame-Options': 'DENY', // Content Security Policy 'Content-Security-Policy': "default-src 'self'", // Strict Transport Security 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains' } });
8. Logging and Monitoring
javascript// Security logging axios.interceptors.request.use((config) => { // Log request (excluding sensitive information) securityLogger.info({ type: 'request', url: config.url, method: config.method, timestamp: new Date().toISOString(), // Don't log sensitive information in headers or data }); return config; }); axios.interceptors.response.use( (response) => { securityLogger.info({ type: 'response', url: response.config.url, status: response.status, timestamp: new Date().toISOString() }); return response; }, (error) => { securityLogger.error({ type: 'error', url: error.config?.url, status: error.response?.status, message: error.message, timestamp: new Date().toISOString() }); return Promise.reject(error); } ); // Anomaly detection function detectAnomalies(response) { // Detect unusually large responses const responseSize = JSON.stringify(response.data).length; if (responseSize > 10 * 1024 * 1024) { // 10MB securityLogger.warn('Unusually large response detected'); } // Detect abnormal response times const duration = response.config.metadata?.duration; if (duration > 30000) { // 30 seconds securityLogger.warn('Slow response detected'); } }
9. Complete Security Configuration Example
javascriptimport axios from 'axios'; import DOMPurify from 'dompurify'; import CryptoJS from 'crypto-js'; const secureApi = axios.create({ baseURL: 'https://api.example.com', timeout: 10000, withCredentials: true, xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN', headers: { 'Content-Type': 'application/json; charset=utf-8', 'X-Content-Type-Options': 'nosniff', 'X-XSS-Protection': '1; mode=block' } }); // Request interceptor - security processing secureApi.interceptors.request.use( (config) => { // 1. Parameter validation and sanitization if (config.data) { config.data = sanitizeData(config.data); } // 2. Add request signature const timestamp = Date.now(); config.headers['X-Timestamp'] = timestamp; config.headers['X-Signature'] = generateRequestSignature(config, timestamp); // 3. Log security event logSecurityEvent('request', config); return config; }, (error) => Promise.reject(error) ); // Response interceptor - security processing secureApi.interceptors.response.use( (response) => { // 1. Verify response signature if (!verifyResponseSignature(response)) { return Promise.reject(new Error('Invalid response signature')); } // 2. XSS sanitization if (response.data) { response.data = sanitizeData(response.data); } // 3. Anomaly detection detectAnomalies(response); return response; }, (error) => { logSecurityEvent('error', null, error); return Promise.reject(error); } ); export default secureApi;
Security Checklist
- Use HTTPS for all data transmission
- Enable CSRF protection
- Store sensitive information using httpOnly Cookie
- Validate and sanitize input data
- Filter output data for XSS
- Set appropriate security headers
- Implement request/response signature verification
- Log security events and monitor anomalies
- Regularly update dependency packages
- Conduct security audits and penetration testing