BillTracker/routes/aboutAdmin.js

85 lines
2.7 KiB
JavaScript

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;