Home  ›  Insights  ›  Engineering
How we build software at Aztia

Shift-Left Security Without Slowing Developers Down: Putting Secret Scanning in CI

← Back to all articles

Credentials don't leak because people are careless. They leak because for about thirty seconds, the short path and the correct path look identical.

The pattern is almost always the same. You're debugging against a real environment. You paste a connection string into a config file to test something quickly. It works, you keep moving, and two hours later you run git add . because the actual change lives in fourteen other files. The credential enters the commit without anyone ever deciding to put it there.

Once it's in history, the cost changes scale. Deleting it in the next commit isn't enough: it's in the repository history, potentially in every teammate's local clone and in any fork. The only serious remedy is rotating the credential, with all the coordination and breakage risk that implies.

So we treat security as part of the pipeline rather than as a review at the end.

Two layers of defense

Layer 1, the local hook. A pre-commit hook scans for credential patterns before the commit exists. This is the friendly layer: it runs on the developer's machine, in seconds, and stops the mistake at the point where fixing it costs five seconds and zero conversations.

Layer 2, an unbypassable CI gate. The same scan runs in continuous integration, server-side, as a required gate before any deploy. Alongside it run the pipeline's other two controls: dependency scanning and static analysis (SAST).

Why both layers exist is the important part of this article, and it deserves its own section.

Why the server-side gate is the one that counts

The local hook is useful, convenient, and not a security control. It lives on a developer's machine, anyone in a hurry can skip it (--no-verify exists and everyone knows it), and it isn't installed by default in the clone of whoever joined on Tuesday.

If your only defense is the local hook, what you have isn't a policy. It's a well-intentioned suggestion.

The CI gate differs along the one dimension that matters: nobody can skip it without leaving a record and stopping the deploy. It doesn't depend on anyone's local setup, on anyone remembering to install it, or on discipline under pressure, which is exactly the thing that fails at the worst moment.

The right way to think about the two layers: the local hook exists to save the developer time, and the CI gate exists to protect the business. Confusing those roles is the classic mistake. Plenty of teams install the hook, announce internally that they now have secret scanning, and still hold no real guarantee at all.

What changes when an agent writes part of the code

We built Hura, our technical assessment platform, with AI agents inside the flow. That moved this gate from good practice to non-negotiable, for three reasons we hadn't anticipated.

Volume changes the arithmetic of the mistake. Credential accidents are low-probability per commit. Multiply the volume of code passing through review and the math moves on its own. A control that caught one case a year starts earning its keep.

Agents are excellent at filling in blanks. Ask an agent for a config example and you get one that's complete, well formed, and carrying a real-looking value in the key field. It's what you asked for. And a value with the right shape is exactly what a scanner has to catch, because a human eye can't tell it apart from the real thing. That's why our policy also bans realistically formatted example secrets, whoever wrote them: they train the team, and the tooling, to coexist with credentials in plain text.

The repo is the context. An agent reads your documentation and your code in order to work. A secret left written in a doc stops being a forgotten file and becomes material that propagates into whatever the agent writes and suggests next. That's the practical reason behind our "by reference, never by value" rule: secrets live in a secret manager, and documents say which credential is needed and where to get it, never what it is.

There's a fourth boundary that matters as much as credentials in our case. Hura processes candidate data, so the policy extends to what goes into a prompt and what gets written to a log. Personal data doesn't travel to a model or into a debug trace because it was convenient during testing. That rule is worth writing before you need it, not after.

How we did it without slowing work down

Three decisions, and one of them is the one we argue about most.

Scan early and cheap. Secret scanning is fast. Putting it early in the pipeline, rather than at the end next to the heavy test stages, means a failure lands in seconds instead of after a full build.

A failure has to explain what to do. A gate that says "possible secret detected" and nothing else produces two things: frustration, and pressure to turn it off. The message has to name the file, the line, and the correct path forward, which is to move the value into the secret manager and leave the reference behind. The quality of the error message determines whether a security control survives its first quarter.

False positives get managed, not ignored. Here's the uncomfortable debate. Every secret scanner generates noise, and noise is the mechanism by which these controls die: people learn to route around them out of habit. The only sustainable answer is to treat each false positive as a pipeline bug, tuning the rule and documenting the exception with its reason, and never as grounds for relaxing the gate. That's ongoing work, and it's the real price of this practice. It isn't zero.

Takeaway

Run two layers and be clear on what each is for: the local hook saves developer time, and the CI gate, unbypassable and ahead of any deploy, is what protects the business. If you have agents writing code, that gate stops being optional: volume goes up, they generate realistically formatted examples, and they read your repo as context. Pair it with a "by reference, never by value" policy covering examples, prompts, and logs. If you can only do one thing this week, move your scanning off the laptop and onto the server.

About Aztia. We're a software development firm. We build Hura, our technical assessment platform (huraapp.com), holding ourselves to the same process we describe in this series. More at aztia.co.

Want a team that works like this?

Thirty minutes, no pitch. Tell us what you're building.

Talk to us →