-
Notifications
You must be signed in to change notification settings - Fork 282
Open
Description
🔒 Security: Unsafe JSON Parsing in fs.ts
Summary
The readJson function in src/core/fs.ts performs JSON parsing without validation against prototype pollution attacks. While this requires user action to exploit (installing malicious config), it should be fixed for defense in depth.
Risk Assessment: LOW-MEDIUM - Requires user to install malicious configuration, but follows security best practices.
🐛 Vulnerability
File: src/core/fs.ts:13
export const readJson = <T>(filePath: string): T | null => {
try {
return JSON.parse(fs.readFileSync(filePath, 'utf8')) as T; // ← VULNERABLE
} catch {
return null;
}
};Problem
- No validation against
__proto__,constructor, orprototypepollution - No size limits (DoS via massive JSON)
- No schema validation
Attack Vector
A malicious .claude.json or settings.json with prototype pollution:
{
"__proto__": {
"env": {
"ANTHROPIC_API_KEY": "attacker-controlled-key"
}
}
}Impact
- ✅ Could inject malicious object properties
- ✅ Could alter application behavior
- ✅ Could override environment variables
- ❌ Not remotely exploitable (requires local malicious config)
⚠️ Requires user to install/configure untrusted variant
✅ Recommended Fix
Option 1: Use secure-json-parse (RECOMMENDED)
import { parse } from 'secure-json-parse';
export const readJson = <T>(filePath: string): T | null => {
try {
const content = fs.readFileSync(filePath, 'utf8');
return parse(content, { protoAction: 'remove' }) as T;
} catch {
return null;
}
};Option 2: Manual sanitization
export const readJson = <T>(filePath: string): T | null => {
try {
const raw = fs.readFileSync(filePath, 'utf8');
const parsed = JSON.parse(raw);
// Sanitize by removing prototype chain
return JSON.parse(JSON.stringify(parsed)) as T;
} catch {
return null;
}
};Option 3: Add size limit + schema validation
import { z } from 'zod';
const MAX_JSON_SIZE = 1024 * 1024; // 1MB
export const readJson = <T>(filePath: string): T | null => {
try {
const stats = fs.statSync(filePath);
if (stats.size > MAX_JSON_SIZE) {
throw new Error('JSON file too large');
}
const content = fs.readFileSync(filePath, 'utf8');
return JSON.parse(content) as T;
} catch {
return null;
}
};📊 Additional Considerations
Dependency Installation
npm install secure-json-parseAlternative: Zero-dependency approach
If you prefer not to add a dependency, Option 2 provides basic protection without external packages.
🔍 Verification
After fix:
# Test that normal JSON still works
npm test
# Manual verification
node -e "const fs = require('fs'); console.log(JSON.parse(fs.readFileSync('package.json', 'utf8')));"📚 References
🎯 Context
Why this matters for cc-mirror:
- This tool creates isolated variants with custom configurations
- Users may download/share variant configurations from untrusted sources
- Defense in depth prevents accidental compromise
- Zero performance impact (fix is simple and safe)
Why NOT critical:
- No remote attack surface (CLI tool, not a network service)
- Requires user action to exploit (installing malicious configs)
- Development-focused tool (not exposed to untrusted input)
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels