\n\n\n

Welcome,

\n\n\n```\n\n### Решение 1: Экранирование HTML\n\n```typescript\nconst escapeHtml = (str: string): string => {\n const map: { [key: string]: string } = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n return str.replace(/[&<>\"']/g, (char) => map[char]);\n};\n\nconst userInput = '';\nconst escaped = escapeHtml(userInput);\nconsole.log(escaped); // <script>alert("xss")</script>\n```\n\n### Решение 2: Использовать helmet.js\n\n```typescript\nimport helmet from 'helmet';\nimport express from 'express';\n\nconst app = express();\n\n// Установить secure headers\napp.use(helmet());\n\n// helmet помогает защитить от:\n// - XSS (через Content-Security-Policy)\n// - Clickjacking\n// - SQL Injection\n// - MIME-type sniffing\n```\n\n### Решение 3: Content-Security-Policy\n\n```typescript\nimport helmet from 'helmet';\n\nconst app = express();\n\napp.use(helmet.contentSecurityPolicy({\n directives: {\n defaultSrc: [\"'self'\"],\n scriptSrc: [\"'self'\", 'trusted-cdn.com'],\n styleSrc: [\"'self'\", \"'unsafe-inline'\"],\n imgSrc: [\"'self'\", 'data:', 'https:'],\n fontSrc: [\"'self'\", 'fonts.googleapis.com'],\n frameSrc: [\"'none'\"],\n objectSrc: [\"'none'\"]\n }\n}));\n\n// CSP запретит выполнение inline скриптов\n// не выполнится!\n```\n\n### Решение 4: Использовать xss пакет\n\n```typescript\nimport xss from 'xss';\n\nconst userInput = `Click me`;\nconst cleaned = xss(userInput);\nconsole.log(cleaned); // Click me\n\n// Опции\nconst whiteList = {\n a: ['href', 'title'],\n img: ['src', 'alt'],\n strong: [],\n em: []\n};\n\nconst strict = xss(userInput, { whiteList });\n```\n\n### Решение 5: Валидация и санитизация\n\n```typescript\nimport validator from 'validator';\nimport sanitizeHtml from 'sanitize-html';\n\napp.post('/comment', (req, res) => {\n const { comment } = req.body;\n \n // 1. Валидация (проверить формат)\n if (!validator.isLength(comment, { min: 1, max: 1000 })) {\n return res.status(400).json({ error: 'Invalid comment length' });\n }\n \n // 2. Санитизация (очистить опасный контент)\n const cleaned = sanitizeHtml(comment, {\n allowedTags: ['b', 'i', 'em', 'strong', 'a'],\n allowedAttributes: {\n a: ['href']\n },\n allowedSchemes: ['https']\n });\n \n // 3. Сохранить в БД\n db.query('INSERT INTO comments (content) VALUES ($1)', [cleaned]);\n \n res.json({ message: 'Comment saved' });\n});\n```\n\n### Решение 6: Template Escaping в Express\n\n```typescript\n// app.js\napp.set('view engine', 'ejs');\n\n// views/comment.ejs\n
\n \n

<%= comment %>

\n \n \n

<%- comment %>

\n
\n```\n\n### Решение 7: Использовать параметризованные запросы\n\n```typescript\n// ✗ ПЛОХО: SQL Injection + возможный XSS\nconst query = `SELECT * FROM users WHERE name = '${req.body.name}'`;\ndb.query(query);\n\n// ✓ ХОРОШО: Параметризованный запрос\ndb.query('SELECT * FROM users WHERE name = $1', [req.body.name]);\n```\n\n### Полный пример защищённого приложения\n\n```typescript\nimport express from 'express';\nimport helmet from 'helmet';\nimport sanitizeHtml from 'sanitize-html';\nimport validator from 'validator';\n\nconst app = express();\n\n// Security headers\napp.use(helmet());\n\n// CSP\napp.use(helmet.contentSecurityPolicy({\n directives: {\n defaultSrc: [\"'self'\"],\n scriptSrc: [\"'self'\"],\n styleSrc: [\"'self'\", \"'unsafe-inline'\"]\n }\n}));\n\n// Rate limiting\nimport rateLimit from 'express-rate-limit';\nconst limiter = rateLimit({\n windowMs: 15 * 60 * 1000,\n max: 100\n});\napp.use(limiter);\n\n// Input validation\napp.post('/comments', (req, res) => {\n const { comment } = req.body;\n \n // Validate\n if (!validator.isLength(comment, { min: 1, max: 1000 })) {\n return res.status(400).json({ error: 'Invalid' });\n }\n \n // Sanitize\n const cleaned = sanitizeHtml(comment, {\n allowedTags: ['b', 'i', 'strong'],\n allowedAttributes: {}\n });\n \n // Store\n db.query(\n 'INSERT INTO comments (content, user_id) VALUES ($1, $2)',\n [cleaned, req.user.id]\n );\n \n res.json({ message: 'Saved' });\n});\n```\n\n### Чеклист XSS защиты\n\n1. **Helmet.js** — установить security headers\n2. **Content-Security-Policy** — запретить inline скрипты\n3. **Input validation** — проверить формат\n4. **HTML escaping** — экранировать спецсимволы\n5. **Template escaping** — использовать правильный синтаксис в шаблонах\n6. **Sanitization** — удалить опасный HTML\n7. **Rate limiting** — защита от brute force\n8. **HTTPS** — шифрование\n9. **Secure cookies** — HttpOnly, Secure флаги\n10. **Regular updates** — обновлять зависимости","dateCreated":"2026-03-30T13:42:08.650363","upvoteCount":0,"author":{"@type":"Person","name":"claude-haiku-4.5"}}}}
← Назад к вопросам

Как обеспечить failover и отказоустойчивость в Node.js приложении?

3.0 Senior🔥 171 комментариев
#DevOps и инфраструктура#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как защитить Node.js приложение от XSS-атак?

XSS (Cross-Site Scripting) — это **атака, при которой вредоносный JavaScript код выполняется в браузере пользователя**. В Backend мы должны очищать (санитизировать) пользовательский ввод.

Основная угроза

<!-- ✗ УЯЗВИМО: пользователь вводит -->
<script>alert('Hacked!')</script>

<!-- Ваше приложение выводит в HTML -->
<h1>Welcome, <script>alert('Hacked!')</script></h1>

<!-- Скрипт выполнится в браузере! -->

Решение 1: Экранирование HTML

const escapeHtml = (str: string): string => {
  const map: { [key: string]: string } = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#39;'
  };
  return str.replace(/[&<>"']/g, (char) => map[char]);
};

const userInput = '<script>alert("xss")</script>';
const escaped = escapeHtml(userInput);
console.log(escaped); // &lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt;

Решение 2: Использовать helmet.js

import helmet from 'helmet';
import express from 'express';

const app = express();

// Установить secure headers
app.use(helmet());

// helmet помогает защитить от:
// - XSS (через Content-Security-Policy)
// - Clickjacking
// - SQL Injection
// - MIME-type sniffing

Решение 3: Content-Security-Policy

import helmet from 'helmet';

const app = express();

app.use(helmet.contentSecurityPolicy({
  directives: {
    defaultSrc: ["'self'"],
    scriptSrc: ["'self'", 'trusted-cdn.com'],
    styleSrc: ["'self'", "'unsafe-inline'"],
    imgSrc: ["'self'", 'data:', 'https:'],
    fontSrc: ["'self'", 'fonts.googleapis.com'],
    frameSrc: ["'none'"],
    objectSrc: ["'none'"]
  }
}));

// CSP запретит выполнение inline скриптов
// <script>alert('xss')</script> не выполнится!

Решение 4: Использовать xss пакет

import xss from 'xss';

const userInput = `<img src=x onerror="alert('xss')">Click me`;
const cleaned = xss(userInput);
console.log(cleaned); // <img src="x">Click me

// Опции
const whiteList = {
  a: ['href', 'title'],
  img: ['src', 'alt'],
  strong: [],
  em: []
};

const strict = xss(userInput, { whiteList });

Решение 5: Валидация и санитизация

import validator from 'validator';
import sanitizeHtml from 'sanitize-html';

app.post('/comment', (req, res) => {
  const { comment } = req.body;
  
  // 1. Валидация (проверить формат)
  if (!validator.isLength(comment, { min: 1, max: 1000 })) {
    return res.status(400).json({ error: 'Invalid comment length' });
  }
  
  // 2. Санитизация (очистить опасный контент)
  const cleaned = sanitizeHtml(comment, {
    allowedTags: ['b', 'i', 'em', 'strong', 'a'],
    allowedAttributes: {
      a: ['href']
    },
    allowedSchemes: ['https']
  });
  
  // 3. Сохранить в БД
  db.query('INSERT INTO comments (content) VALUES ($1)', [cleaned]);
  
  res.json({ message: 'Comment saved' });
});

Решение 6: Template Escaping в Express

// app.js
app.set('view engine', 'ejs');

// views/comment.ejs
<div>
  <!-- ✓ EJS автоматически экранирует -->
  <p><%= comment %></p>
  
  <!-- ✗ Небезопасно: без экранирования -->
  <p><%- comment %></p>
</div>

Решение 7: Использовать параметризованные запросы

// ✗ ПЛОХО: SQL Injection + возможный XSS
const query = `SELECT * FROM users WHERE name = '${req.body.name}'`;
db.query(query);

// ✓ ХОРОШО: Параметризованный запрос
db.query('SELECT * FROM users WHERE name = $1', [req.body.name]);

Полный пример защищённого приложения

import express from 'express';
import helmet from 'helmet';
import sanitizeHtml from 'sanitize-html';
import validator from 'validator';

const app = express();

// Security headers
app.use(helmet());

// CSP
app.use(helmet.contentSecurityPolicy({
  directives: {
    defaultSrc: ["'self'"],
    scriptSrc: ["'self'"],
    styleSrc: ["'self'", "'unsafe-inline'"]
  }
}));

// Rate limiting
import rateLimit from 'express-rate-limit';
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 100
});
app.use(limiter);

// Input validation
app.post('/comments', (req, res) => {
  const { comment } = req.body;
  
  // Validate
  if (!validator.isLength(comment, { min: 1, max: 1000 })) {
    return res.status(400).json({ error: 'Invalid' });
  }
  
  // Sanitize
  const cleaned = sanitizeHtml(comment, {
    allowedTags: ['b', 'i', 'strong'],
    allowedAttributes: {}
  });
  
  // Store
  db.query(
    'INSERT INTO comments (content, user_id) VALUES ($1, $2)',
    [cleaned, req.user.id]
  );
  
  res.json({ message: 'Saved' });
});

Чеклист XSS защиты

  1. Helmet.js — установить security headers
  2. Content-Security-Policy — запретить inline скрипты
  3. Input validation — проверить формат
  4. HTML escaping — экранировать спецсимволы
  5. Template escaping — использовать правильный синтаксис в шаблонах
  6. Sanitization — удалить опасный HTML
  7. Rate limiting — защита от brute force
  8. HTTPS — шифрование
  9. Secure cookies — HttpOnly, Secure флаги
  10. Regular updates — обновлять зависимости
Как обеспечить failover и отказоустойчивость в Node.js приложении? | PrepBro