SlideShare a Scribd company logo
2
Most read
3
Most read
6
Most read
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
toString().padStart(width) : cell.padEnd(width); }).join(''))).join
}; const proportion = (max, val) => Math.round(val * 100 / max); co
calcProportion = table => { table.sort((row1, row2) => row2[DENSITY
row1[DENSITY_COL]); const maxDensity = table[0][DENSITY_COL]; table
forEach(row => { row.push(proportion(maxDensity, row[DENSITY_COL]))
return table; }; const getDataset = file => { const lines = fs.read
FileSync(file, 'utf8').toString().split('n'); lines.shift(); lines
return lines.map(line => line.split(',')); }; const main = compose
(getDataset, calcProportion, renderTable); const fs = require('fs'
compose = (...funcs) => x => funcs.reduce((x, fn) => fn(x), x); con
DENSITY_COL = 3; const renderTable = table => { const cellWidth = [
8, 8, 18, 6]; return table.map(row => (row.map((cell, i) => { const
= cellWidth[i]; return i ? cell.toString().padStart(width) : cell.p
(width); }).join(''))).join('n'); }; const proportion = (max, val)
Безопасность
приложений Node.js
Тимур Шемсединов
github.com/HowProgrammingWorks
github.com/tshemsedinov
Chief Software Architect at Metarhia
Lecturer at Kiev Polytechnic Institute
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Аспекты безопасности для Node.js
● Конкурентная модель исполнения I/O
● Уязвимости path traversal повсюду
● SQL injection, XSRF, XSS и другие типичные
● Зависимости: загляните в node_modules
● Утечки ресурсов (приводящие к падению)
● Храним только хеши паролей с солью
● Управляем нагрузкой, иначе встречаем DoS
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Инструменты безопасности для Node.js
● Линтер может кое-что найти
github.com/nodesecurity/eslint-plugin-security
● Умеет искать npm audit и даже исправлять
через npm audit fix
● Специальные инструменты: nsp, snyk
● Githib имеет встроенный Security Alert
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Конкурентная модель
● В одном процессе и одном потоке
выполняется одновременно много запросов
● Все данные в памяти у них общие
● Права у процесса общие
● Переменные окружения и конфиги общие
● Соединения с БД, зависимости и сеть общие
● Падает тоже процесс целиком
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Глобальное состояние
let groupName;
app.use((req, res, next) => {
groupName = 'idiots'; next();
});
app.get('/user', (req, res) => {
if (res.groupName === 'idiots') {
res.end('I know you!');
}
});
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Миксины к req и res
app.use((req, res, next) => {
res.groupName = 'idiots';
next();
});
app.get('/user', (req, res) => {
if (res.groupName === 'idiots') {
res.end('I know you!');
}
});
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Специальное место res.locals
app.use((req, res, next) => {
res.locals.groupName = 'idiots';
next();
});
app.get('/user', (req, res) => {
if (res.locals.groupName === 'idiots') {
res.end('I know you!');
}
});
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Примешивание методов
app.get('/user/:id', (req, res, next) => {
req.auth = (login, password) => { /* auth */ };
next();
});
app.get('/user/:id', (req, res) => {
if (req.auth(req.params.id, '111')) {
res.end('I know you!');
}
});
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Соединение с БД на обработчиках
app.get((req, res, next) => {
req.db = new Pool(config);
next();
});
app.get('/user/:id', (req, res) => {
req.db.query('SELECT * from USERS', (e, r) => {
});
});
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Потеря соединений при ошибках
const db = new Pool(config);
app.get('/user/:id', (req, res) => {
req.db.query('SELECT * from USERS', (err, r) => {
if (err) throw err;
// Prepare data to reply client
});
});
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
Зависимости
● Возможно, встроенные модули умеют
● Пакеты с очень похожими именами
● Зараженные пакеты
● Перед использованием смотрим код
● Смотрим вложенные зависимости
● Проверяем по базам уязвимостей
● Проверяем сообщество и поддержку
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
SQLI (SQL Injection)
Инъекция SQL
Привет! Смотри, что про тебя пишут:
http://bank-web-site.com/accounts?
name='marcus'%20--%20
“SELECT * from Accounts where name=” + name
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
XSRF (Cross-Site Request Forgery)
Межсайтовая подделка запросов
Привет! Смотри, что про тебя пишут:
http://payment-system.com/api/transfer?
amount=1000&destination=card-number
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
XSS (Cross-Site Scripting)
Межсайтовый скриптинг
Привет! Смотри, что про тебя пишут:
http://control-panel.com/help.php?q=
%3Cscript%3Ealert('Hello');%3C/script%3E
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
CSP (Content Security Policy)
В браузеры встроен еще один
уровень защиты от XSS и других типов атак
https://developer.mozilla.org/en-US/docs/
Web/HTTP/CSP
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
На что еще обратить внимание
● httponly cookies
https://www.owasp.org/index.php/HttpOnly
● HTTP Headers:
● X-XSS-Protection
● X-Frame-Options
● X-Content-Type-Options
etc.
const fs = require('fs'); const compose = (...funcs) => x => funcs.
reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab
table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma
=> (row.map((cell, i) => { const width = cellWidth[i]; return i ? c
OWASP (Open Web App. Security Project)
Открытый проект обеспечения безопасности
веб-приложений
https://owasp.org/

More Related Content

PDF
Базы данных в 2020
PDF
Information system structure and architecture
PDF
Введение в программирование (1 часть)
PDF
Почему хорошее ИТ-образование невостребовано рыночком
PDF
Objects have failed
PDF
Node.js in 2019
PDF
Rust: абстракции и безопасность, совершенно бесплатно
PDF
Decorators' recipes
Базы данных в 2020
Information system structure and architecture
Введение в программирование (1 часть)
Почему хорошее ИТ-образование невостребовано рыночком
Objects have failed
Node.js in 2019
Rust: абстракции и безопасность, совершенно бесплатно
Decorators' recipes

What's hot (14)

PPTX
Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, ...
PDF
Оптимизация производительности Python
PDF
5.1 Перегрузка операторов
PDF
Python dict: прошлое, настоящее, будущее
PPT
SciPy
PDF
Магия метаклассов
PPTX
Funny JS #2
PPT
Программирование. Лекция 3
PPTX
Pervoobraznaya i neopredelennyj_integral
PDF
8 встреча — Язык программирования Python (В. Ананьев)
ODP
Charming python sc2-8
PDF
Магия в Python: Дескрипторы. Что это?
ODP
Coroutines
PDF
Векторизация кода (семинар 3)
Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, ...
Оптимизация производительности Python
5.1 Перегрузка операторов
Python dict: прошлое, настоящее, будущее
SciPy
Магия метаклассов
Funny JS #2
Программирование. Лекция 3
Pervoobraznaya i neopredelennyj_integral
8 встреча — Язык программирования Python (В. Ананьев)
Charming python sc2-8
Магия в Python: Дескрипторы. Что это?
Coroutines
Векторизация кода (семинар 3)
Ad

Similar to Node.js security (12)

PDF
DevConf. Дмитрий Сошников - ECMAScript 6
PPTX
Павел Беликов, Как избежать ошибок, используя современный C++
PDF
Лекция 8. Intel Threading Building Blocks
PPTX
Reactive extensions
PPT
Подробная презентация JavaScript 6 в 1
PDF
Перевод базы Caché из 8 бит в Unicode
PPT
Подробная презентация JavaScript 6 в 1
PPTX
Статический анализ кода
PPTX
статический анализ кода
PDF
SECON'2014 - Павел Щеваев - Метаданные и автогенерация кода
PDF
Clojure #2 (2014)
DevConf. Дмитрий Сошников - ECMAScript 6
Павел Беликов, Как избежать ошибок, используя современный C++
Лекция 8. Intel Threading Building Blocks
Reactive extensions
Подробная презентация JavaScript 6 в 1
Перевод базы Caché из 8 бит в Unicode
Подробная презентация JavaScript 6 в 1
Статический анализ кода
статический анализ кода
SECON'2014 - Павел Щеваев - Метаданные и автогенерация кода
Clojure #2 (2014)
Ad

More from Timur Shemsedinov (20)

PDF
How to use Chat GPT in JavaScript optimizations for Node.js
PDF
IT Revolution in 2023-2024: AI, GPT, business transformation, future professi...
PDF
Multithreading in Node.js and JavaScript
PDF
Node.js threads for I/O-bound tasks
PDF
Node.js Меньше сложности, больше надежности Holy.js 2021
PDF
Rethinking low-code
PDF
Hat full of developers
PDF
FwDays 2021: Metarhia Technology Stack for Node.js
PDF
Node.js for enterprise - JS Conference
PDF
Node.js for enterprise 2021 - JavaScript Fwdays 3
PDF
Node.js in 2021
PDF
Node.js middleware: Never again!
PDF
Patterns and antipatterns
PDF
Race-conditions-web-locks-and-shared-memory
PDF
Asynchronous programming and mutlithreading
PDF
Node.js in 2020 - part 3
PDF
Node.js in 2020 - part 2
PDF
Node.js in 2020 - part 1
PDF
Web Locks API
PDF
Node.js in 2020
How to use Chat GPT in JavaScript optimizations for Node.js
IT Revolution in 2023-2024: AI, GPT, business transformation, future professi...
Multithreading in Node.js and JavaScript
Node.js threads for I/O-bound tasks
Node.js Меньше сложности, больше надежности Holy.js 2021
Rethinking low-code
Hat full of developers
FwDays 2021: Metarhia Technology Stack for Node.js
Node.js for enterprise - JS Conference
Node.js for enterprise 2021 - JavaScript Fwdays 3
Node.js in 2021
Node.js middleware: Never again!
Patterns and antipatterns
Race-conditions-web-locks-and-shared-memory
Asynchronous programming and mutlithreading
Node.js in 2020 - part 3
Node.js in 2020 - part 2
Node.js in 2020 - part 1
Web Locks API
Node.js in 2020

Node.js security

  • 1. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c toString().padStart(width) : cell.padEnd(width); }).join(''))).join }; const proportion = (max, val) => Math.round(val * 100 / max); co calcProportion = table => { table.sort((row1, row2) => row2[DENSITY row1[DENSITY_COL]); const maxDensity = table[0][DENSITY_COL]; table forEach(row => { row.push(proportion(maxDensity, row[DENSITY_COL])) return table; }; const getDataset = file => { const lines = fs.read FileSync(file, 'utf8').toString().split('n'); lines.shift(); lines return lines.map(line => line.split(',')); }; const main = compose (getDataset, calcProportion, renderTable); const fs = require('fs' compose = (...funcs) => x => funcs.reduce((x, fn) => fn(x), x); con DENSITY_COL = 3; const renderTable = table => { const cellWidth = [ 8, 8, 18, 6]; return table.map(row => (row.map((cell, i) => { const = cellWidth[i]; return i ? cell.toString().padStart(width) : cell.p (width); }).join(''))).join('n'); }; const proportion = (max, val) Безопасность приложений Node.js Тимур Шемсединов github.com/HowProgrammingWorks github.com/tshemsedinov Chief Software Architect at Metarhia Lecturer at Kiev Polytechnic Institute
  • 2. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Аспекты безопасности для Node.js ● Конкурентная модель исполнения I/O ● Уязвимости path traversal повсюду ● SQL injection, XSRF, XSS и другие типичные ● Зависимости: загляните в node_modules ● Утечки ресурсов (приводящие к падению) ● Храним только хеши паролей с солью ● Управляем нагрузкой, иначе встречаем DoS
  • 3. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Инструменты безопасности для Node.js ● Линтер может кое-что найти github.com/nodesecurity/eslint-plugin-security ● Умеет искать npm audit и даже исправлять через npm audit fix ● Специальные инструменты: nsp, snyk ● Githib имеет встроенный Security Alert
  • 4. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Конкурентная модель ● В одном процессе и одном потоке выполняется одновременно много запросов ● Все данные в памяти у них общие ● Права у процесса общие ● Переменные окружения и конфиги общие ● Соединения с БД, зависимости и сеть общие ● Падает тоже процесс целиком
  • 5. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Глобальное состояние let groupName; app.use((req, res, next) => { groupName = 'idiots'; next(); }); app.get('/user', (req, res) => { if (res.groupName === 'idiots') { res.end('I know you!'); } });
  • 6. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Миксины к req и res app.use((req, res, next) => { res.groupName = 'idiots'; next(); }); app.get('/user', (req, res) => { if (res.groupName === 'idiots') { res.end('I know you!'); } });
  • 7. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Специальное место res.locals app.use((req, res, next) => { res.locals.groupName = 'idiots'; next(); }); app.get('/user', (req, res) => { if (res.locals.groupName === 'idiots') { res.end('I know you!'); } });
  • 8. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Примешивание методов app.get('/user/:id', (req, res, next) => { req.auth = (login, password) => { /* auth */ }; next(); }); app.get('/user/:id', (req, res) => { if (req.auth(req.params.id, '111')) { res.end('I know you!'); } });
  • 9. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Соединение с БД на обработчиках app.get((req, res, next) => { req.db = new Pool(config); next(); }); app.get('/user/:id', (req, res) => { req.db.query('SELECT * from USERS', (e, r) => { }); });
  • 10. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Потеря соединений при ошибках const db = new Pool(config); app.get('/user/:id', (req, res) => { req.db.query('SELECT * from USERS', (err, r) => { if (err) throw err; // Prepare data to reply client }); });
  • 11. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c Зависимости ● Возможно, встроенные модули умеют ● Пакеты с очень похожими именами ● Зараженные пакеты ● Перед использованием смотрим код ● Смотрим вложенные зависимости ● Проверяем по базам уязвимостей ● Проверяем сообщество и поддержку
  • 12. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c SQLI (SQL Injection) Инъекция SQL Привет! Смотри, что про тебя пишут: http://bank-web-site.com/accounts? name='marcus'%20--%20 “SELECT * from Accounts where name=” + name
  • 13. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c XSRF (Cross-Site Request Forgery) Межсайтовая подделка запросов Привет! Смотри, что про тебя пишут: http://payment-system.com/api/transfer? amount=1000&destination=card-number
  • 14. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c XSS (Cross-Site Scripting) Межсайтовый скриптинг Привет! Смотри, что про тебя пишут: http://control-panel.com/help.php?q= %3Cscript%3Ealert('Hello');%3C/script%3E
  • 15. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c CSP (Content Security Policy) В браузеры встроен еще один уровень защиты от XSS и других типов атак https://developer.mozilla.org/en-US/docs/ Web/HTTP/CSP
  • 16. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c На что еще обратить внимание ● httponly cookies https://www.owasp.org/index.php/HttpOnly ● HTTP Headers: ● X-XSS-Protection ● X-Frame-Options ● X-Content-Type-Options etc.
  • 17. const fs = require('fs'); const compose = (...funcs) => x => funcs. reduce((x, fn) => fn(x), x); const DENSITY_COL = 3; const renderTab table => { const cellWidth = [18, 10, 8, 8, 18, 6]; return table.ma => (row.map((cell, i) => { const width = cellWidth[i]; return i ? c OWASP (Open Web App. Security Project) Открытый проект обеспечения безопасности веб-приложений https://owasp.org/