security: gate /help, signature modal submit, and cancel_delete_tag on staff role
Closes the remaining non-broccolini interaction paths after the prior TICKET_BUTTON_HANDLERS gate. After this commit, every bot interaction is staff-only except the panel buttons (open_ticket / open_ticket_thread / open_ticket_channel) and their ticket-creation modal submit — those have to stay public because they're how members and customers open tickets. Specific changes: - handlers/commands/index.js: handleCommand no longer has the `!== 'help'` carve-out. /help now goes through requireStaffRole like every other slash command. Non-staff get the same ephemeral "only available to the support team" reply. - broccolini-discord.js: the signature_modal_* modal-submit handler now calls requireStaffRole before writing to StaffSignature. /signature already gates the modal display via the slash-command staff check; this is defense in depth against directly crafted submissions. - handlers/buttons.js: cancel_delete_tag moved out of FREE_BUTTON_HANDLERS and gated alongside confirm_delete_tag::*. The dialog is only shown ephemerally to the staff who triggered /response delete, so non-staff can't reach it in normal flow; gating keeps the button surface consistent. Kept public (by design — these are the customer entry points): open_ticket / open_ticket_thread / open_ticket_channel buttons ticket_modal / ticket_modal_thread / ticket_modal_channel submits
This commit is contained in:
@@ -11,6 +11,7 @@ const { mongoose } = require('./db-connection');
|
||||
// Handlers
|
||||
const { handleButton, handleTicketModal } = require('./handlers/buttons');
|
||||
const { handleCommand, handleContextMenu, handleAutocomplete } = require('./handlers/commands');
|
||||
const { requireStaffRole } = require('./handlers/commands/helpers');
|
||||
const { handleDiscordReply } = require('./handlers/messages');
|
||||
|
||||
// Services & jobs
|
||||
@@ -110,6 +111,9 @@ client.on('interactionCreate', async interaction => {
|
||||
}
|
||||
|
||||
if (interaction.isModalSubmit() && interaction.customId.startsWith('signature_modal_')) {
|
||||
// Staff-only: /signature shows this modal, which is gated; double-gate the
|
||||
// submit path in case an attacker crafts the submission directly.
|
||||
if (await requireStaffRole(interaction)) return;
|
||||
// Handle signature modal submit
|
||||
try {
|
||||
const valediction = interaction.fields.getTextInputValue('valediction');
|
||||
|
||||
Reference in New Issue
Block a user