Security of JavaScript Applications: Top 10 Vulnerabilities
JavaScript, especially in the Node.js environment, has become the foundation of modern web development. However, its popularity makes applications an attractive target for attacks. Ignoring security issues can lead to data leaks, financial losses, and reputational damage. In this article, we will analyze the top 10 most critical vulnerabilities of JavaScript (Node.js) applications, based on the OWASP Top 10 standard, and show how to prevent them using code examples.
1. Injection
Injections remain one of the most dangerous threats. In the context of Node.js, SQL injections and NoSQL injections (for example, in MongoDB) are most common.
Problem
Direct concatenation of user input into database queries allows an attacker to execute arbitrary code.
Example of vulnerable code
const user = req.body.username;const query = `SELECT * FROM users WHERE username = '${user}'`;db.query(query, callback);Solution
Use parameterized queries or ORM/ODM. For MongoDB, use mongo-sanitize.
const query = 'SELECT * FROM users WHERE username = $1';db.query(query, [user], callback);2. Broken Authentication and Session Management
Weak authentication is a direct path to account compromise.
Problem
Using predictable tokens (e.g., JWT with the none algorithm), storing passwords in plain text, or lacking a limit on the number of login attempts.
Example of vulnerability
// JWT without algorithm verificationconst token = jwt.sign({ user: 'admin' }, 'secret', { algorithm: 'none' });Solution
- Always verify the JWT algorithm:
jwt.verify(token, secret, { algorithms: ['HS256'] }). - Store passwords using
bcryptorargon2. - Implement a login attempt limit (
express-rate-limit).
const bcrypt = require('bcrypt');const saltRounds = 10;const hash = await bcrypt.hash(password, saltRounds);3. XSS (Cross-Site Scripting)
XSS allows injecting a malicious script into a web page, which then executes in the victim's browser.
Problem
Outputting user content without escaping, especially when using Server-Side Rendering (SSR) in Next.js or Nuxt.js.
Vulnerable code (Express)
res.send(`<h1>Hello, ${req.query.name}</h1>`);Solution
- Escape output: use libraries like
escape-htmlor template engines with auto-escaping (EJS, Pug). - Set the CSP (Content Security Policy) header:
helmet.contentSecurityPolicy().
const helmet = require('helmet');app.use(helmet.contentSecurityPolicy({ directives: { defaultSrc: ["'self'"] }}));4. Insecure Direct Object References (IDOR)
A vulnerability occurs when a user can access objects (files, database records) by knowing or guessing their identifier.
Example
app.get('/api/user/:id', (req, res) => { // No check that req.user.id === req.params.id const user = db.findUser(req.params.id); res.json(user);});Solution
Always check access rights at the server level.
if (req.user.id !== req.params.id) { return res.status(403).send('Forbidden');}5. Security Misconfiguration
This includes using default credentials, debug modes in production, and incorrect CORS settings.
Problem
// Open CORSapp.use(cors({ origin: '*' }));