@felixgeelhaar/cclint
Version:
A comprehensive linter for CLAUDE.md files with multi-language code block validation
60 lines • 2.59 kB
JavaScript
import { readFile } from 'fs/promises';
import { ContextFile } from '../domain/ContextFile.js';
import { PathValidator } from './security/PathValidator.js';
export class FileReader {
pathValidator;
constructor() {
// Initialize with allowed extensions for CLAUDE.md files
this.pathValidator = new PathValidator(['.md', '.MD', '.markdown']);
}
async readContextFile(filePath, basePath) {
try {
// Validate the path for security
const safePath = this.pathValidator.validatePath(filePath, basePath);
// Check if file exists and is actually a file
if (!this.pathValidator.isValidFile(safePath)) {
throw new Error(`Path does not exist or is not a file: ${safePath}`);
}
// Check if file has allowed extension
if (!this.pathValidator.hasAllowedExtension(safePath)) {
throw new Error(`File type not allowed. Only Markdown files (.md, .MD, .markdown) are supported`);
}
// Read the file content
const content = await readFile(safePath, 'utf-8');
// Check for suspicious content patterns
this.validateFileContent(content, safePath);
return new ContextFile(safePath, content);
}
catch (error) {
if (error instanceof Error) {
throw new Error(`Failed to read file ${filePath}: ${error.message}`);
}
throw new Error(`Failed to read file ${filePath}: Unknown error`);
}
}
/**
* Validate file content for potential security issues
* @param content The file content to validate
* @param filePath The file path for error messages
*/
validateFileContent(content, filePath) {
// Check file size (limit to 10MB)
const maxSize = 10 * 1024 * 1024; // 10MB
if (content.length > maxSize) {
throw new Error(`File ${filePath} exceeds maximum size of 10MB`);
}
// Check for null bytes
if (content.includes('\x00')) {
throw new Error(`File ${filePath} contains null bytes`);
}
// Check for excessive line length (potential ReDoS attack)
const lines = content.split('\n');
const maxLineLength = 10000;
for (let i = 0; i < lines.length; i++) {
if (lines[i].length > maxLineLength) {
throw new Error(`File ${filePath} has line ${i + 1} exceeding ${maxLineLength} characters`);
}
}
}
}
//# sourceMappingURL=FileReader.js.map