SAST vs SCA vs Secrets Detection vs IaC Scanning: A Practical Guide
By Fimil Team
Application security testing isn’t one thing — it’s at least five different things, each catching a fundamentally different class of vulnerability. Most teams know they should be “scanning their code,” but the landscape of tools and acronyms can be overwhelming. SAST, SCA, DAST, IAST, SBOM, IaC — it starts to feel like alphabet soup.
This guide breaks down the five categories of application security testing that matter most for modern development teams. For each one, we’ll cover what it is, what it catches, what it misses, and which open-source tools are best-in-class. By the end, you’ll have a clear mental model for what a comprehensive security testing strategy looks like.
SAST: Static Application Security Testing
What it catches
SAST tools parse your code into an abstract syntax tree (AST) and search for patterns that match known vulnerability signatures. The kinds of issues SAST finds include:
- Injection vulnerabilities — SQL injection, command injection, XSS, and other cases where user input flows into dangerous functions without sanitization
- Insecure cryptography — Use of weak algorithms (MD5, SHA1 for security-sensitive operations), hardcoded encryption keys, insufficient key lengths
- Authentication flaws — Missing authentication checks on sensitive endpoints, insecure session management, improper credential handling
- Unsafe deserialization — Deserializing untrusted data that could lead to remote code execution
- Path traversal — File system operations using unsanitized user input
- Race conditions — Time-of-check-to-time-of-use (TOCTOU) bugs in concurrent code
Here’s a concrete example. A SAST scanner would flag this Python code:
@app.route("/users")
def get_user():
user_id = request.args.get("id")
query = f"SELECT * FROM users WHERE id = {user_id}" # SQL injection
result = db.execute(query)
return jsonify(result)
The tool recognizes that request.args.get() is a user-input source and db.execute() is a dangerous sink, and that the data flows from source to sink without sanitization.
What it misses
SAST operates on code patterns, not runtime behavior. It can’t detect vulnerabilities that only manifest at runtime (like misconfigured authentication middleware), issues in dynamically-generated code, or business logic flaws. It also tends to produce false positives on complex data flows where sanitization happens in a non-obvious way.
Best open-source tools
- Semgrep — Pattern-based analysis supporting 30+ languages. Fast, low false-positive rate.
- Bandit — Python-specific security linter. Catches Python security anti-patterns.
- Gosec — Go-specific security checker. Understands Go concurrency pitfalls.
When you need it: Always. SAST is the foundation of any application security program. If you’re only going to run one type of security testing, make it SAST.
SCA: Software Composition Analysis
What it catches
SCA tools read your dependency manifests and lockfiles, then cross-reference each package and version against known CVE databases:
- Known CVEs in direct dependencies — Vulnerabilities in the libraries you explicitly import, like a remote code execution bug in a specific version of
lodashorlog4j - Known CVEs in transitive dependencies — Vulnerabilities in the dependencies of your dependencies. Your app doesn’t import
minimistdirectly, butwebpackdoes, and that version ofminimisthas a prototype pollution vulnerability - License compliance issues — Some SCA tools also flag dependencies with licenses that conflict with your project’s license requirements (GPL in a proprietary project, for example)
- Outdated packages — Identifying dependencies that are significantly behind the latest version, which often correlates with unpatched vulnerabilities
Here’s what an SCA finding looks like in practice:
Package: express
Version: 4.17.1
CVE: CVE-2024-XXXXX
Severity: High
Fixed In: 4.18.2
Summary: Open redirect vulnerability in express.static middleware
The fix is typically straightforward: update the package to a version where the CVE is patched.
What it misses
SCA only knows about known, published vulnerabilities. A zero-day in one of your dependencies won’t be flagged until a CVE is issued. SCA also can’t tell you if a vulnerable function in a dependency is actually reachable from your code — a critical distinction that reachability analysis addresses.
Best open-source tools
- Trivy — Scans dependencies, container images, IaC, and more. Supports virtually every package ecosystem.
- Grype — Anchore's vulnerability scanner. Excellent accuracy, fast scanning.
- OSV-Scanner — Google's scanner using the Open Source Vulnerabilities database.
When you need it: As soon as you have any third-party dependencies — which is every modern project.
Why Run Multiple SCA Scanners?
You might wonder why Fimil runs Trivy, Grype, and OSV-Scanner when they all do SCA. The answer is coverage. Each tool pulls from slightly different vulnerability databases and uses different matching algorithms. Trivy might catch a CVE that Grype misses because it hasn’t been added to Grype’s database yet, and vice versa. Running multiple tools and deduplicating the results gives you the broadest possible coverage without the noise of seeing the same CVE three times.
Secrets Detection
What it catches
Secrets scanners use a combination of pattern matching (regex), entropy analysis (detecting high-entropy strings that look like keys), and known key format detection:
- API keys — AWS access keys (
AKIA...), Google Cloud service account keys, Stripe keys (sk_live_...), Slack tokens (xoxb-...), and hundreds of other vendor-specific formats - Database credentials — Connection strings with embedded passwords, hardcoded database passwords in config files
- Private keys — SSH private keys, TLS/SSL certificates with private keys, PGP private keys
- OAuth tokens — GitHub personal access tokens, GitLab tokens, Bitbucket app passwords
- Generic passwords — Variables named
password,secret, orapi_keywith hardcoded string values
This is one of the most critical scanning categories because leaked secrets in git history persist forever — even if you delete the file in a later commit, the secret is still in the git log. Here’s a common example:
# config.py
AWS_ACCESS_KEY = "AKIAIOSFODNN7EXAMPLE"
AWS_SECRET_KEY = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
Even if a developer catches this in code review and removes it in the next commit, both keys are permanently in the git history. An attacker with read access to the repository can find them by searching the history.
What it misses
Secrets scanners can’t detect credentials stored in external secret management systems (which is the correct approach). They can also struggle with custom secret formats that don’t match known patterns, and with secrets that are split across multiple variables or config files. False positives are common with entropy-based detection — randomly generated IDs and test fixtures often look like secrets.
Best open-source tools
- Gitleaks — Fast, configurable secrets scanner with git history support. Great for CI/CD pipelines.
- TruffleHog — Deep scanning with secret verification — it can check if a detected key is still valid.
When you need it: If your code has ever touched a credential — and it has — you need secrets detection. Scan git history, not just the current state of the code.
Pro tip: Even if you’re diligent about never committing secrets, run a one-time full history scan. You’d be surprised what you find from before
.gitignorerules were in place.
IaC Scanning: Infrastructure as Code Security
What it catches
IaC scanners check your infrastructure definitions against security best practices and compliance frameworks:
- Overly permissive IAM policies — S3 buckets with public read access, IAM roles with
*:*permissions, security groups allowing 0.0.0.0/0 ingress - Missing encryption — Unencrypted EBS volumes, S3 buckets without server-side encryption, RDS instances without encryption at rest
- Insecure defaults — Databases accessible from the public internet, containers running as root, Kubernetes pods without security contexts
- Compliance violations — Configurations that violate CIS benchmarks, SOC2 controls, PCI-DSS requirements, or HIPAA safeguards
- Dockerfile issues — Running as root, using
latesttag (no version pinning), copying secrets into images, missing health checks
Here’s a Terraform example that would be flagged:
resource "aws_s3_bucket" "data" {
bucket = "company-sensitive-data"
# Missing: encryption configuration
# Missing: public access block
# Missing: versioning
# Missing: logging
}
An IaC scanner would flag this bucket for missing encryption, no public access block, no versioning, and no access logging — four distinct security issues, all catchable before the infrastructure is provisioned.
What it misses
IaC scanners analyze the definitions, not the running infrastructure. They can’t detect drift (where the actual cloud state has diverged from the code), runtime misconfigurations made manually in the cloud console, or vulnerabilities in the applications running on the infrastructure.
Best open-source tools
- Checkov — The most comprehensive IaC scanner. Supports Terraform, CloudFormation, Kubernetes, Helm, and more. Built-in CIS/SOC2/PCI-DSS mappings.
- Hadolint — Specialized Dockerfile linter. Catches privilege escalation and inefficient layer caching.
When you need it: As soon as you manage infrastructure through code. Catching a publicly-accessible S3 bucket in code review is infinitely cheaper than discovering it after a data breach.
Container Security
What it catches
Container image scanning examines the layers of a built container image to find:
- OS-level vulnerabilities — Outdated packages in the base image (Alpine, Debian, Ubuntu). A
python:3.11-slimbase image might have 20 known CVEs in its system libraries - Application-level vulnerabilities — Libraries installed via
pip install,npm install, orapt-get installinside the Dockerfile - Misconfigurations — Images running as root, missing health checks, excessive capabilities
- Malware — Some scanners can detect known malicious packages or backdoors in image layers
Container scanning is distinct from SCA because it scans the built artifact, not just the dependency manifest. Your requirements.txt might specify flask>=2.0, but the actual version installed in the container could be different. Container scanning sees what’s actually in the image.
What it misses
Container scanners analyze images at rest, not running containers. They can’t detect runtime attacks, container escapes, or dynamic behavior. They also can’t see into encrypted or obfuscated content within the image.
Best open-source tools
- Trivy — The same Trivy used for SCA also excels at container image scanning. Fast, comprehensive.
- Grype — Also supports container image scanning alongside dependency scanning.
When you need it: If you deploy containers — and most modern applications do — you need container image scanning. Base images accumulate vulnerabilities silently over time.
How They All Fit Together
Each scanning category catches a different class of vulnerability:
| Category | What It Analyzes | What It Catches |
|---|---|---|
| SAST | Your source code | Code-level bugs (injection, XSS, crypto) |
| SCA | Your dependencies | Known CVEs in libraries |
| Secrets | Your code + git history | Hardcoded credentials |
| IaC | Your infra definitions | Cloud misconfigurations |
| Container | Your built images | OS and image-level CVEs |
None of these categories is a substitute for another. A codebase can have perfect SAST results (no injection vulnerabilities in your own code) while having critical SCA findings (a dependency with a known RCE) and leaked secrets in the git history. A comprehensive security testing strategy runs all five categories.
The challenge, of course, is that running five categories of scanners — potentially 12+ individual tools — produces a massive volume of findings. Many of those findings are duplicates across tools, and the noise can be paralyzing.
Bottom line: No single scanning category covers everything. A comprehensive strategy needs all five.
This is exactly the problem Fimil solves. We orchestrate all of these scanner categories behind a single dashboard, deduplicate findings across tools, and prioritize using EPSS scores and reachability analysis so you see the 15 findings that matter — not the 2,000 that don’t.
A Practical Starting Point
If you’re just getting started with application security testing, here’s a pragmatic order of operations:
-
Start with SCA. It’s the easiest to set up (just point it at your lockfiles) and often reveals critical vulnerabilities with straightforward fixes (update a package version). The ROI is immediate.
-
Add secrets detection. Run it once against your full git history — you might be surprised what you find. Then add it to CI to prevent new secrets from being committed.
-
Add SAST. Start with Semgrep using the
--config=autorule set. It has a low false-positive rate and catches the most impactful patterns. Tune from there. -
Add IaC scanning if you have infrastructure-as-code. Checkov’s default rules catch the most common cloud misconfigurations.
-
Add container scanning if you deploy containers. Scan your images as part of your CI/CD pipeline so vulnerabilities are caught before deployment.
Or skip the incremental setup and let Fimil run all of them at once. We’ll figure out which scanners your codebase needs, run them, deduplicate the results, and show you what matters. You can compare how this stacks up against running individual tools or using alternative platforms.
Have questions about which scanning categories your team should prioritize? Get in touch — we’re happy to help you build a security testing strategy that fits your stack and your team size.