JavaScript Application Security: Top 10 Vulnerabilities for Beginners
\n\nDevelopment in JavaScript, especially in the Node.js environment, opens up broad opportunities for creating modern web applications. However, with great power comes great responsibility. Ignoring security issues can lead to data leaks, financial losses, and reputational damage. For beginner developers, understanding the main threats is the first step towards creating secure code. In this article, we will break down the top 10 JavaScript (Node.js) vulnerabilities based on the OWASP list, with code examples and practical protection tips.
\n\n1. Cross-Site Scripting (XSS)
\nXSS is one of the most common attacks. An attacker injects a malicious script into a web page, which executes in the victim's browser. In Node.js, this often happens through unescaped data output.
\n\nExample of vulnerable code (Express):
\napp.get('/user/:name', (req, res) => {\n res.send('<h1>Hello, ' + req.params.name + '</h1>');\n});\n\n\nHow to protect: Use template engines with auto-escaping (e.g., Handlebars, EJS) or libraries like helmet. Never insert user input directly into HTML.
app.get('/user/:name', (req, res) => {\n const safeName = encodeURIComponent(req.params.name);\n res.send(`<h1>Hello, ${safeName}</h1>`);\n});\n\n\n2. SQL Injection
\nIf your application uses an SQL database (e.g., PostgreSQL or MySQL), improper query handling can lead to the execution of arbitrary SQL code.
\n\nVulnerable code:
\nconst query = `SELECT * FROM users WHERE email = '${userInput}'`;\ndb.query(query, callback);\n\n\nSolution: Always use parameterized queries or ORMs (e.g., Sequelize, Prisma).
\n\nconst query = 'SELECT * FROM users WHERE email = $1';\ndb.query(query, [userInput], callback);\n\n\n3. Cross-Site Request Forgery (CSRF)
\nA CSRF attack forces a user to perform an unwanted action on a site where they are authenticated. For example, transferring money or changing a password.
\n\nProtection: Use CSRF tokens. In Express, the csurf library was popular (now deprecated, replaced by csrf-csrf or built-in framework solutions).
const csrf = require('csrf-csrf');\nconst { generateToken } = csrf();\n\napp.post('/transfer', (req, res) => {\n const token = req.body._csrf;\n if (!validateToken(token)) {\n return res.status(403).send('CSRF attack');\n }\n // Execute transfer\n});\n\n\n4. Insecure Dependencies
\nNode.js applications use thousands of packages from npm. Outdated or vulnerable dependencies are a common cause of breaches.
\n\nRecommendations:
\n- \n
- Regularly run
npm auditto check for vulnerabilities. \n - Use
snykorDependabotfor automatic updates. \n - Remove unused packages. \n
5. Insecure Authentication and Session Management
\nWeak passwords, lack of login attempt limits, improper storage of session tokens — all of this leads to account compromise.
\n\nBest practices:
\n- \n
- Store passwords in hashed form (bcrypt, argon2). \n
- Use JWT with a short lifespan and refresh tokens. \n
- Set a limit on login attempts (rate limiting). \n
const bcrypt = require('bcrypt');\nconst saltRounds = 10;\n\n// Registration\nconst hash = await bcrypt.hash(password, saltRounds);\n\n// Login\nconst match = await bcrypt.compare(inputPassword, hash);\n\n\n6. Access Control Deficiencies
\nUser