Path Traversal on Digitalocean
How Path Traversal Manifests in Digitalocean
Path traversal vulnerabilities in Digitalocean applications typically arise from improper validation of file paths in Node.js/Express APIs that interact with Digitalocean's storage services. When user-controlled input is used to construct file paths without proper sanitization, attackers can navigate outside intended directories.
A common pattern in Digitalocean applications involves reading configuration files or serving static assets. Consider this vulnerable Digitalocean Spaces integration:
const { S3Client } = require('@aws-sdk/client-s3');
const { getSignedUrl } = require('@aws-sdk/s3-request-presigner');
const s3Client = new S3Client({
region: 'nyc3',
credentials: { accessKeyId: process.env.SPACES_KEY, secretAccessKey: process.env.SPACES_SECRET }
});
app.get('/download/:filename', async (req, res) => {
const filename = req.params.filename; // No validation!
const params = {
Bucket: 'my-space',
Key: filename
};
try {
const url = await getSignedUrl(s3Client, 'getObject', params);
res.redirect(url);
} catch (err) {
res.status(404).send('File not found');
}
An attacker could request /download/../../etc/passwd to attempt reading sensitive files. While Digitalocean Spaces won't serve arbitrary filesystem files, this pattern becomes dangerous when combined with local file operations or when the application serves files from mounted volumes.
Another Digitalocean-specific scenario involves Spaces CDN URLs with path traversal in query parameters:
app.get('/cdn-proxy', (req, res) => {
const path = req.query.path || 'index.html';
// Vulnerable: path traversal in query parameter
fetch(url).then(r => r.text()).then(text => res.send(text));
This allows attackers to access files outside the intended directory structure by manipulating the path parameter.
Digitalocean-Specific Detection
Detecting path traversal in Digitalocean applications requires both static analysis and runtime scanning. middleBrick's black-box scanner identifies these vulnerabilities by testing unauthenticated endpoints with path traversal payloads.
For Digitalocean Spaces applications, middleBrick tests common traversal patterns:
../../etc/passwd
../windows/win.ini
....//....//etc/passwd
./././etc/passwd
WEB-INF/web.xmlThe scanner examines how the application handles these requests, looking for:
- Information disclosure through error messages
- Unexpected redirects to sensitive locations
- HTTP 200 responses containing sensitive data
- Differentiated error responses that reveal file existence
For Digitalocean App Platform deployments, middleBrick also checks for:
- Environment variable exposure through traversal
- Access to .do files (Digitalocean configuration files)
- Traversal in Dockerfile paths during build processes
Manual testing should include:
curl -v 'https://your-app.digitalocean.app/download/../../etc/passwd'
curl -v 'https://your-app.digitalocean.app/download/..%2f..%2fetc%2fpasswd' # URL encodedDigitalocean's Spaces API has built-in protections, but applications often add layers that reintroduce vulnerabilities. middleBrick's OpenAPI analysis can identify risky path parameters in your API specification that might be vulnerable to traversal attacks.
Digitalocean-Specific Remediation
Remediating path traversal in Digitalocean applications requires input validation and safe path handling. Here are Digitalocean-specific fixes:
1. Input Validation with Pathname Module
const { S3Client } = require('@aws-sdk/client-s3');
const path = require('path');
const s3Client = new S3Client({
region: 'nyc3',
credentials: { accessKeyId: process.env.SPACES_KEY, secretAccessKey: process.env.SPACES_SECRET }
});
app.get('/download/:filename', async (req, res) => {
const filename = req.params.filename;
// Validate: only allow alphanumeric, hyphens, underscores, and dots
if (!/^[a-zA-Z0-9._-]+$/.test(filename)) {
return res.status(400).send('Invalid filename');
}
// Prevent traversal by resolving and checking prefix
const safePath = path.normalize(filename);
if (safePath.startsWith('.') || safePath.includes('..')) {
return res.status(400).send('Invalid path');
}
const params = {
Bucket: 'my-space',
Key: safePath
};
try {
const url = await getSignedUrl(s3Client, 'getObject', params);
res.redirect(url);
} catch (err) {
res.status(404).send('File not found');
}
2. Using Digitalocean's Built-in Security Features
Digitalocean App Platform provides security configurations that help prevent traversal attacks:
# app.yaml for Digitalocean App Platform
name: my-app
region: nyc
services:
- name: api
git:
repo_clone_url: https://github.com/your-org/your-repo.git
branch: main
build_command: npm run build
run_command: npm start
health_check_path: /health
environment_variables:
scope: RUN_TIME
value: production
# Security hardening
3. Safe Path Construction with Digitalocean Spaces
const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
const s3Client = new S3Client({
region: 'nyc3',
credentials: {
accessKeyId: process.env.SPACES_KEY,
secretAccessKey: process.env.SPACES_SECRET
}
});
function safeDownload(filename) {
// Whitelist allowed characters
if (!/^[a-zA-Z0-9_.-]+$/.test(filename)) {
throw new Error('Invalid characters in filename');
}
// Resolve to absolute path within allowed directory
const baseDir = 'uploads/';
const fullPath = path.join(baseDir, filename);
// Verify the resolved path is within the base directory
if (!fullPath.startsWith(baseDir)) {
throw new Error('Path traversal attempt detected');
}
return fullPath;
}
app.get('/secure-download/:filename', async (req, res) => {
try {
const safePath = safeDownload(req.params.filename);
const params = {
Bucket: 'my-space',
Key: safePath
};
const data = await s3Client.send(new GetObjectCommand(params));
res.attachment(safePath.split('/').pop());
data.Body.pipe(res);
} catch (err) {
res.status(400).send('Invalid request');
}
Related CWEs: inputValidation
| CWE ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |
Frequently Asked Questions
How does Digitalocean Spaces prevent path traversal attacks?
Digitalocean Spaces implements object storage security at the S3-compatible API level. It doesn't allow access to the underlying filesystem, so traditional path traversal to read system files isn't possible. However, applications can still be vulnerable if they construct object keys from user input without validation. Spaces will only return objects that exist in your bucket with the exact key name provided. The security responsibility shifts to your application code to validate and sanitize input before constructing object keys or local file paths.
Can middleBrick scan my Digitalocean App Platform deployment for path traversal?
Yes, middleBrick can scan any publicly accessible API endpoint, including those deployed on Digitalocean App Platform. Simply provide the URL of your deployed application. The scanner tests for path traversal by sending payloads like ../../etc/passwd and ../windows/win.ini to your endpoints. It analyzes the responses to detect information disclosure, unexpected behavior, or server errors that might indicate a vulnerability. middleBrick's scanning takes 5-15 seconds and requires no credentials or configuration.