const express = require('express'); const fs = require('fs'); const path = require('path'); const { requireAuth, requireAdmin } = require('../middleware/requireAuth'); const router = express.Router(); // Base directory for path validation const BASE_DIR = path.resolve(__dirname, '..'); /** * Sanitize file paths to prevent path traversal attacks * @param {string} filePath - The file path to sanitize * @returns {string|null} - The sanitized absolute path or null if invalid */ function sanitizePath(filePath) { try { // Resolve the absolute path const resolvedPath = path.resolve(BASE_DIR, filePath); // Check if the resolved path is within the project directory if (!resolvedPath.startsWith(BASE_DIR)) { return null; } return resolvedPath; } catch (err) { return null; } } /** * Redact sensitive information from file content * @param {string} content - The content to redact * @returns {string} - The redacted content */ function redactSensitiveContent(content) { if (!content) return content; return content // Redact internal IPs .replace(/\b192\.168\.[0-9]{1,3}\.[0-9]{1,3}\b/g, '[REDACTED]') .replace(/\b10\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\b/g, '[REDACTED]') .replace(/\b172\.(1[6-9]|2[0-9]|3[0-1])\.[0-9]{1,3}\.[0-9]{1,3}\b/g, '[REDACTED]') // Redact passwords, api_keys, secrets .replace(/(password|api_key|secret)\s*=\s*[^\\\s]+/gi, '$1=[REDACTED]'); } // Admin-only endpoint to serve FUTURE.md and DEVELOPMENT_LOG.md content router.get('/', requireAuth, requireAdmin, (req, res) => { try { // Sanitize paths to prevent path traversal const futureMdPath = sanitizePath('FUTURE.md'); const devLogMdPath = sanitizePath('DEVELOPMENT_LOG.md'); // Check if paths are valid if (!futureMdPath || !devLogMdPath) { return res.status(400).json({ error: 'Invalid file path', code: 'INVALID_FILE_PATH' }); } const futureContent = fs.readFileSync(futureMdPath, 'utf-8'); const devLogContent = fs.readFileSync(devLogMdPath, 'utf-8'); // Redact sensitive information const sanitizedFutureContent = redactSensitiveContent(futureContent); const sanitizedDevLogContent = redactSensitiveContent(devLogContent); res.json({ future: sanitizedFutureContent, developmentLog: sanitizedDevLogContent }); } catch (err) { // Sanitize error message to prevent path disclosure console.error('[aboutAdmin] Error reading files:', err.message.replace(BASE_DIR, '[REDACTED]')); res.status(500).json({ error: 'Failed to read project documentation files', code: 'FILE_READ_ERROR' }); } }); module.exports = router;