Discord Bots

Keeping Your Discord Bot Token Safe with Environment Variables

How bot tokens leak, what an attacker can do with one, and a practical setup for keeping tokens out of your code, logs and git history.

On this page
  1. What an attacker can do with your token
  2. How tokens actually leak
  3. The fix: environment variables
  4. If a token has already leaked
  5. Reduce the blast radius
  6. Other secrets deserve the same care
  7. A quick checklist
  8. Summary

A Discord bot token is a password that never expires on its own and bypasses two-factor authentication. Anyone who has it can log in as your bot and do everything its permissions allow — in every server it has joined. Protecting it is the single most important security task for a bot developer, and it’s mostly about habits.

What an attacker can do with your token

With a leaked token, someone can:

  • Delete channels, roles and messages in every server your bot can manage.
  • Ban or kick members, or mass-DM them with scam links.
  • Read messages the bot can see, including in private channels it has access to.
  • Get your bot flagged or disabled by Discord for abuse you didn’t commit.

The damage is limited only by the permissions your bot has. That’s the first lesson: a bot invited with Administrator turns a leaked token into a catastrophe.

How tokens actually leak

Almost every leak we see falls into one of these categories:

  1. Committed to a public repository. The token is pasted into config.json or the main file, and the project is pushed to GitHub. Automated scrapers watch public commits and find tokens within minutes.
  2. Left in git history. The token is removed from the code in a later commit — but it’s still in the history, where anyone can find it.
  3. Shared in a screenshot or paste. A helpful stranger asks for your code to debug it, or a screenshot of your editor shows the token.
  4. Printed to logs. Debug code logs the whole config object, and logs end up in a support ticket or a public channel.
  5. An eval command. An owner-only eval command with a weak permission check lets someone run client.token.

Discord participates in GitHub’s secret scanning programme, so a token pushed to a public repository is often detected and reset automatically. That protects your servers — but it also takes your bot offline until you notice, which is another reason to never commit it.

The fix: environment variables

The standard solution is to keep secrets out of code entirely and pass them to the process through environment variables. Your code reads a variable by name; the value lives somewhere else.

In Node.js:

client.login(process.env.DISCORD_TOKEN);

In Python:

import os
bot.run(os.environ["DISCORD_TOKEN"])

Where the value comes from depends on where the bot runs.

Locally: a .env file

For development, keep variables in a .env file and load it with dotenv (Node.js) or python-dotenv (Python):

DISCORD_TOKEN=paste-your-token-here
DATABASE_URL=mysql://user:pass@localhost:3306/bot

Then — before your first commit — add it to .gitignore:

.env

Commit a .env.example with the variable names and empty values, so collaborators know what to set without seeing your secrets. Using .env files in Node.js and Python walks through the setup for both languages.

In production: the host’s environment

On the server, you don’t upload the .env file at all. Instead, set variables in your host’s panel. On Kerit Cloud, environment variables are stored encrypted, injected into your bot’s container at start, and never printed in logs. Each bot runs in its own isolated container, so other customers can’t read your environment or files.

The same code works in both places: locally the value comes from .env, in production from the panel.

If a token has already leaked

Act immediately, in this order:

  1. Reset the token in the Discord Developer Portal under Bot → Reset Token. The old token stops working instantly.
  2. Update the environment variable on your host with the new token and restart the bot.
  3. Audit your servers. Check the audit log of servers your bot is in for actions you didn’t take.
  4. Clean the repository. Removing the token in a new commit is not enough. Either rewrite history with a tool like git filter-repo, or — simpler — treat the old token as permanently public and rely on the reset. Never reuse it.

Resetting is the only step that actually protects you. Everything else is cleanup.

Reduce the blast radius

Even with good habits, assume a leak could happen and limit what it would cost.

Use least-privilege permissions. Invite the bot with only the permissions it needs. A music bot doesn’t need Manage Roles; a moderation bot doesn’t need Administrator. Server admins also appreciate bots that don’t ask for everything.

Lock down owner commands. If you have an eval or shell command, restrict it to your user ID — checked in code, not by role name — or remove it from production builds entirely.

const OWNER_ID = process.env.OWNER_ID;
if (interaction.user.id !== OWNER_ID) {
  return interaction.reply({ content: 'Not allowed.', ephemeral: true });
}

Don’t log configuration objects. Log the fact that config loaded, not its contents. If you must debug, print variable names and whether they’re set.

Protect your Discord account. Enable two-factor authentication on the account that owns the application. For bots with several maintainers, create a Developer Portal team so ownership doesn’t hinge on one person’s account.

Rotate after staff changes. If someone with access to the token leaves the project, reset it.

Other secrets deserve the same care

Everything in this article applies to database passwords, API keys for AI services, payment provider keys and webhook URLs. Discord webhook URLs in particular are often overlooked — anyone with one can post to that channel. Treat every credential as an environment variable, and see keeping database credentials secure for database-specific advice.

A quick checklist

  • [ ] Token read from process.env / os.environ, never hard-coded
  • [ ] .env in .gitignore before the first commit
  • [ ] .env.example committed with blank values
  • [ ] Production variables set in the host panel, not uploaded as a file
  • [ ] Bot invited with minimum permissions
  • [ ] Owner commands checked by user ID
  • [ ] 2FA on the owning Discord account
  • [ ] Token reset immediately after any suspected leak

Summary

Treat your bot token like a password with no expiry and no 2FA. Keep it in environment variables — a git-ignored .env file locally and encrypted panel variables in production — never in code, logs or screenshots. If it leaks, reset it first and clean up second, and limit the damage in advance with least-privilege permissions and locked-down owner commands.