
GitLab Runner Token Exposed: My Security Blunder
Okay, so picture this: it was late, I'd had one too many cups of kape, and I was determined to get this self-hosted GitLab runner humming. My goal? To finally automate some of my personal projects and...
r5yn1r4143
3w ago
Okay, so picture this: it was late, I'd had one too many cups of kape, and I was determined to get this self-hosted GitLab runner humming. My goal? To finally automate some of my personal projects and save myself the tedious manual deployments. Sounds heroic, right? Well, it turned into a cautionary tale about something as basic as, well, basic security.
TL;DR
I messed up. Big time. When setting up my first self-hosted GitLab runner, I accidentally exposed the runner's authentication token. This is a secret key that lets your runner talk securely to your GitLab instance. If someone else gets it, they can potentially run malicious code on your machine or, worse, use your GitLab infrastructure for their own nefarious purposes. Thankfully, I caught it before anything terrible happened, but it was a stark reminder that even the simplest steps need a security lens.
The Grand Ambition: Self-Hosting My First GitLab Runner
I was inspired. Seeing other developers boast about their custom CI/CD pipelines using self-hosted runners really lit a fire under me. I imagined seamless deployments, automated testing, the whole nine yards. So, I decided to dive in. My setup was pretty standard: a small Linux VM I had lying around, ready to be the workhorse for my code.
The GitLab documentation, bless its heart, is usually pretty good. I followed the steps for installing the GitLab Runner, creating a new runner in my GitLab instance, and then registering it. This is where the core of the operation happens – the registration process. You need to tell your runner how to find your GitLab instance and, crucially, authenticate itself.
This authentication uses a registration token, and more importantly, once registered, the runner uses a runner token (often called an authentication token) to communicate with the GitLab API. This token is stored in the runner's configuration file, usually something like /etc/gitlab-runner/config.toml.
My initial thought process was: "Okay, I need this token to register. Where should I put it?" I was working on a shell script to automate the initial setup and registration. And that's where my brain, fueled by caffeine and overconfidence, went off the rails.
I wanted the script to be self-contained. So, instead of carefully managing the config.toml file and its sensitive contents, I thought it would be "convenient" to have the registration token directly in my setup script.
My naive script looked something like this (and yes, this is where I cringe):
#!/bin/bashTHIS IS THE BAD PART - DON'T DO THIS!
GITLAB_URL="https://your.gitlab.instance.com"
REGISTRATION_TOKEN="THIS_IS_MY_SUPER_SECRET_TOKEN_FROM_GITLAB_UI"
RUNNER_NAME="my-awesome-runner-$(hostname)"
TAG_LIST="docker,linux,ci"echo "Registering GitLab Runner..."
The command to register the runner. The token is passed directly.
gitlab-runner register \
--non-interactive \
--url "$GITLAB_URL" \
--registration-token "$REGISTRATION_TOKEN" \
--executor "docker" \
--docker-image alpine:latest \
--description "$RUNNER_NAME" \
--tag-list "$TAG_LIST"echo "Runner registered!"
See the problem? The REGISTRATION_TOKEN was right there in plain text. My plan was to then copy this script to my VM, run it, and have a registered runner. But in my haste, I thought, "What if I make this script even more automated? What if I put this script somewhere public, or at least accessible, and just curl it onto the server to run?"
And that, my friends, is how I ended up with a script containing a sensitive token, sitting in a GitHub repository that, while not entirely public, was certainly not locked down with the same rigor I'd apply to, say, my personal banking details.
The "Uh Oh" Moment: How I Discovered the Leak
It wasn't a dramatic hack. It was far more mundane, and frankly, embarrassing. I was doing a routine check of my GitLab instance's runner list. I had just registered my new runner, and it was showing up green, ready to go. But then I noticed something odd. There was another runner listed, one I didn't create. It had a generic-sounding name and was trying to connect from an IP address that was definitely not my VM.
My heart sank. I immediately went to my GitHub repository where I had stored that "convenient" setup script. I scrolled down. There it was. The REGISTRATION_TOKEN. Staring back at me, mocking my amateurism.
I checked the logs on my GitLab instance, looking for signs of unauthorized access. Thankfully, the other runner hadn't actually done anything malicious yet. It was likely a bot or an automated scanner that had found the token in my repository. These bots scour public and semi-public code repositories looking for these juicy secrets.
The error message I would have seen if the rogue runner had tried to do something significant might have looked something like this, depending on the action:
ERROR: Job failed: runner_not_registered: runner has not been authenticated
Or, if it tried to claim a job it wasn't supposed to:
ERROR: Registering runner... failed: this runner is not registered
But the real danger was that the token itself proved that my GitLab instance was accessible and that I had a runner registered. If someone had been more sophisticated, they could have used that token to:
The sheer panic was real. I felt like I'd left my front door wide open with a sign saying "Free stuff inside!"
The Fix: Revoking and Re-registering with Security in Mind
The good news? Fixing it was relatively straightforward, though it required a bit of a reset.
Step 1: Revoke the Stolen Token
In my GitLab instance, I navigated to the Admin Area > CI/CD > Runners. I found the compromised runner (which, thankfully, hadn't been fully configured or assigned to any critical jobs) and clicked the button to "untag" and then "delete" it. This effectively invalidated that specific runner's registration.
More importantly, I needed to ensure that the registration token itself was no longer valid. GitLab allows you to reset these. I went to Admin Area > Settings > CI/CD and found the "Runner registration tokens" section. I clicked
Comments
Sign in to join the discussion.