audit
This commit is contained in:
@@ -10,7 +10,7 @@ const { getBot } = require('../api/bosscordClient');
|
||||
const { getGmailClient, sendGmailReply } = require('../services/gmail');
|
||||
const { updateTicketActivity } = require('../services/tickets');
|
||||
const { enqueueSend } = require('../services/channelQueue');
|
||||
const { extractRawEmail } = require('../utils');
|
||||
const { extractRawEmail, safeEqual } = require('../utils');
|
||||
const { CONFIG } = require('../config');
|
||||
|
||||
const router = express.Router();
|
||||
@@ -43,8 +43,9 @@ function authMiddleware(req, res, next) {
|
||||
}
|
||||
const auth = req.headers.authorization;
|
||||
const token = auth && auth.startsWith('Bearer ') ? auth.slice(7) : null;
|
||||
if (token !== key) {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
// Identical response body for missing vs invalid token — don't tell a probe which state it's in.
|
||||
if (!safeEqual(token, key)) {
|
||||
return res.status(401).json({ error: 'unauthorized' });
|
||||
}
|
||||
next();
|
||||
}
|
||||
@@ -189,7 +190,9 @@ router.post('/tickets/:id/messages', express.json(), async (req, res) => {
|
||||
return res.status(404).json({ error: 'Discord channel not found' });
|
||||
}
|
||||
const discordUser = req.body.displayName || 'bOSScord';
|
||||
await enqueueSend(channel, content);
|
||||
// Content originates from the bOSScord web UI (staff-gated) but still crosses an HTTP boundary —
|
||||
// allow explicit user/role mentions a staff member typed, block @everyone/@here.
|
||||
await enqueueSend(channel, { content, allowedMentions: { parse: ['users', 'roles'] } });
|
||||
|
||||
if (!ticket.gmailThreadId.startsWith('discord-')) {
|
||||
try {
|
||||
|
||||
@@ -2,6 +2,7 @@ const express = require('express');
|
||||
const rateLimit = require('express-rate-limit');
|
||||
const { ChannelType } = require('discord.js');
|
||||
const { CONFIG } = require('../config');
|
||||
const { safeEqual } = require('../utils');
|
||||
const { applyConfigUpdates, readAllConfig } = require('../services/configPersistence');
|
||||
const { logSystem } = require('../services/debugLog');
|
||||
const { REGISTRY: NOTIFICATION_REGISTRY } = require('../services/notificationRegistry');
|
||||
@@ -15,6 +16,7 @@ const {
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// Intentionally no trust-proxy: loopback-only; global rate-limit bucket.
|
||||
const internalLimiter = rateLimit({
|
||||
windowMs: 60 * 1000,
|
||||
max: 10,
|
||||
@@ -28,7 +30,7 @@ router.use(internalLimiter);
|
||||
// Middleware: verify internal secret
|
||||
router.use((req, res, next) => {
|
||||
const secret = req.headers['x-internal-secret'];
|
||||
if (!CONFIG.INTERNAL_API_SECRET || secret !== CONFIG.INTERNAL_API_SECRET) {
|
||||
if (!CONFIG.INTERNAL_API_SECRET || !safeEqual(secret, CONFIG.INTERNAL_API_SECRET)) {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
next();
|
||||
@@ -136,10 +138,13 @@ router.post('/restart', express.json(), (req, res) => {
|
||||
const delay = new Date(scheduledFor).getTime() - Date.now();
|
||||
if (delay <= 0) return res.status(400).json({ error: 'Scheduled time is in the past' });
|
||||
if (scheduledRestart) clearTimeout(scheduledRestart);
|
||||
scheduledRestart = setTimeout(() => {
|
||||
// Lazy require: broccolini-discord.js requires this file at module scope before its exports are populated.
|
||||
const { trackTimeout } = require('../broccolini-discord');
|
||||
scheduledRestart = trackTimeout(setTimeout(() => {
|
||||
console.log('[restart] Scheduled restart firing...');
|
||||
process.exit(0);
|
||||
}, delay);
|
||||
}, delay));
|
||||
if (scheduledRestart && typeof scheduledRestart.unref === 'function') scheduledRestart.unref();
|
||||
res.json({ ok: true, mode, scheduledFor, delayMs: delay });
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user