---
title: "The Scanner Was Gone and the Bill Wasn't"
canonical: https://dxdev.com/blog/2026-08-20_security-billing-outlived-the-tool/
datePublished: 2026-08-20
---
The invoice line item for GitHub Advanced Security did not match what the tool had done. The scan history for that repo said the last run was May 22. A surprise charge showed up, I noticed the amount looked wrong, and pulled the thread.

Here's the mechanism, because it's the kind of thing that will bite anyone running CodeQL or Semgrep through GitHub Actions.

## Two separate switches, one workflow

In May, during a CI hardening pass on our main repo, we turned on GitHub Advanced Security to unblock SARIF uploads from CodeQL and Semgrep. Three days later, a follow-up ticket ripped the CodeQL workflow back out for unrelated reasons, and it was gone from the YAML.

What nobody clocked: Advanced Security isn't a workflow. It's a repository-level license toggle, separate from whatever GitHub Actions steps happen to call into it. Delete the workflow and you've deleted the thing that *used* the feature. The feature itself, and its billing, stays exactly where you left it. GitHub doesn't unbill you for having an unused capability turned on; it bills per active committer on any repo where the setting is enabled, whether or not a single scan runs.

Five committers were billed against that repo, every month, for a tool that scanned nothing and produced zero alerts from May 22 onward. Three months of that added up to real money spent on a setting nobody remembered existed.

## Finding it

The diagnostic path here wasn't clever, it was just someone finally reading a receipt instead of routing it past themselves. Once the amount looked off, the check was: pull the repo's security tab, confirm last scan date, cross-reference against the billing API's committer count for that repo. Last scan May 22, five billable committers, feature still flagged on. That was the whole investigation.

The fix took longer to verify than to apply. Disabling Code Security on the one repo is a single settings toggle. Confirming it was *only* that repo meant walking all 13 repos in the org and checking each one's Advanced Security status against the billing API's per-repo committer counts, because the org's other two active repos still run real scans (25 open alerts, 65 fixed, a real history) and turning those off by mistake would have been a worse problem than the one being fixed. Before touching anything, I pulled a full alert snapshot on those two repos as a rollback record, in case the toggle had any side effect on existing findings. It didn't, but you check before you flip the switch, not after.

Result: billable committers on the dead repo went from 5 to 1 (GitHub still counts something even fully disabled, apparently), so the monthly cost fell to about a fifth of what it had been, and I filed a support ticket asking for a credit on the June-through-August charges. I asked for most of it back; GitHub's own docs say they don't refund the current month's consumed licenses, so the realistic number is smaller than what I asked for. Ticket's open.

## What I didn't do, and why

The tempting fix is "audit the billing dashboard monthly." I'm not doing that, because it's the same failure mode with a calendar reminder bolted on, it depends on a human remembering to look at a page that doesn't demand attention. It already ran three months before anyone noticed once; adding a manual checkpoint just gives it another place to quietly stop happening.

The actual structural gap is more interesting: this org already has hard spend caps set to zero on `actions`, `packages`, `codespaces`, `git_lfs`, and `ai_credits`. Those categories cannot silently accrue cost past zero without an explicit budget raise. Advanced Security has no such cap available, at least not as a first-class budget category in GitHub's billing settings the way those others are. That's not a process failure, it's a product gap, and it's the actual reason a real monthly charge ran for three months with nobody noticing: every other spend lane in that org has a tripwire, and this was the one lane that didn't.

I haven't built the workaround yet. It'd be a small scheduled check, walk the org's repos, cross-reference Advanced Security status against committer counts and last-scan timestamps, flag anything billing on a feature with no recent activity. That's a script, not a GitHub setting, because GitHub doesn't give you the setting. Worth noting for anyone with the same five hard caps configured and a sixth line item they've never thought to look at: the caps you set are exactly the caps you're protected on, and nothing else.
