mirror of
https://github.com/aaronsb/obsidian-mcp-plugin.git
synced 2026-07-22 06:45:14 +00:00
- Add CONTRIBUTING.md with development guidelines
- Add SECURITY.md with vulnerability reporting policy
- Create GitHub issue templates for bugs and features
- Add PR template with checklist
- Set up GitHub Actions for testing and security scanning
- Document all security findings from code audit
- Create detailed GitHub issues for all vulnerabilities
- Update CHANGELOG with security audit results
- Add project structure documentation
This establishes proper open-source project structure and documents
all critical security issues that need to be addressed.
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
5.4 KiB
5.4 KiB
🟠 HIGH: Missing Input Validation Across All Operations
Summary
The plugin lacks comprehensive input validation for file content, search queries, and operation parameters, leading to potential crashes, DoS attacks, and unexpected behavior.
Current Behavior
- No validation of file content size or format
- Search queries accept regex without sanitization
- No limits on batch operations
- Missing validation for special characters in filenames
- No protection against malformed JSON/YAML in frontmatter
Security Impact
- Severity: HIGH
- Attack Vector: Malicious input via MCP protocol
- Impact: DoS, memory exhaustion, application crashes, data corruption
Vulnerable Areas
1. File Content Operations
// No size limits!
async createFile(path: string, content: string): Promise<any> {
await this.ensureDirectoryExists(path);
const file = await this.app.vault.create(path, content);
return { path: file.path };
}
2. Search Operations
// Unvalidated regex can cause ReDoS
async searchSimple(query: string): Promise<any[]> {
const results = await this.search(query); // No regex validation
return results;
}
3. Batch Operations
// No limits on array size
case 'combine': {
const { paths, destination } = params; // paths could be 10,000 items!
// ... processing without limits
}
Attack Scenarios
- Memory Exhaustion: Create file with 1GB of content
- ReDoS Attack: Search with
(a+)+bpattern - CPU DoS: Combine 10,000 files in one operation
- Path Injection: Filename with
../../embedded - Data Corruption: Invalid UTF-8 sequences in content
Proposed Solution
Input Validator Framework
interface ValidationRule {
field: string;
validators: Validator[];
}
class InputValidator {
private rules: Map<string, ValidationRule[]> = new Map();
constructor() {
// Define validation rules
this.rules.set('vault.create', [
{
field: 'path',
validators: [
new LengthValidator(1, 255),
new PatternValidator(/^[^<>:"|?*]+$/),
new PathSafetyValidator()
]
},
{
field: 'content',
validators: [
new SizeValidator(0, 10 * 1024 * 1024), // 10MB max
new UTF8Validator(),
new ContentTypeValidator()
]
}
]);
}
validate(operation: string, params: any): ValidationResult {
const rules = this.rules.get(operation);
if (!rules) return { valid: true };
const errors: ValidationError[] = [];
for (const rule of rules) {
const value = params[rule.field];
for (const validator of rule.validators) {
const result = validator.validate(value);
if (!result.valid) {
errors.push({
field: rule.field,
message: result.message,
code: result.code
});
}
}
}
return {
valid: errors.length === 0,
errors
};
}
}
Specific Validators Needed
-
File Size Limits
class FileSizeValidator { validate(content: string): ValidationResult { const sizeInBytes = Buffer.byteLength(content, 'utf8'); if (sizeInBytes > this.maxSize) { return { valid: false, message: `File size ${sizeInBytes} exceeds limit ${this.maxSize}` }; } return { valid: true }; } } -
Safe Regex Validator
class SafeRegexValidator { validate(pattern: string): ValidationResult { try { // Check for dangerous patterns if (this.hasExponentialComplexity(pattern)) { return { valid: false, message: 'Regex pattern has exponential complexity' }; } new RegExp(pattern); return { valid: true }; } catch (e) { return { valid: false, message: 'Invalid regex pattern' }; } } } -
Batch Operation Limits
class BatchLimitValidator { validate(items: any[]): ValidationResult { if (items.length > this.maxBatchSize) { return { valid: false, message: `Batch size ${items.length} exceeds limit ${this.maxBatchSize}` }; } return { valid: true }; } }
Implementation Plan
Phase 1: Critical Validators
- Path safety (prevent injection)
- File size limits
- Basic content validation
Phase 2: Operation Validators
- Search query safety
- Batch operation limits
- Parameter type checking
Phase 3: Advanced Validation
- Content type detection
- Encoding validation
- Rate limiting
Configuration
{
"validation": {
"maxFileSize": 10485760,
"maxBatchSize": 100,
"maxPathLength": 255,
"allowedFileTypes": [".md", ".txt", ".pdf"],
"regexTimeout": 1000,
"strictMode": true
}
}
Testing Requirements
- Unit tests for each validator
- Fuzzing tests with malformed input
- Performance tests with large inputs
- Integration tests for all operations
Acceptance Criteria
- Input validation framework implemented
- All operations validate input
- Clear error messages for validation failures
- Configurable validation rules
- Performance impact < 5ms per operation
- Documentation for validation rules
Labels
security high-priority input-validation dos-prevention