UNPKG

@felixgeelhaar/cclint

Version:

A comprehensive linter for CLAUDE.md files with multi-language code block validation

60 lines 2.59 kB
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