From DevOps to DevSecOps: How I Became Clearview's In-House Pen-Tester

It took me a decade of shipping things reliably before I started spending my nights trying to break them.

For a long time I was the person who shipped it. CI/CD pipelines, Terraform modules, the monitoring stack, the "why is staging down?" Slack messages at midnight. I have been doing that work for nearly two decades, even before it was called DevOps.

Earlier this year I took on a different job inside Clearview Team. Now, before any new feature ships, somebody spends a day trying to break it. Often, that somebody is me.

The Night the Job Description Changed

It was March 2026. I could not sleep. Too much coffee, too many open browser tabs, and a Hacker News thread I could not stop reading about a breach that turned out to be a misconfiguration — a public-read S3 bucket exposing millions of records.

"That could never happen to us," I thought. "We have policies. We check these things." Then I got up, opened my laptop, and started checking anyway.

Four hours later I had found three public S3 buckets in our own infrastructure. None of them held customer data — they held logs and config files, enough information for an attacker to draw a map of the system.

The Terraform that created those buckets had been written in the early days, before we had standards, before we had a review process, before a single checkov rule ran in the pipeline. Nobody had ever gone back. They had terraform apply-ed once and moved on.

Those buckets were not somebody else's mistake. They were my Terraform, my missing review process. Finding them was less a security win than a critique of how I had been working for years.

I fixed them that morning, wrote up the incident, told the team. And then I could not stop.

What an Engineer Reads at Night When They Cannot Sleep

I started spending evenings on a different reading list:

  • JWT vulnerabilities — specifically how stateless tokens make revocation almost impossible
  • SQL injection patterns that still work in 2026 — parameterised queries handle the textbook case, but ORMs like TypeORM ship their own foot-guns (raw queries, addSelect on relations, QueryBuilder with string interpolation)
  • CORS bypasses — wildcard subdomain matching, reflected origins, preflight caching abuse
  • What trust proxy actually does in Express — and why getting the hop count wrong means your rate limiter trusts attacker-supplied IPs, which matters a great deal if you are sitting behind CloudFront and an ALB

I am not claiming to be a research-level expert in any of these. I am claiming curiosity. I went deep enough on each to spot the same patterns in our own codebases and to ask sharper questions during reviews. That is different from being a full pen tester, and I try not to confuse the two.

Slowly, I started looking at our code differently. Every endpoint became a question about what happens when somebody sends weird input; every configuration became a suspicion about whether it was actually secure or only looked secure.

I was running curl against staging at strange hours, creating test invoices, reading the error messages line by line, mapping out what existed. I was becoming paranoid, in a mostly-good way.

The hard part about paranoia is knowing when to put it down. I have lost sleep over things that turned out to be fine. I have filed false positives with embarrassing confidence — I once shipped a critical report about a writable S3 bucket because I had tested with aws s3 cp --dryrun, which validates syntax but not IAM. The actual upload failed with AccessDenied. I had to correct my own report the next morning.

Paranoia is useful, but it needs guardrails: a checklist, a second opinion, the willingness to say I was wrong out loud and in writing.

What Tools Catch and What They Miss

People often ask why I do so much of this by hand instead of running Burp Suite, OWASP ZAP, or one of the big enterprise scanners.

I do use those tools. They are excellent at coverage. A DAST scanner will methodically poke every parameter on every endpoint. A dependency scanner will pick up known CVEs in your package-lock.json. These are table stakes — you should run them no matter who is on your team.

But automated tools find known patterns. What I find by hand is different:

  • The CORS rule that accepts any subdomain — technically valid regex, but allows attacker-controlled origins
  • The scientific-notation invoice for one million dollars — 1e6 passes IsNumber() validation because it is a number, but the business logic never expected six figures
  • The internal fields that nobody should be allowed to set, but anyone can — Object.assign(user, req.body) happily merges isDeleted and role along with everything else
  • The webhook that accepts whatever you send it because validation was deferred to an async queue, which also does not validate — a design tradeoff that quietly became a security gap

None of these have a CVE number. They are business-logic vulnerabilities — the consequence of how this specific code, this specific ORM configuration, and this specific architectural decision interact. Scanners do not know a client's business rules; the person who reviews the diff does.

That said, manual testing does not scale. I cannot personally curl every endpoint before every release for every Clearview client. So we run both — automated tools for breadth, a human for depth — and every manual finding becomes a custom rule that catches the next instance automatically.

The Role We Wrote Around It

At some point my late-night reading turned into part of the job. It happened gradually.

First I added security checks inside our Terraform modules — automated S3 bucket policy validation, IAM policy scanning, the kind of guard that would have caught those public buckets before they ever reached production.

Then I started doing quiet pre-deployment reviews. Not formal audits. Just "let me look at this endpoint before it goes live."

Then, on a real client project, I found a vulnerability that would have let anyone create invoices without authentication. No login. No rate limiting. Just curl -X POST and a JSON payload, every minute, forever.

That was the inflection point. Not because it was the scariest finding I have ever shipped a report on, but because there was a dollar sign attached. The team — and the client — could see exactly what an attacker would have done with it. Abstract security risk is easy to deprioritise. A vulnerability that prints fake invoices in your accounting system is not.

After that, the role was real.

Today, at Clearview Team, every new feature we ship to a client gets sent through a pen-tester pass before it lands in production. That pass is a known step in the sprint — scheduled and time-boxed. It is the same engineer (often me) sitting down with the diff and asking, on purpose, how do I break this?

A four-stage sprint flow — Plan, Build, Pen-Tester Pass, Ship. The pen-tester pass is the accented middle stage, run by the same Clearview engineer who knows the codebase. Findings ship as pull requests in the same sprint, and every manual finding becomes a CI rule for the next one.

