Discord Bot Security: Preventing Command Injection and API Key Leaks in 2026
A Discord bot security failure has consequences beyond your bot crashing — a compromised token means an attacker can message every user in your bot's servers, ban members, and delete channels. Security is not optional.
The Token is Everything
Your Discord bot token is the single credential that controls your bot completely. Treat it like a root password:
Never commit it to version control:
# .gitignore
.env
config.json # If it contains tokens
secrets.js
Always use environment variables:
// index.js
require('dotenv').config();
const token = process.env.DISCORD_TOKEN;
// Never: const token = 'MTA2NTA...' <- hardcoded, DANGEROUS
Rotate immediately if exposed:
- Go to Discord Developer Portal → Your App → Bot → Reset Token
- Update your VPS environment variable
- PM2 restart your bot
Preventing Command Injection in Bot Logic
If your bot accepts user input and uses it in system calls or database queries:
// VULNERABLE: direct string interpolation
const result = await exec(`grep ${userInput} /var/log/bot.log`);
// SAFE: never pass user input to shell commands
// Use JavaScript file reading APIs instead of shell commands
const fs = require('fs');
const logs = fs.readFileSync('/var/log/bot.log', 'utf8');
const matches = logs.split('
').filter(line => line.includes(sanitizedInput));
For database operations, always use parameterized queries (covered in the database guide).
Permission Validation
Never rely on Discord roles alone for sensitive bot operations — validate server-side:
// Check if the user running the command has the required Discord permission
if (!interaction.member.permissions.has(PermissionFlagsBits.Administrator)) {
return interaction.reply({ content: 'You need Administrator permission.', ephemeral: true });
}
Check specific permissions, not just roles — roles can be misconfigured. Direct permission checks are harder to bypass.
Server Allowlisting for Production Bots
If your bot should only operate in specific servers:
const ALLOWED_GUILDS = new Set(['guild_id_1', 'guild_id_2']);
client.on('guildCreate', async (guild) => {
if (!ALLOWED_GUILDS.has(guild.id)) {
console.log(`Leaving unauthorized guild: ${guild.name}`);
await guild.leave();
}
});
For private bots, this prevents the bot from being added to servers outside your control.