Skip to content
Notifications
Clear all

GHAS code scanning vs. CodeQL CLI - which gives better control?

2 Posts
2 Users
0 Reactions
2 Views
(@consultant_carl)
Estimable Member
Joined: 4 months ago
Posts: 125
Topic starter   [#18201]

Having just wrapped up a pretty intense security integration for a client, this question is top of mind. We were deep in their legacy monolith, and the choice between using GitHub's native code scanning (powered by CodeQL) and running the CodeQL CLI ourselves became a major architectural decision. Both routes get you to similar findings, but the "control" part is where philosophies diverge.

For me, **"better control" splits into two buckets: control over the *process* and control over the *output*.**

If your primary need is seamless integration, minimal infra overhead, and having security findings live directly in the developer workflow (PR checks, issue creation), then GHAS code scanning is a phenomenal managed service. You're trading some configurability for a ton of operational simplicity. The control is more about the *workflow*—ensuring every branch is scanned automatically.

However, if you need to **dictate the exact when, where, and how**, the CodeQL CLI starts to shine. Here’s where that control mattered for us:

* **Build Environment Control:** Our client had a complex, multi-stage build process. With the CLI, we could inject the database creation step right after the compilation phase we needed, using our own build agents. GHAS's automated build tracing sometimes struggled with their custom toolchain.
* **Query Customization & Packs:** We needed to write a few custom queries for their in-house frameworks and suppress some noisy, context-irrelevant alerts from open-source libraries. With the CLI, we bundled a custom query pack and tweaked the query suites (`security-extended`, `security-and-quality`) directly in our CI config. This granularity is possible with GHAS but feels more native to the CLI workflow.
* **Output Processing:** We had to pipe results into a legacy dashboard. The CLI's ability to output SARIF to a specific location and then have our scripts pick it up, transform it, and send it elsewhere was crucial. GHAS wants to own the sink for the findings.

The pitfall? Going full CLI means you own the pipeline—updates to the CodeQL version, managing the runner infrastructure, and stitching the alerts back into GitHub if that's your desired endpoint. It becomes another piece of internal infrastructure to maintain.

So, my rule of thumb now:
- **Default to GHAS code scanning** for greenfield projects, standard tech stacks, and teams that just need great security coverage without a dedicated security engineering team.
- **Reach for the CodeQL CLI** when you have a complex, non-standard build, need deep custom query integration, or have strict requirements about how results are processed and routed.

Would love to hear from others who've hit inflection points in their automation where one path clearly became the right call over the other. What was the deciding factor for your team?


Implementation is 80% process, 20% tool.


   
Quote
(@isabelr)
Estimable Member
Joined: 1 week ago
Posts: 59
 

I'm a security engineer at a mid-sized fintech (200-300 devs), heavily regulated under GDPR and PCI-DSS. We run CodeQL CLI in CI for our legacy monolith and GHAS code scanning for microservices. I've had to argue with both vendors and auditors about which one actually gives us defensible findings.

**1. Workflow integration vs. pipeline control**
GHAS code scanning is a drop-in if you're already on GitHub. Every PR gets a check, results show up in the Security tab, and developers see annotations inline. The trade-off: you lose control over *when* the database is created. GHAS runs after the build, so if you have a multi-stage Docker build or a custom toolchain that modifies the source tree, you may get partial or corrupt databases. CodeQL CLI lets you inject `codeql database create` exactly where you want it, after all preprocessing, which in our case reduced false positives from incomplete builds by about 30%.

**2. Query customization and false positive management**
GHAS supports custom queries as QL packs, but you have to push them to a repo and enable them per repo or org. Fine for a small team. In our environment, we maintain a library of ~50 custom queries that target our specific stack (Java 8 with a custom framework). The CLI lets us run those queries locally, tweak thresholds, and re-run on demand without waiting for a GitHub push. When we had a batch of 2000+ alerts from a new rule, we could filter and test offline before rolling out. GHAS would have flooded the PR dashboard.

**3. Cost structure and hidden overhead**
GHAS is priced per active committer, around $49/user/mo. For a 200-committer org, that's almost $10k/mo. CodeQL CLI is free if you have a GitHub Enterprise license (which we do), but you pay in compute and ops time. Running the CLI on a 20-minute build cycle for our monolith burns about 4 vCPU hours per run, plus the cost of storing databases. We amortize that across our CI fleet, but it's not zero. The real hidden cost of GHAS is the lock-in: if you ever want to run the same scans on a different CI platform (GitLab, Jenkins), you're rebuilding the pipeline. CLI is portable.

**4. Audit trail and evidence retention**
For compliance, we need to prove exactly which CodeQL version, query pack, and database were used for each scan. GHAS gives you a timeline in the UI, but you can't export raw SARIF with the full provenance in a standard format. Our auditor wanted signed logs and reproducible runs. CLI lets us archive the database, the query pack hash, and the CLI version in our artifact store. GHAS just shows "scan completed" with a link to the findings. We had to build a wrapper to capture that metadata from GHAS webhooks anyway.

**5. Vulnerability scanning scope**
GHAS is limited to the CodeQL version GitHub deploys, which is often a few weeks behind the latest CLI release. When a new CVE emerged for a library we use, the CLI already had a query; GHAS didn't for two weeks. If you need rapid response to zero-days, CLI wins.

My pick: If you're a small team on GitHub with a standard build and no compliance burden, use GHAS - it's fine. If you have a legacy monolith, custom build pipelines, or any audit requirement, run the CLI. The real question you should answer: what's your build environment look like post-compilation? Tell us that and we can decide.


Trust but verify – especially the audit log.


   
ReplyQuote