That is what an in-house pen tester gets you that an external annual audit does not. The feedback loop is short, and the fix usually lands in the same sprint that introduced the risk, not nine months later in a remediation backlog.

What I Catch on the Pen-Tester Pass

Here is the shortlist of categories that show up over and over again across stacks and clients:

Six recurring vulnerability categories shown as a 2-by-3 grid: auth holes on new endpoints, mass assignment via ORM helpers, IDOR or BOLA on numeric IDs, input validation that is really type checking, rate limits that count the wrong IP, and infrastructure drift since the last engagement.

  1. Auth holes on new endpoints. Somebody adds a route, forgets the auth decorator, ships. I catch this before the route hits production by asserting every endpoint either carries @Authorized() or sits on an explicit public-endpoint allowlist.
  2. Mass assignment via ORM helpers. Object.assign(entity, dto) looks innocent. It is not, when the entity has fields the user is never supposed to set. I run a curl against the endpoint with a payload that sets every internal field and see what survives.
  3. IDOR / BOLA on numeric IDs. Anything in a URL of the form /invoices/:id. I swap in another tenant's id and read the response.
  4. Input validation that is actually type checking. IsNumber() lets 1e9 through. IsString() lets a 50 MB payload through. I send the obvious edge cases and read the error messages.
  5. Rate limits that count the wrong IP. If trust proxy is misconfigured, every request looks like it came from the load balancer. I send ten thousand requests with rotating X-Forwarded-For headers and watch what the limiter thinks.
  6. Infrastructure drift since the last engagement. A bucket that was private six months ago is public now because someone toggled a setting in the console. I re-run checkov and tfsec against the live Terraform plan, not just the repo.

None of this is novel. The novelty is that it happens every sprint, by the same person, on the same engagement. Familiarity with the codebase is the hidden multiplier — an external auditor will never find the business-logic invoice bug, because they will not know what an invoice is supposed to look like for this client.

What It Gets the Client

Clearview Team takes on web and mobile build engagements for startups and scaling companies. The teams we work with are usually small, usually shipping fast, and usually one configuration drift away from a story they would rather not be in.

What the client gets:

  • A feature is never the first thing to find a vulnerability in production. A peer reading the diff with an attacker mindset is.
  • They don't pay extra for the security review. It is not a separate procurement, a separate vendor, or a separate quarter. It rides on the same sprint that ships the feature.
  • When we find something, we hand them the fix. I am an engineer. They do not get a thirty-page report — they get a pull request.
  • The codebase gets harder to break the longer we work on it. Every finding becomes a CI rule that catches the next instance automatically. The boundary tightens by itself.
  • No surprise certifications, no surprise breach. When a SOC 2 auditor or a customer due-diligence questionnaire shows up, the answers are already true.

I will not put a percentage on what this prevents — I do not know what would have shipped without it, and Clearview does not invent numbers for sales copy. In the months since this role has been real, no Clearview client has shipped a production-incident-class security bug from a feature that went through the pen-tester pass. The ones we have found in production were inherited from before our engagement, and we wrote up exactly what we found and exactly what we changed.

What This Costs Us

Adding this role to every engagement is not free.

  • A sprint takes a little longer. Time-boxed, but real.
  • Some features get re-scoped. When we hit something structural rather than local during the review, the fix is sometimes an architectural change. That conversation is uncomfortable, and we have it anyway.
  • The pen tester needs a peer. I cannot review my own work alone — I have been wrong before and I will be again. The second opinion is part of the process, not an add-on.

We treat all three as features of the model rather than bugs in it. A feature ships a little slower and holds up better in production.

The Mindset Shift, for Anyone Considering the Move

If you are a DevOps engineer reading this and wondering whether you should make the same shift — you do not need a certification. You do not need to become a full-time pen tester. You need to start asking what if? about the systems you already own.

Five things that helped me, in order:

  1. Audit your own infrastructure first. Run checkov on your Terraform. Check your S3 bucket policies. Review your IAM roles. You will probably find something, and it will motivate everything that follows.
  2. Learn one attack vector deeply. Mass assignment if you use an ORM with auto-mapping. BOLA/IDOR if your API uses sequential IDs. Authentication bypass if you run your own auth flow. SSRF if your app makes outbound HTTP calls based on user input. Pick one. Learn it well enough to spot it in the wild. Then pick another.
  3. Read the detailed breach post-mortems. Not the sensational ones. Cloudflare's. GitLab's. The ones that explain the root cause, the timeline, and what changed. That is where real attacks live.
  4. Break something — in staging, with permission. Find a vulnerability. Exploit it responsibly. Document the steps. See how it feels. That feeling — the mix of excitement and dread — is how you know you are thinking like an attacker.
  5. Turn every finding into a check. Every manual finding should become a rule that runs automatically next time. Found a public S3 bucket? Add a checkov rule. Found a missing auth decorator? Add a CI test that verifies every route is on the auth list. The goal is to make yourself unnecessary for the easy stuff, so you can spend your time on the hard stuff.

The paranoia helps, but the checklists help more.

On this page 9 sections
  1. The Night the Job Description Changed
  2. What an Engineer Reads at Night When They Cannot Sleep
  3. What Tools Catch and What They Miss
  4. The Role We Wrote Around It
  5. What I Catch on the Pen-Tester Pass
  6. What It Gets the Client
  7. What This Costs Us
  8. The Mindset Shift, for Anyone Considering the Move
  9. We Could Put a Pen-Tester Pass on Your Sprint
Type to search. to navigate. Enter to open. Esc to close.