CWE-476 in APIs
- CWE ID
- CWE-476
- Category
- Input Validation
- Severity
- MEDIUM
- Short Name
- Null Deref
What is CWE-476?
CWE-476 refers to the NULL Pointer Dereference weakness, where software dereferences a pointer that it expects to be valid but instead points to NULL. This occurs when an application attempts to access memory through a pointer that has not been initialized, has been explicitly set to NULL, or has become NULL due to a previous operation. When this happens, the application typically crashes with a segmentation fault or access violation error, potentially causing denial of service or allowing an attacker to manipulate the application's state.
CWE-476 in API Contexts
In API development, NULL pointer dereferences can manifest in several critical ways. When an API endpoint receives input that leads to a NULL reference, the entire service may crash, affecting all concurrent users. Common scenarios include:
- Database query failures returning NULL that aren't properly handled before object access
- Missing request parameters that result in NULL objects being passed to business logic
- External service dependencies returning NULL responses that aren't validated
- Authentication middleware failing and returning NULL user objects
For example, an API endpoint might expect a user object from authentication middleware. If authentication fails but the code doesn't check for NULL before accessing user properties, a single failed authentication attempt could crash the entire API service. This is particularly dangerous in serverless or containerized environments where a crash might trigger a restart loop or consume resources unexpectedly.
Detection
Detecting CWE-476 requires both static analysis and runtime testing. Static code analysis tools can identify potential NULL dereferences by tracking variable assignments and control flow paths. However, runtime testing is essential because some NULL conditions only manifest with specific input combinations.
middleBrick's API security scanner includes NULL pointer dereference detection as part of its Input Validation category. The scanner sends crafted requests designed to trigger NULL conditions in your API endpoints, monitoring for crashes, error responses, or abnormal behavior. For example, it might:
- Send requests with missing required parameters
- Submit empty or malformed JSON payloads
- Test authentication bypass attempts that could result in NULL user objects
- Simulate database failures or timeouts
The scanner runs these tests in a sandboxed environment and reports any crashes or error conditions, providing the specific endpoint and request that triggered the issue. This black-box approach requires no source code access or credentials, making it ideal for testing production APIs or third-party services.
Remediation
Fixing NULL pointer dereferences requires defensive programming practices and proper error handling. Here are concrete examples across different API contexts:
// BAD: No NULL check - will crash if user is NULL
app.get('/api/profile', (req, res) => {
const user = req.user; // Could be NULL if auth failed
res.json({ name: user.name, email: user.email }); // Crash!
});
// GOOD: Proper NULL validation
app.get('/api/profile', (req, res) => {
const user = req.user;
if (!user) {
return res.status(401).json({ error: 'Authentication required' });
}
res.json({ name: user.name, email: user.email });
});
// BAD: Assuming database query succeeds
app.get('/api/users/:id', async (req, res) => {
const user = await db.findUser(req.params.id); // Could return NULL
res.json({ name: user.name }); // Crash if user not found
});
// GOOD: Handling database NULL results
app.get('/api/users/:id', async (req, res) => {
const user = await db.findUser(req.params.id);
if (!user) {
return res.status(404).json({ error: 'User not found' });
}
res.json({ name: user.name });
});
// BAD: External service dependency without validation
app.post('/api/translate', async (req, res) => {
const translation = await translationService.translate(req.body.text);
res.json({ result: translation.translatedText }); // Crash if translation is NULL
});
// GOOD: External service error handling
app.post('/api/translate', async (req, res) => {
try {
const translation = await translationService.translate(req.body.text);
if (!translation || !translation.translatedText) {
return res.status(500).json({ error: 'Translation service unavailable' });
}
res.json({ result: translation.translatedText });
} catch (error) {
res.status(500).json({ error: 'Translation failed' });
}
});
Additional best practices include using TypeScript or similar type-safe languages that enforce NULL checks at compile time, implementing comprehensive error boundaries in your API framework, and using the Null Object pattern where appropriate to provide default behavior instead of NULL references.