Programming

I Stopped "Compiling and Praying" When I Realized Security Isn't My QA Team's Job

A

Admin User

Author

Jul 6, 2026
5 min read
9 views
I Stopped "Compiling and Praying" When I Realized Security Isn't My QA Team's Job

I remember the exact moment I knew something was broken in my workflow. It was 2 AM, a Saturday, and I was sitting in a Slack thread with five other engineers explaining why a SQL injection vulnerability made it to production. The conversation kept circling back to the same question: "How did this slip through code review?" The answer, if I'm being honest, was that we were treating security like a checkbox at the end of the pipeline instead of something baked into how we actually build.

That's when I read something that reframed everything: the idea that "compile and pray" isn't a deployment strategy—it's a cry for help. And I realized I'd been doing exactly that for years. Running tests, shipping code, hoping nothing broke. No staging environment security scans, no static analysis on PRs, no clear separation between what catches bugs during development and what catches vulnerabilities when the app is actually running.

The Thing Nobody Tells You About SAST and DAST

Here's what I've learned: most developers hear "SAST" and "DAST" and think they're interchangeable. They're not. Not even close.

SAST—Static Application Security Testing—works like having an obsessive code reviewer who reads every line before it ever runs. It catches hardcoded secrets, SQL injection patterns, insecure cryptography calls. The tool doesn't care if your app is running; it just cares about what's written. Tools like SonarQube and Semgrep live in this space.

DAST—Dynamic Application Security Testing—is the opposite. It waits until your app is actually running, then treats it like a real attacker would. Manipulating requests, fuzzing inputs, checking for XSS holes and broken authentication. OWASP ZAP and Burp Suite do this.

The mistake I made? I was relying on DAST alone, running security scans in production (or close to it). That's backwards. SAST should catch low-hanging fruit on every commit. DAST should only run against a staging environment, where you can safely simulate attacks without risking user data.

The Pipeline That Actually Works

I started thinking about this differently after I restructured how my team handles CI/CD. We moved from "everything runs before production" to "the right tool at the right time."

On commit, SAST kicks in immediately. A developer pushes code, and within seconds they know if they've accidentally hardcoded an API key or written vulnerable SQL. That's the fastest feedback loop possible—and the cheapest to fix.

During build, we added Software Composition Analysis (SCA) to scan dependencies for known CVEs. Nobody wants to ship a package with a disclosed vulnerability.

Only after deploying to staging does DAST run. This is where we simulate real attacks without touching production. If something breaks here, we've found it in a safe place.

My Take: Security Isn't Separate From Quality

What struck me most about this approach is that it stops treating security as some external requirement bolted onto development. It's just... good testing at the right stage.

The comparison the article makes—about building a fortress, starting with the moat (unit tests) before the catapult (DAST)—actually changed how I explain this to junior developers. You can't secure broken code. Unit tests that verify sanitization functions work as intended? That's your real defense against XSS. Integration tests that verify tokens expire and permissions don't leak? That's your actual security investment.

Where I diverge slightly is on tooling. I've found that the best SAST tool is often the one your team will actually use. SonarQube is powerful but heavy. Semgrep is faster but requires more tuning. Snyk works well if you're already in the JavaScript/Node ecosystem. Don't get paralyzed choosing—pick one and actually run it on every PR.

A Practical Reality Check

Here's what a minimal setup looks like in GitHub Actions:

name: Security Checks
on: [pull_request]

jobs:
  sast:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run Semgrep
        run: semgrep ci --config=p/owasp-top-ten
      
  sca:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Check dependencies
        run: npm audit --audit-level=moderate

Nothing fancy. But this catches vulnerabilities before code review even starts. The cost? A few extra minutes per build.

What I'm Still Figuring Out

The hardest part isn't the tools—it's convincing teams that this matters when there's a feature deadline. I'm still working on that conversation. How do you balance shipping fast with shipping securely? I'd genuinely like to know how other teams in Islamabad's tech scene are handling this.

The old way—compile and pray—doesn't work anymore. Not at scale, not in production, not when a breach costs millions. The good news? The alternative isn't expensive. It just requires thinking differently about when security gets checked.

Source: This post was inspired by "# Compila e Reza? — Segurança e Qualidade na Prática: O Papel do SAST, DAST e Testes Automatizados no Ciclo de Vida do Software Moderno" by Dev.to. Read the original article

Share this article

Written by Adil Sher

Full stack developer building high-traffic platforms, AI services, and custom web applications. Explore my portfolio, learn about my background, or get in touch.

Related Articles

Code Isn't Engineering Until You Stop Thinking It Is
Programming Jul 17

Code Isn't Engineering Until You Stop Thinking It Is

Someone asked me last week what I actually do for a living. Not in the polite "oh that's nice" way—genuinely curious. I said "I'm a developer" and watched their face go blank. They nodded like I'd said "I work in an office." It hit me that I couldn't explain my job any better tha...

PHP Forms Aren't Broken—Your Expectations Are
Programming Jul 16

PHP Forms Aren't Broken—Your Expectations Are

I spent two hours last week debugging a form that "wasn't working." The client said data wasn't being saved. I pulled up the network tab, saw the POST request going out clean, checked the database, and found... nothing. Then I looked at the form's action attribute. It was pointin...