io.github.Baneado98/cloud-pathfinder
IaC attack-path auditor: finds internet-to-crown-jewel chains in Terraform/CFN/K8s.
Open source Repository Open in the app JSON README (API)
About
IaC attack-path auditor: finds internet-to-crown-jewel chains in Terraform/CFN/K8s.
Details
- Kind
- MCP servers
- Topic
- Cloud & DevOps
- Publisher
- baneado98
- Origin
- official
- Category
- ferramentas
- Transport
- http
- Version
- 0.1.0
- Last push
- 2026-06-24T08:20:47Z
- Repository state
- ativo
- Language
- Dockerfile
- License
- MIT
- Added
- 2026-08-29 03:01:42
- Updated
- 2026-08-29 03:01:42
- Origin id
io.github.Baneado98/cloud-pathfinder
README
# cloud-pathfinder π°οΈ
[](./LICENSE)
[](https://github.com/Baneado98/cloud-pathfinder)
[](https://www.npmjs.com/package/cloud-pathfinder-mcp)
[](https://cloud-pathfinder.vercel.app)
[](#sarif-210--github-code-scanning)
**Attack-path auditor for Infrastructure-as-Code β Terraform, CloudFormation, Kubernetes, CDK, Pulumi, Bicep/ARM.**
Not a linter. It parses your IaC into a **resource graph**, resolves cross-resource (and cross-file) relationships, and searches for the **multi-hop chains from the public internet to your crown jewels** (data stores, secrets, admin). It returns a `BREACHABLE / EXPOSED / HARDENED` verdict and the concrete route an attacker would walk.
> Example chain it finds:
> `open security group (SSH 0.0.0.0/0) β EC2 instance-profile role β iam:PassRole privilege escalation to admin β S3 exfiltration`
Available as an **MCP server** (Claude, Cursor, any MCP agent) and a **pay-per-call x402 API** (autonomous AI agents with a wallet).
---
## π Privacy & data model (read this first)
Sending your IaC to a third party is sensitive β so here is **exactly** what happens:
- **Your IaC is never stored and never logged.** Every audit runs **in memory** on
the hosted service and is **discarded** when the response is sent. No database of
your templates, no retention, no analytics on file contents.
- **What is sent:** only the IaC text you pass (the `files` map or `source` blob).
Nothing is read from your machine, your cloud account, or your credentials β
**cloud-pathfinder never touches a live cloud** (see "honest limits" below). There
are **no cloud keys to provide** because it analyzes the *declared* templates only.
- **Free tier vs deep tier β both run server-side, here's why and what differs:**
- The thin npm client ships **zero analysis logic** (no graph engine, no IAM
privesc knowledge base). It is a pure HTTP caller. So even the **free verdict +
counts** are computed on the hosted service, then your IaC is dropped. This is
the honest tradeoff that keeps the moat off your machine β we say so plainly
rather than claim a fake "100% local" mode.
- **Deep analysis is strictly opt-in** (`deep: true`, behind payment). Only then
are the full chains, file:line evidence and remediation returned. You send the
same IaC either way β nothing *extra* leaves your machine for the deep tier.
> **Hosted service:** https://cloud-pathfinder.vercel.app β all analysis runs
> server-side. This npm package is a **thin MCP client**: it sends the IaC text to
> the hosted endpoint and renders the verdict. No analysis logic ships to your machine.
---
## β‘ How it works (30 seconds)
1. Your MCP agent calls `audit_iac_attack_paths { files: { "main.tf": "..." } }`.
2. The thin client POSTs the IaC text to `https://cloud-pathfinder.vercel.app`.
3. The hosted engine builds a typed **resource graph**, runs a BFS from an
`INTERNET` node to every data store / secret / admin sink, and resolves IAM
privilege-escalation reachability along each hop β **in memory**.
4. The IaC is **discarded**; nothing is persisted.
5. The deep tier returns every full chain with per-hop `file:line` evidence; the
free tier returns the verdict, score and counts.
The npm tarball contains only the HTTP caller β so **nothing, free or deep, runs
offline**. Without the server it degrades to a clear network error.
---
## π Why this isn't a linter (and why a local one can't replace it)
A linter flags resources one at a time: "this SG is open", "this role is broad".
cloud-pathfinder reasons about how those facts **connect** β work a per-file local
tool structurally cannot do:
| Capability | Local linter | **cloud-pathfinder** |
|---|:---:|:---:|
| Flag one open SG / one broad role | β
| β
|
| **Graph** β which SG attaches to which instance, which role it assumes, what it reads | β | β
|
| **Reachability BFS** internet β crown jewel, full multi-hop chain + file:line | β | β
|
| **IAM privilege-escalation KB** (20+ primitives: PassRole, CreatePolicyVersionβ¦) | β | β
|
| **Multi-cloud** β AWS / GCP / Azure in one graph | β | β
|
| **Choke-point** analysis (the one hop that, fixed, cuts the most paths) | β | β
|
| **Diff mode** β what a PR INTRODUCES / ELIMINATES / AGGRAVATES | β | β
|
| **Kubernetes** LB/NodePort β privileged pod β cluster-admin SA β Secret | β | β
|
| **SARIF 2.1.0** for GitHub code scanning (inline chains on the Security tab) | β | β
|
- **π Graph, not lint.** Builds a typed resource graph and resolves the real
relationships across files and clouds.
- **π§ Reachability search.** BFS from `INTERNET` to every data store / secret /
admin sink, returning the full multi-hop chain with **per-hop file:line evidence**.
- **π IAM privilege-escalation knowledge base.** Knows AWS managed-policy
permissions and **20+ privilege-escalation primitives** (PassRole+RunInstances,
CreatePolicyVersion, AttachRolePolicy, SSM SendCommand, UpdateFunctionCode,
UpdateAssumeRolePolicyβ¦).
- **βΈοΈ Kubernetes attack surface.** LoadBalancer/NodePort exposure β privileged /
hostPath / hostNetwork pods, **cluster-admin ServiceAccounts**, and mounted Secrets.
Formats are **auto-detected per file** and analyzed **together** β mix `.tf`,
CloudFormation `.yaml/.json` and Kubernetes manifests in one call.
---
## π Quickstart β add it to your MCP client
```json
{
"mcpServers": {
"cloud-pathfinder": { "command": "npx", "args": ["-y", "cloud-pathfinder-mcp"] }
}
}
```
No key needed for the free tier. Restart your client and the
**`audit_iac_attack_paths`** + **`diff_attack_paths`** tools appear. (Remote server:
`https://cloud-pathfinder.vercel.app/mcp`.)
### Tool: `audit_iac_attack_paths`
```jsonc
{
"files": {
"main.tf": "resource \"aws_security_group\" \"web\" { ingress { ... cidr_blocks = [\"0.0.0.0/0\"] } } ...",
"k8s.yaml": "apiVersion: v1\nkind: Service\n..."
}
// or: "source": "<a single IaC blob>", "filename": "main.tf"
}
```
### Example β input β output
```
audit_iac_attack_paths { "files": { "main.tf": "<SG open to 0.0.0.0/0 on 22 +
EC2 with instance-profile role that can s3:* + iam:PassRole>" } }
β FREE: verdict: BREACHABLE Β· risk 86/100 Β· 1 attack path Β· 1 crown jewel Β· 3 misconfigs
β DEEP (deep:true): verdict: BREACHABLE
PATH #1 (internet β admin):
[1] INTERNET β aws_security_group.web (main.tf:4 β ingress 22 from 0.0.0.0/0)
[2] β aws_instance.app (main.tf:19 β attaches sg web)
[3] β aws_iam_role.app_role (main.tf:31 β instance profile)
[4] β iam:PassRole + ec2:RunInstances (privesc β launch instance as admin role)
[5] β s3:* on aws_s3_bucket.data (main.tf:52 β exfiltration sink)
CHOKE POINT: tighten main.tf:4 ingress β cuts this entire path.
FIX: restrict ingress CIDR; split the role; add a permissions boundary.
```
The **free** tier returns the verdict, risk score, and the **counts** (how many
attack paths, crown jewels and misconfigurations). The **deep** tier returns every
full chain with hops, file:line evidence, privilege-escalation reachability and
remediation.
### Tool: `diff_attack_paths` β the CI/CD gate
Give it the IaC **before** and **after** a change (a PR's base and head trees) and it
reports exactly what the change did to your attack surface: which internetβcrown-jewel
chains it **INTRODUCES**, which it **ELIMINATES**, and which it **AGGRAVATES** β with
an `INTRODUCES_BREACH` / `REDUCES_RISK` / `NEUTRAL` / `MIXED` verdict.
```jsonc
{
"before": { "files": { "main.tf": "...security group admits 10.0.0.0/16..." } },
"after": { "files": { "main.tf": "...security group admits 0.0.0.0/0..." } }
// deep: true β full introduced/eliminated chains + beforeβafter exploitability + which choke points now matter
}
```
A per-file linter or a single-state scan cannot answer this: it needs the full graph
+ privesc reachability on **both** states and a semantic cross-state path match.
HTTP: `POST /diff` (free, counts only) / `POST /pro/diff` (deep).
## Free HTTP API
```http
POST /audit
Content-Type: application/json
{ "files": { "main.tf": "resource \"aws_security_group\" ..." } }
```
Rate-limited to 30 requests/hour/IP. For unlimited/commercial/deep use, call `/pro/audit`.
**Input formats:** Terraform / OpenTofu, CloudFormation, Kubernetes, Helm, Kustomize,
Pulumi (TS/JS/Python), Bicep/ARM, and **AWS CDK** β both the synthesized
`cdk.out/*.template.json` and the **un-synthed CDK program** (TypeScript + Python),
so a CI gate runs on the PR diff before `cdk synth`.
---
## SARIF 2.1.0 β GitHub code scanning
Add `?format=sarif` (or `{ "format": "sarif" }`) to `/audit`, `/pro/audit`, `/diff`
or `/pro/diff` to get **SARIF 2.1.0** you can upload to **GitHub code scanning** β
every attack chain shows up inline on the PR's Security tab.
- Each chain is one SARIF `result` with a **`codeFlow`** (a step-through walk:
internet β SG β instance role β privesc β S3), anchored to the IaC `file:line`,
plus `security-severity`/CVSS so the badge colors correctly.
- The **diff** SARIF only fails the check on **introduced/aggravated** routes
(error-level); eliminated/eased land as `note`.
- The **free** tier returns a redacted-but-schema-valid SARIF (counts only β no
chains, no code-flows, no route file:line); the full code-flows are premium.
```yaml
# .github/workflows/cloud-pathfinder.yml (sketch)
- run: curl -s -X POST "$CPF/pro/diff?format=sarif" -H "Authorization: Bearer $KEY" \
--data @payload.json -o cloud-pathfinder.sarif
- uses: github/codeql-action/upload-sarif@v3
with: { sarif_file: cloud-pathfinder.sarif }
```
---
## π³ Unlock `/pro` β two ways to pay (dual-pay)
The deep `/pro/audit` returns the **full attack chains**, **per-hop evidence**,
**privilege-escalation analysis** and **remediation**. Two payment lanes coexist:
| Lane | For | How |
|---|---|---|
| π³ **Card (Stripe)** | Humans / teams | Buy a prepaid key at `/pro/checkout`, then send `Authorization: Bearer <key>` (or set `CLOUD_PATHFINDER_KEY`). |
| πͺ **x402 (USDC)** | AI agents with a wallet | Pay **$0.30** per call automatically. Settles on Base. No signup, no key. |
```http
POST /pro/audit # 402 (shows BOTH lanes) β pay β result
```
---
## What it catches (selected)
| Class | Detail |
|---|---|
| Public β role β data | Open SG on a sensitive port (SSH/RDP/DB) β instance role that can read S3/Dynamo/RDS/Secrets β exfiltration |
| IAM privilege escalation | `iam:PassRole`+`ec2:RunInstances`, `iam:CreatePolicyVersion`, `iam:AttachRolePolicy`, `ssm:SendCommand`, wildcard `*` on `*`, and ~15 more |
| Public data stores | `publicly_accessible = true` RDS, world-open buckets |
| Kubernetes | LoadBalancer/NodePort β privileged pod β cluster-admin ServiceAccount β Secret |
| CloudFormation | `!Ref`/`!GetAtt` intrinsics resolved; `ManagedPolicyArns`/inline policies analyzed |
---
## How it stays honest
The premium **engine and knowledge base never ship in the npm package** β the
published client is a thin renderer that calls the hosted analysis service. The free
tier is genuinely useful (verdict + counts); the deep chains, evidence and privesc
analysis are server-side behind payment.
**Heuristic static analysis of declared IaC**, not a live cloud assessment. It
reasons over what the templates declare (no runtime SCP/permissions-boundary/condition
evaluation). Treat findings as prioritized leads, not a guarantee.
MIT Β· [github.com/Baneado98/cloud-pathfinder](https://github.com/Baneado98/cloud-pathfinder)