All posts

April 3, 2026 · 4 min read

The Bot Token I Committed 'Just to Test It Quickly' Could Read Every Channel in the Workspace

I built a small internal bot last year to post automated updates into a team's chat workspace whenever a deploy went out. Setting it up meant generating a bot token from the workspace's developer settings, and to get it working fast, I pasted that token directly into a script and pushed it to a repo, telling myself I'd move it to a proper environment variable once the basic thing worked.

The 'just to test it quickly' part that didn't stay quick

The bot worked on the first try, which is usually the moment a temporary shortcut gets forgotten rather than fixed, because there's no visible reason to go back and clean it up. The repo it lived in was private at the time, which felt like enough of a safety net to not think about it further. Months later, for an unrelated reason, that repo got made public temporarily during a reorganization, and the token sat there, in plain text, in the commit history, for about two days before anyone noticed and locked it back down.

What I hadn't actually checked about that token

I'd generated the token to post messages, and I'd assumed, without checking, that it could only post messages. When I finally looked at what permissions had actually been granted during setup, the token could also read the full message history of every channel it had been added to, including ones well beyond the one it was meant to post updates into, because the setup flow had defaulted to a broader permission scope than the one narrow thing I actually needed.

Why this combination is worse than either mistake alone

A leaked token that can only do the one narrow thing it was meant for is a much smaller problem than a leaked token that can also read everything else, simply because nobody checked what permissions were actually being requested at setup time. The two mistakes compounded each other: a credential handling shortcut, plus a permissions scope nobody had actually verified, met at the worst possible moment when the repo briefly went public.

What actually changed afterward

  • The token got rotated immediately, and the new one was scoped down to the single permission the bot actually needed, not the broader default the setup flow offered.
  • It moved to a proper environment variable, checked in a way that made it impossible to accidentally commit again.
  • I now actually read the permissions screen on any bot or integration token before generating it, rather than accepting whatever the platform defaults to.
  • Any repo that ever briefly goes public, even by accident, now gets a full secrets scan before anyone assumes it's fine because it's private again.

Nothing came of this one, as far as anyone could tell, likely because two days is a short window and nobody happened to be scanning for it in that exact time. What stuck with me is how much of the actual risk was sitting quietly in a permission I'd never checked, granted the moment I generated a token I assumed was more limited than it actually was.

Related reading

Harbova is a security service for apps built with AI tools. Start with a free scan, and if it finds something serious, we can fix it and prove it is closed.