Filesystem Security Checks
Filesystem security checks identify vulnerabilities that could allow attackers to access files outside intended directories or read sensitive system files.
fs-sensitive-path
Severity: High
What It Detects
Access to sensitive file paths:
- SSH configuration (
~/.ssh/) - AWS credentials (
~/.aws/) - GPG keys (
~/.gnupg/) - Kubernetes configs (
~/.kube/) - Environment files (
.env) - System credential files
Why It's Dangerous
Accessing sensitive paths can expose:
- Private SSH keys (server access)
- Cloud credentials (AWS, GCP, Azure)
- Database passwords
- API keys and tokens
- Application secrets
Example Vulnerable Code
// Reading SSH keys
const sshKey = fs.readFileSync(`${homeDir}/.ssh/id_rsa`); // DANGEROUS!
// Reading AWS credentials
const awsCreds = fs.readFileSync(`${homeDir}/.aws/credentials`); // DANGEROUS!
// Reading environment files
const envContent = fs.readFileSync('.env'); // DANGEROUS if exposed!Safe Alternative
// Don't read credential files directly
// Instead, use environment variables or SDKs
// For AWS - use SDK's built-in credential chain
import { fromEnv, fromIni } from '@aws-sdk/credential-providers';
const client = new S3Client({
credentials: fromEnv(), // Reads from environment
});
// For SSH - use ssh-agent or credential helpers
import { createAgent } from 'ssh-agent';
const agent = await createAgent();
// For configuration - use environment variables
const dbPassword = process.env.DB_PASSWORD;fs-path-traversal
Severity: High
What It Detects
Path traversal patterns:
../sequences that could escape directories- Unsanitized path concatenation
- User input in file paths
Why It's Dangerous
Path traversal allows attackers to:
- Read files outside the intended directory
- Access system files (
/etc/passwd) - Read application secrets
- Potentially write to arbitrary locations
Example Vulnerable Code
// User-controlled file path
const fileName = req.query.file;
const content = fs.readFileSync(`./uploads/${fileName}`); // DANGEROUS!
// Attacker input: "../../../etc/passwd"
// Path concatenation without validation
const filePath = userDir + '/' + userFile;
const data = fs.readFileSync(filePath); // DANGEROUS!
// Template with user input
const templatePath = `./templates/${userTemplate}.html`;Safe Alternative
import path from 'path';
// Resolve and validate the path
const baseDir = path.resolve('./uploads');
const requestedPath = path.resolve(baseDir, fileName);
// Ensure path is within allowed directory
if (!requestedPath.startsWith(baseDir)) {
throw new Error('Invalid file path');
}
const content = fs.readFileSync(requestedPath);More robust solution:
import path from 'path';
function getSafePath(baseDir, userPath) {
// Resolve both paths to absolute
const base = path.resolve(baseDir);
const full = path.resolve(base, userPath);
// Check that resolved path starts with base
if (!full.startsWith(base + path.sep) && full !== base) {
throw new Error('Path traversal attempt detected');
}
// Additional check: no .. in the resolved path
const relative = path.relative(base, full);
if (relative.startsWith('..')) {
throw new Error('Invalid path');
}
return full;
}
// Usage
const safePath = getSafePath('./uploads', userInput);
const content = fs.readFileSync(safePath);Summary
| Check | Severity | Key Fix | |-------|----------|---------| | fs-sensitive-path | High | Don't read credential files; use env vars | | fs-path-traversal | High | Validate paths are within allowed directories |
Best Practices
1. Use Absolute Path Resolution
Always resolve paths to absolute before comparison:
const resolved = path.resolve(baseDir, userInput);2. Implement Path Allowlists
const allowedDirs = [
path.resolve('./public'),
path.resolve('./uploads'),
];
function isPathAllowed(filePath) {
const resolved = path.resolve(filePath);
return allowedDirs.some(dir =>
resolved.startsWith(dir + path.sep) || resolved === dir
);
}3. Sanitize User Input
// Remove path separators and traversal
const sanitize = (input) => {
return path.basename(input); // Only filename, no directory
};
const safeFile = sanitize(userInput);
const filePath = path.join('./uploads', safeFile);4. Use chroot or Containers
For high-security scenarios:
- Run file operations in a chroot jail
- Use containerization to limit filesystem access
- Mount only necessary directories
Next Steps
- Supply Chain - Dependency security
- MCP TypeScript - MCP-specific checks
- Reviewing Findings - How to fix issues