阿里云主机折上折
  • 微信号
Current Site:Index > Secure coding standards

Secure coding standards

Author:Chuan Chen 阅读数:58283人阅读 分类: JavaScript

JavaScript, as a dynamic, weakly typed scripting language, can easily lead to security vulnerabilities due to non-standard coding practices during development. Adhering to secure coding standards can effectively reduce potential risks and improve code quality and application security.

Variable Declaration and Scope Control

Always use const and let instead of var to declare variables, avoiding hoisting and global pollution. For constants that need protection, use Object.freeze() for deep freezing:

// Unsafe practice
var apiKey = '12345'; 

// Safe practice
const CONFIG = Object.freeze({
  API_KEY: '12345',
  MAX_RETRY: 3
});

// Attempts to modify will fail silently
CONFIG.API_KEY = 'hack'; // Throws an error in strict mode

Avoid declaring global variables within function scope by using IIFE to encapsulate sensitive operations:

(function() {
  const secretToken = generateToken();
  // Secure scope operations
})();

Input Validation and Sanitization

Treat all external inputs as untrusted data. Use strict validation libraries like Joi or Yup:

import * as yup from 'yup';

const userSchema = yup.object().shape({
  username: yup.string()
    .required()
    .matches(/^[a-zA-Z0-9_]+$/, 'Only alphanumeric characters and underscores allowed'),
  age: yup.number()
    .integer()
    .min(13)
    .max(120)
});

// Validation example
try {
  await userSchema.validate({
    username: "admin'--",
    age: "25"
  });
} catch (err) {
  console.error('Validation failed:', err.errors);
}

For DOM operations, always escape dynamic content:

function safeHTML(str) {
  const div = document.createElement('div');
  div.textContent = str;
  return div.innerHTML;
}

document.getElementById('output').innerHTML = safeHTML(userInput);

Secure Communication and Data Handling

Use HTTPS and avoid storing sensitive information on the frontend. For necessary API keys, consider using HttpOnly Cookies:

// Unsafe
localStorage.setItem('auth_token', 'Bearer xyz');

// Relatively safe
fetch('/api/login', {
  method: 'POST',
  credentials: 'include',  // Works with backend HttpOnly Cookies
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ /* data */ })
});

For encrypting sensitive data, use the Web Crypto API instead of custom algorithms:

async function hashPassword(password) {
  const encoder = new TextEncoder();
  const data = encoder.encode(password + process.env.SALT);
  const hash = await crypto.subtle.digest('SHA-256', data);
  return Array.from(new Uint8Array(hash))
    .map(b => b.toString(16).padStart(2, '0'))
    .join('');
}

Preventing XSS Attacks

Modern frameworks like React/Vue provide basic protection, but dangerous scenarios still require attention:

// Dangerous operation example in React
function UnsafeComponent({ userInput }) {
  // Wrong approach
  return <div dangerouslySetInnerHTML={{ __html: userInput }} />;
  
  // Correct approach
  return <div>{userInput}</div>; // Automatic escaping
}

When dynamically creating scripts, use textContent instead of innerHTML:

const script = document.createElement('script');
script.textContent = 'console.log("Safe execution")';
document.body.appendChild(script);

Preventing CSRF Attacks

Implement CSRF token mechanisms and integrate them with frameworks:

// Frontend token retrieval
let csrfToken = document.querySelector('meta[name="csrf-token"]').content;

// Include token in requests
fetch('/api/transfer', {
  method: 'POST',
  headers: {
    'X-CSRF-Token': csrfToken,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ amount: 100 })
});

Dependency Management Security

Regularly use npm audit to check dependencies and lock versions:

{
  "dependencies": {
    "lodash": "4.17.21",  // Fixed version
    "react": "^18.2.0"    // Allow patch updates
  }
}

Use Content Security Policy (CSP) for enhanced protection:

<meta http-equiv="Content-Security-Policy" 
      content="default-src 'self'; script-src 'self' 'unsafe-inline' cdn.example.com;">

Error Handling and Logging

Avoid exposing sensitive information in error messages:

try {
  await criticalOperation();
} catch (err) {
  // Unsafe
  console.error(`Operation failed: ${err.stack}`);
  
  // Safe approach
  console.error('Operation failed: System error');
  sendToMonitoring({
    errorCode: 'E500',
    timestamp: Date.now()
  });
}

Performance and Memory Safety

Avoid common memory leak patterns:

// Event listener leaks
window.addEventListener('resize', heavyCalculation);

// Correct approach
const debouncedCalc = debounce(heavyCalculation, 200);
window.addEventListener('resize', debouncedCalc);

// Cleanup on component unmount
window.removeEventListener('resize', debouncedCalc);

Use streaming APIs for handling large files:

async function processFile(file) {
  const stream = file.stream();
  const reader = stream.getReader();
  
  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    // Process data in chunks
  }
}

Secure Practices with Modern APIs

Use structuredClone instead of JSON.parse(JSON.stringify()) for deep copying:

const original = new Set([1, 2, new Map([[3, 4]])]);
const copy = structuredClone(original);  // Preserves reference relationships

Validate message sources in Worker communication:

// worker.js
self.onmessage = (event) => {
  if (event.origin !== window.location.origin) return;
  // Safely handle messages
};

Enhancing Type Safety

Even with JavaScript, consider type checking:

// Use JSDoc to enhance type safety
/**
 * @param {string} url
 * @param {{ method?: string, body?: object }} options
 * @returns {Promise<{ data: any, status: number }>}
 */
async function safeFetch(url, options = {}) {
  // Implementation
}

Browser Storage Standards

Differentiate storage usage for different scenarios:

// Session-level data
sessionStorage.setItem('temp_data', JSON.stringify({ tabState: 'active' }));

// Long-term preferences
localStorage.setItem('user_prefs', JSON.stringify({
  theme: 'dark',
  fontSize: 14
}));

// Sensitive data
const secureStore = {
  set(key, value) {
    crypto.subtle.encrypt(/* encryption parameters */)
      .then(ciphertext => {
        localStorage.setItem(key, ciphertext);
      });
  }
};

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

上一篇:性能优化建议

下一篇:代码复用原则

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.