Most security teams find out they're exposed the same way an attacker does — by scanning. The
difference is who gets there first. This CTEM program flips that timeline: instead of waiting for
a pentest, a bug bounty report, or an incident to reveal what's exposed, it runs the same
reconnaissance an attacker would run — continuously, against your own footprint — and turns the
output into tracked, owned remediation work before it becomes an incident.
The pipeline mirrors an actual attack chain, stage by stage:
Every major cloud provider now ships a native posture-management or "well-architected" tool —
and on paper, that's convenient. In practice, a lot of these tools quietly meter you into
consumption-based pricing for the AI/analysis layer underneath. AWS's Well-Architected Tool
review itself is free, but plug it into Bedrock-backed recommendations or continuous AI-assisted
analysis, and the bill scales with usage in a way that's hard to forecast and easy to lose track
of — a classic hidden-cost trap for a program that's supposed to be about reducing risk, not
opening a new unpredictable line item.
This toolchain takes the opposite approach on purpose:
| Tool | Category | Function |
|---|---|---|
| theHarvester | ||
| OSINT / Digital Footprint | Passive discovery of hosts, emails, and exposure tied to the domain | |
| Amass / Subfinder | ||
| Attack Surface Management | Enumerate every subdomain forming the external asset inventory | |
| Naabu | ||
| Attack Surface Management | Identify open ports on discovered hosts | |
| httpx | ||
| Attack Surface Management | Confirm which hosts are live and fingerprint the tech running | |
| Nuclei | ||
| Vulnerability Assessment | Detect known CVEs, misconfigurations, and exposed cloud resources via community + custom templates | |
| TruffleHog | ||
| Secret / Credential Exposure | Find live API keys and credentials leaked in code repositories | |
| ScoutSuite | ||
| Cloud Security Posture (CSPM) | Audit cloud account configuration against security best practice | |
| BloodHound + AzureHound / AWSHound | ||
| Identity & Attack Path Analysis | Map privilege-escalation and lateral-movement paths across cloud identity graphs |
A word of caution before you run any of this: verify what you trust
In March 2026, Aqua Security's Trivy — one of the most widely used open-source scanners in the cloud-native ecosystem — was itself compromised. A threat actor tracked as TeamPCP force-pushed malicious tags across the trivy, trivy-action, and setup-trivy GitHub repos and published tampered Docker Hub images, turning a trusted security tool into a credential-harvesting weapon inside thousands of CI/CD pipelines. It's a sharp reminder that a CTEM pipeline built entirely on open-source tooling is only as trustworthy as your verification discipline. Ten lessons worth carrying into how you run this stack:
A "security vendor" label is not a trust guarantee — even scanners get compromised
Version tags (@v1, @latest) are mutable and can be force-pushed by anyone with write access
Pin every GitHub Action and container image to an immutable full commit SHA or digest, never a tag
Credential rotation must be atomic — revoke first, then reissue; a staggered rotation window is an open door
Avoid pull_request_target in any workflow that touches forked PR code — it runs with base-repo secrets against untrusted input
Any CI/CD runner that executed a since-compromised action should have every exposed secret treated as burned, not just rotated
Don't trust an artifact because the filename or registry looks official — verify cryptographically, every time
Use short-lived OIDC tokens for cloud access instead of long-lived static credentials in CI/CD
Watch for anomalous tag movement or force-pushes on the dependencies you consume — it's a detectable signal, not just hindsight
Build a culture where your own tooling gets the same scrutiny you'd apply to a stranger's code — trust is earned per-run, not once
Verify before you run: cosign + SLSA provenance
Before any of the binaries or container images in this pipeline touch your infrastructure, verify both the signature and the build provenance:
cosign verify --certificate-identity-regexp "https://github.com/<org>/<repo>" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
ghcr.io/<org>/<tool>:<version>
slsa-verifier verify-image ghcr.io/<org>/<tool>:<version> \
--source-uri github.com/<org>/<repo> --source-tag v<version>
If either check fails, stop — don't run it "just this once." That two-command habit, run before every tool in this pipeline gets pulled, is the actual signature of a security engineer who double-checks everything rather than trusting the label on the box.
git clone <your-repo-link-here>
cd ctem-pipeline
(Repo link to be added — this is a placeholder for your actual GitHub URL.)
Install prerequisites
Set up the Python virtual environment (see caveat below before you skip this step)
python3 -m venv ctem-venv
source ctem-venv/bin/activate # Windows: ctem-venv\Scripts\activate
pip install -r requirements.txt
go install -v github.com/owasp-amass/amass/v4/...@master
go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest
go install -v github.com/projectdiscovery/naabu/v2/cmd/naabu@latest
go install -v github.com/projectdiscovery/httpx/cmd/httpx@latest
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
./run_ctem.sh -d yourdomain.com
This chains: theHarvester → Amass/Subfinder → Naabu → httpx → Nuclei, writing results into
a /results
directory as structured JSON for downstream ingestion into your SIEM or a
watchlist/dashboard.
scout aws --profile readonly-audit
azurehound list --tenant <tenant-id> -o azurehound-output.json
Import outputs into your BloodHound Neo4j instance to visualize attack paths.
If you run pip install
against your system Python directly, you will very likely hit dependency
conflicts — theHarvester, ScoutSuite, and TruffleHog's Python wrapper each pin different versions
of shared libraries (requests
, boto3
, PyYAML
are common collision points). The symptom is
usually a cryptic ImportError
or version-resolution failure that looks like it's about one tool,
but is actually a transitive dependency clash between two unrelated tools.
Fix: always use an isolated venv per the steps above, and if you still hit an error:
pip install --upgrade pip setuptools wheel
pip install -r requirements.txt --no-cache-dir
If a specific tool's install still fails, isolate it into its own venv rather than fighting
version pins in a shared environment — it costs a few extra seconds of setup and saves hours of
dependency debugging.
This pipeline is designed to be run by anyone with basic CLI familiarity — no dedicated infrastructure, no recurring SaaS bill, and no cloud-vendor lock-in. The goal isn't a fancy dashboard; it's finding what an attacker would find, before they do.