CWE-532 in APIs
- CWE ID
- CWE-532
- Category
- Data Exposure
- Severity
- MEDIUM
- Short Name
- Log Data Leak
What is CWE-532?
CWE-532 describes the insertion of sensitive information into debugging code. This weakness occurs when developers include confidential data—such as passwords, API keys, personal information, or system details—within debug statements, logging mechanisms, or diagnostic code that may be exposed in production environments. The core issue is that debugging information intended for development or troubleshooting purposes contains data that should remain confidential.
The weakness manifests when developers, while troubleshooting issues, embed sensitive information directly into code that outputs diagnostic information. This might include printing passwords to console logs, including authentication tokens in error messages, or logging full request/response payloads containing personal data. The problem compounds when this debug code is accidentally left in production deployments or when debug logs are accessible to unauthorized users.
CWE-532 in API Contexts
APIs are particularly vulnerable to CWE-532 because they often handle authentication, process sensitive data, and generate extensive logs for debugging and monitoring. Several API-specific scenarios commonly exhibit this weakness:
- Authentication debugging: Logging full authentication requests including passwords, API keys, or tokens
- Error message exposure: Including database connection strings, query parameters, or internal system details in API error responses
- Request/response logging: Logging complete HTTP payloads containing PII, credit card numbers, or health information
- Stack trace exposure: Returning full stack traces with file paths, database schemas, or internal implementation details
- Debug endpoints: Creating diagnostic endpoints that expose internal system state, configuration files, or environment variables
Consider a typical authentication endpoint that might inadvertently expose sensitive information:
app.post('/login', (req, res) => {
console.log(`Debug: email=${req.body.email}, password=${req.body.password}`);
const user = authenticate(req.body.email, req.body.password);
if (user) {
res.json({ token: generateToken(user) });
} else {
res.status(401).json({ error: 'Invalid credentials' });
}
});
This code logs the password in plaintext, creating a significant security vulnerability if logs are accessible or if the application is deployed to production without removing debug statements.
Detection
Detecting CWE-532 requires both static code analysis and runtime monitoring. Static analysis tools can scan source code for common patterns like logging sensitive fields, debug statements containing confidential data, or hardcoded credentials in diagnostic code. However, runtime detection is equally important since debug code might be conditionally included or dynamically generated.
middleBrick's black-box scanning approach specifically targets CWE-532 by testing API endpoints for information disclosure through various techniques:
- Authentication bypass testing: Attempting to access debug endpoints or diagnostic information without proper authentication
- Input fuzzing: Sending malformed requests to trigger error messages that might expose sensitive information
- Response analysis: Examining API responses for stack traces, database errors, or internal implementation details
- Metadata extraction: Checking for server headers, framework versions, or other information that could aid attackers
The scanner evaluates whether APIs inadvertently reveal sensitive information through their responses, error messages, or diagnostic endpoints. For example, it might detect if an API returns detailed error messages containing database connection strings or if authentication failures reveal whether an email address exists in the system.
Using middleBrick's CLI tool, developers can scan their APIs for CWE-532 vulnerabilities:
middlebrick scan https://api.example.com/auth/login
The scanner will test the endpoint for information disclosure patterns and provide a security score with specific findings related to sensitive data exposure in debug code or error messages.
Remediation
Remediating CWE-532 requires a systematic approach to eliminate sensitive information from debugging code and implement proper logging practices. Here are key strategies with code examples:
1. Remove Sensitive Data from Logs
The most direct remediation is eliminating sensitive information from all logging statements:
// Vulnerable - logs password
console.log(`User login attempt: ${email}, password: ${password}`);
// Secure - logs only non-sensitive identifiers
console.log(`User login attempt: ${email}`);
2. Implement Structured Logging with Redaction
Use logging frameworks that support structured logging and automatic redaction of sensitive fields:
const logger = require('structured-logger');
// Define sensitive fields to redact
const SENSITIVE_FIELDS = ['password', 'token', 'apiKey', 'ssn'];
function safeLog(obj) {
const redacted = JSON.parse(JSON.stringify(obj));
SENSITIVE_FIELDS.forEach(field => {
if (redacted[field]) {
redacted[field] = '[REDACTED]';
}
});
logger.info('API request', redacted);
}
3. Sanitize Error Messages
Ensure error responses don't expose internal details:
app.post('/api/data', async (req, res) => {
try {
const result = await processData(req.body);
res.json(result);
} catch (error) {
// Vulnerable - exposes internal error details
// res.status(500).json({ error: error.message });
// Secure - generic error message
res.status(500).json({
error: 'Internal server error',
requestId: generateRequestId()
});
}
});
4. Environment-Based Debug Control
Ensure debug code is only active in development environments:
const IS_PRODUCTION = process.env.NODE_ENV === 'production';
function debugLog(message, data) {
if (!IS_PRODUCTION) {
console.log(`DEBUG: ${message}`, data);
}
}
// Usage
debugLog('Processing payment', { amount: 100, userId: req.user.id });
5. Input Validation and Sanitization
Validate and sanitize all inputs before logging or processing:
function sanitizeInput(input) {
return {
email: input.email,
// Exclude password, token, and other sensitive fields
};
}
app.post('/login', (req, res) => {
const sanitized = sanitizeInput(req.body);
console.log(`Login attempt: ${sanitized.email}`);
// Process authentication
});
6. Security Headers and Rate Limiting
Prevent information disclosure through HTTP headers and excessive requests:
app.use((req, res, next) => {
res.set({
'X-Content-Type-Options': 'nosniff',
'X-Frame-Options': 'DENY',
'X-XSS-Protection': '1; mode=block',
'Server': ' ', // Remove server information
});
next();
});