CWE-79 in APIs
What is Cwe 79?
Cwe 79, officially titled Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting'), is a critical web application vulnerability that occurs when an application fails to properly validate or escape user-supplied data before embedding it in web pages. This weakness allows attackers to inject malicious scripts that execute in the context of other users' browsers.
The vulnerability stems from the application's inability to distinguish between trusted and untrusted data. When user input containing executable code (typically JavaScript, but also HTML, CSS, or other scripting languages) is rendered without proper sanitization, the browser interprets it as legitimate content rather than malicious code. This enables attackers to steal session cookies, redirect users to phishing sites, deface web pages, or perform actions on behalf of authenticated users.
Cwe 79 manifests in three primary forms: stored XSS (malicious scripts saved in the application's database and served to multiple users), reflected XSS (scripts embedded in URLs or form submissions and immediately reflected back to the user), and DOM-based XSS (client-side scripts that manipulate the DOM using unsafe user input). The weakness affects applications that dynamically generate HTML content without adequate output encoding or input validation mechanisms.
Cwe 79 in API Contexts
While Cwe 79 is traditionally associated with web applications, APIs face unique XSS risks when they serve as data sources for client-side applications or when they directly return HTML content. API developers must understand how this weakness manifests in their specific context to prevent exploitation.
APIs commonly encounter Cwe 79 when they return user-generated content without proper sanitization. Consider an API endpoint that returns user comments, product reviews, or profile information. If this data contains malicious scripts and the API doesn't sanitize or encode the output, client applications consuming the API will render these scripts when displaying the data.
// Vulnerable API endpoint
app.get('/api/comments/:id', (req, res) => {
const comment = db.getComment(req.params.id);
res.json({ content: comment.text }); // No sanitization
});This weakness becomes particularly dangerous when APIs serve single-page applications (SPAs) or mobile apps that render HTML content. An attacker could inject scripts that steal authentication tokens stored in localStorage, intercept API calls, or manipulate the application's behavior. Additionally, APIs that generate HTML emails, PDF reports, or other documents from user input create XSS opportunities if they fail to properly escape special characters.
APIs also face XSS risks through reflected input in error messages, documentation examples, or help endpoints. When APIs echo back user input in responses without validation, they create attack vectors for reflected XSS. This is especially problematic for debugging endpoints or API explorers that display user-supplied data in web interfaces.
Detection
Detecting Cwe 79 requires a combination of automated scanning and manual testing techniques. Security scanners can identify potential XSS vulnerabilities by injecting test payloads and analyzing responses for script execution indicators.
Automated detection tools typically test for XSS by submitting payloads containing common JavaScript patterns, HTML tags, and event handlers. They look for indicators such as script tags appearing in responses, alert() functions triggering, or HTTP headers that suggest XSS protection is disabled. Effective scanners test multiple injection points including query parameters, request bodies, headers, and file uploads.
middleBrick provides comprehensive XSS detection through its 12-point security assessment framework. The scanner automatically tests for Cwe 79 by injecting payloads across all API endpoints and analyzing responses for script execution vulnerabilities. middleBrick's approach includes:
- Testing for stored XSS by submitting payloads that would be saved and later retrieved
- Checking for reflected XSS through parameter manipulation
- Analyzing response headers for proper Content-Security-Policy implementation
- Verifying that user input is properly encoded before being returned in API responses
- Testing for DOM-based XSS scenarios where client-side code might process unsafe input
middleBrick's scanning process takes 5–15 seconds and provides a security risk score (A–F) with specific findings for XSS vulnerabilities. The scanner tests unauthenticated endpoints to identify the attack surface available to potential attackers, then provides actionable remediation guidance for any XSS weaknesses discovered.
Manual testing complements automated scanning by examining specific business logic and user workflows that automated tools might miss. Developers should test API endpoints that handle user-generated content, examine how the application handles special characters, and verify that output encoding is consistently applied across all response types.
Remediation
Preventing Cwe 79 requires a defense-in-depth approach that combines input validation, output encoding, and secure coding practices. The most effective remediation strategy depends on the specific context where user input is used.
Output Encoding (Recommended Approach): The most reliable defense against XSS is to encode user input before rendering it in HTML, JavaScript, or other contexts. Use appropriate encoding functions for each context:
// Node.js with DOMPurify for HTML content
const DOMPurify = require('dompurify');
// Sanitize HTML content before returning
app.get('/api/comments/:id', (req, res) => {
const comment = db.getComment(req.params.id);
const cleanContent = DOMPurify.sanitize(comment.text);
res.json({ content: cleanContent });
});
// URL encoding for attributes
app.get('/api/user/:username', (req, res) => {
const username = req.params.username;
const encodedUsername = encodeURIComponent(username);
res.json({ profileUrl: `/user/${encodedUsername}` });
});Content Security Policy (CSP): Implement a strong Content-Security-Policy header to restrict where scripts can be loaded from and what inline scripts are allowed:
app.use((req, res, next) => {
res.setHeader('Content-Security-Policy',
"default-src 'self'; script-src 'self' https://trusted-cdn.com; " +
"style-src 'self' 'unsafe-inline'; img-src *;"
);
next();
});Input Validation: Validate and sanitize user input based on expected formats. Reject input that contains suspicious patterns or exceeds reasonable length limits:
const { sanitize, validation } = require('xss-clean');
// Middleware to sanitize request bodies
app.use(sanitize());
// Validate specific fields
app.post('/api/comments', (req, res) => {
const { text } = req.body;
if (!validation.isLength(text, { min: 1, max: 1000 })) {
return res.status(400).json({ error: 'Comment too long' });
}
// Additional custom validation for allowed HTML
const allowedTags = ['b', 'i', 'u', 'em', 'strong'];
const cleanText = DOMPurify.sanitize(text, { ALLOWED_TAGS: allowedTags });
const comment = db.createComment(cleanText);
res.status(201).json(comment);
});Framework-Specific Solutions: Leverage framework security features when available. Many modern frameworks provide built-in XSS protection:
# Django template auto-escaping
<p>{{ comment.text|safe }}{% if not comment.is_safe %}</p>
# React JSX auto-escaping
const Comment = ({ text }) => (
<div>{text}</div>
);Security Headers: Implement additional security headers to mitigate XSS impact:
app.use((req, res, next) => {
res.setHeader('X-XSS-Protection', '1; mode=block');
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
next();
});Regular security scanning with tools like middleBrick helps verify that XSS protections remain effective as code evolves. The scanner's continuous monitoring capabilities can alert developers when new XSS vulnerabilities are introduced during development or deployment.