fix: Implement CSRF protection for Trinity Console
CRITICAL SECURITY FIX - Prevents Cross-Site Request Forgery attacks Changes: - Installed csurf middleware (session-based tokens) - Added CSRF middleware to all /admin routes in src/index.js - Configured admin router to pass csrfToken to all views - Updated layout.ejs to send CSRF token with htmx requests - Added EJS view engine configuration - Added body parsing middleware (json + urlencoded) Security Impact: - Prevents malicious sites from executing admin actions using cookies - All POST requests now require valid CSRF token - Invalid tokens return 403 Forbidden - Session-based tokens (no cookies needed) Protected Routes: - /admin/servers/:id/sync (force whitelist sync) - /admin/servers/:id/toggle-whitelist (whitelist toggle) - /admin/grace/:id/extend (grace period extension) - /admin/grace/:id/manual (manual payment override) - /admin/roles/resync/:id (role assignment) Attack Scenario Prevented: User visits malicious site while logged into Trinity Console → Site tries to submit form to admin endpoint → Request includes session cookie but NO CSRF token → Server rejects with 403 Forbidden → Attack failed! Note: csurf is deprecated but still functional. For future refactor, consider csrf-csrf or Express 5 built-in protection. Refs: TRINITY-CONSOLE-PRE-LAUNCH-CHECKLIST.md - Fix #1 Chronicler: #51 Signed-off-by: Claude (Chronicler #51) <claude@firefrostgaming.com>
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
"dependencies": {
|
||||
"body-parser": "^1.20.2",
|
||||
"cookie-parser": "^1.4.7",
|
||||
"csurf": "^1.11.0",
|
||||
"discord.js": "^14.14.1",
|
||||
"dotenv": "^16.4.5",
|
||||
"ejs": "^3.1.9",
|
||||
|
||||
@@ -4,6 +4,7 @@ const session = require('express-session');
|
||||
const passport = require('passport');
|
||||
const DiscordStrategy = require('passport-discord').Strategy;
|
||||
const { Client, GatewayIntentBits, REST, Routes } = require('discord.js');
|
||||
const csrf = require('csurf');
|
||||
|
||||
const authRoutes = require('./routes/auth');
|
||||
const adminRoutes = require('./routes/admin');
|
||||
@@ -32,6 +33,12 @@ passport.use(new DiscordStrategy({
|
||||
// Initialize Express App
|
||||
const app = express();
|
||||
app.set('trust proxy', 1);
|
||||
app.set('view engine', 'ejs');
|
||||
app.set('views', __dirname + '/views');
|
||||
|
||||
// Body parsing middleware
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
|
||||
// Make Discord client accessible to routes
|
||||
app.locals.client = client;
|
||||
@@ -57,9 +64,12 @@ app.get('/health', (req, res) => {
|
||||
});
|
||||
});
|
||||
|
||||
// CSRF Protection (session-based)
|
||||
const csrfProtection = csrf({ cookie: false });
|
||||
|
||||
// Register Routes
|
||||
app.use('/auth', authRoutes);
|
||||
app.use('/admin', adminRoutes);
|
||||
app.use('/admin', csrfProtection, adminRoutes);
|
||||
app.use('/webhook', webhookRoutes);
|
||||
|
||||
// Start Application
|
||||
|
||||
@@ -12,6 +12,12 @@ const rolesRouter = require('./roles');
|
||||
|
||||
router.use(requireTrinityAccess);
|
||||
|
||||
// Make CSRF token available to all admin views
|
||||
router.use((req, res, next) => {
|
||||
res.locals.csrfToken = req.csrfToken();
|
||||
next();
|
||||
});
|
||||
|
||||
router.get('/', (req, res) => {
|
||||
res.redirect('/admin/dashboard');
|
||||
});
|
||||
|
||||
@@ -6,6 +6,12 @@
|
||||
<title><%= title %> | Trinity Console</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<script src="https://unpkg.com/htmx.org@1.9.11"></script>
|
||||
<script>
|
||||
// Configure htmx to include CSRF token in all requests
|
||||
document.body.addEventListener('htmx:configRequest', function(evt) {
|
||||
evt.detail.headers['CSRF-Token'] = '<%= csrfToken %>';
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
tailwind.config = {
|
||||
darkMode: 'class',
|
||||
|
||||
Reference in New Issue
Block a user