# Building a Continuous Threat Exposure Management (CTEM) Program — Open Source, Cloud-Agnostic, and Zero Hidden Cost

> Source: <https://dev.to/gauravgarv4u/building-a-continuous-threat-exposure-management-ctem-program-open-source-cloud-agnostic-and-3keg>
> Published: 2026-09-02 07:27:10+00:00

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](https://dev.to/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:

```
# Verify the image was signed by the expected publisher via Sigstore/cosign keyless signing
cosign verify --certificate-identity-regexp "https://github.com/<org>/<repo>" \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  ghcr.io/<org>/<tool>:<version>

# Verify SLSA provenance attestation matches this exact artifact, not just any release
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.*
