Metadata-Version: 2.4
Name: nhi-hunter
Version: 0.1.0
Summary: AWS IAM privilege-escalation graph builder and pathfinder for Non-Human Identities (roles, CI/CD pipelines, service accounts).
Project-URL: Homepage, https://github.com/Prasanna-27eng/nhi-hunter
Project-URL: Repository, https://github.com/Prasanna-27eng/nhi-hunter
Author: Prasanna Kumar Surendran
License-Expression: MIT
License-File: LICENSE
Keywords: attack-graph,aws-security,cloud-security,cspm,iam,non-human-identity,privilege-escalation,purple-team,red-team
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Information Technology
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Security
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: networkx>=3.0
Requires-Dist: rich>=13.0
Requires-Dist: typer>=0.12
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == 'dev'
Description-Content-Type: text/markdown

# nhi-hunter

**An AWS IAM privilege-escalation graph builder and pathfinder for
Non-Human Identities — find the shortest path from a low-privilege role
(a CI/CD pipeline, a service account) to Admin.**

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/)

> ⚠️ For authorized security testing only. Run it against an account you
> own or have explicit permission to assess. `nhi-hunter` only *reads* a
> local JSON dump — it never calls the AWS API and never assumes a role.

---

## Why nhi-hunter?

Modern AWS accounts are full of **Non-Human Identities (NHIs)**: CI/CD
pipeline roles (GitHub Actions OIDC, GitLab runners), Lambda execution
roles, cross-account automation roles. Each one has a permission policy
*and* a trust policy — and the combination of the two, across many
identities, can quietly chain together into a path from "deploy bot" to
"AdministratorAccess".

`nhi-hunter` takes a local AWS IAM authorization-details dump (no live API
calls, no credentials needed beyond the read-only export) and:

1. Parses every role/user, its permission policies (inline + attached
   managed + group), and its trust policy.
2. Builds a directed graph where an edge `A -> B` means **"identity A can
   obtain the effective permissions of identity B"**, via:
   - **`sts:AssumeRole`** — A's policy allows assuming B, *and* B's trust
     policy allows A.
   - **`iam:PassRole` + `lambda:*`** — A can pass role B to a new/updated
     Lambda function and invoke it, running code as B.
3. Finds the shortest path from a `--start-role` to any identity flagged
   as admin (`AdministratorAccess`/`PowerUserAccess` attached, or a
   wildcard `Action: "*", Resource: "*"` statement) and prints it as a
   readable attack tree.

V1 is intentionally narrow — full policy-evaluation completeness is
already covered by mature tools like
[PMapper](https://github.com/nccgroup/PMapper),
[Cloudsplaining](https://github.com/salesforce/cloudsplaining), and
[Cartography](https://github.com/cartography-cncf/cartography). `nhi-hunter`
is for the "give me a readable attack-path tree from this dump, right now"
case — a quick purple-team check, or a CI gate on `terraform plan` output.

---

## Quick start

```bash
pip install nhi-hunter

# Export your account's IAM data (read-only API call):
aws iam get-account-authorization-details > aws_iam_dump.json

nhi-hunter scan --input aws_iam_dump.json --start-role GitHubActionsOIDC
```

```
[*] Loaded 5 identities, 11 escalation edge(s)
[*] Admin/power-user targets: AdminRole, LambdaAdminRole
[*] Searching for escalation paths from 'GitHubActionsOIDC'...

ESCALATION PATH FOUND (1 hop(s)) -> LambdaAdminRole
GitHubActionsOIDC
  --[iam:PassRole + lambda:*]--> LambdaAdminRole

ESCALATION PATH FOUND (2 hop(s)) -> AdminRole
GitHubActionsOIDC
  --[iam:PassRole + lambda:*]--> LambdaAdminRole
  --[iam:PassRole + lambda:*]--> AdminRole

SCAN COMPLETE
┌────────────────────────┬───────┐
│ Metric                  │ Value │
├────────────────────────┼───────┤
│ Escalation paths found  │     2 │
│ Shortest path length    │     1 │
└────────────────────────┴───────┘
```

A multi-hop `sts:AssumeRole` chain looks like this (from the bundled
example dump, `--start-role CIRunner`):

```
ESCALATION PATH FOUND (2 hop(s)) -> AdminRole
CIRunner
  --[sts:AssumeRole]--> DevRole
  --[sts:AssumeRole]--> AdminRole
```

(Note: once a role holds `AdministratorAccess`, it technically has
`iam:PassRole`+`lambda:*`/`sts:AssumeRole` over every other identity too —
this is why `LambdaAdminRole` and `AdminRole` show edges to/from each other
in the example dump. The interesting result is the path *into* the first
admin identity reached from your low-privilege starting role.)

`nhi-hunter scan` exits non-zero if any escalation path is found — usable
as a CI gate on infrastructure changes.

---

## Try it without an AWS account

`examples/sample_iam_dump.json` is a small, deliberately-misconfigured IAM
dump (same data used in the test suite) with two escalation paths baked
in: a 2-hop `sts:AssumeRole` chain (`CIRunner` → `DevRole` → `AdminRole`)
and a 1-hop `iam:PassRole` + Lambda chain (`GitHubActionsOIDC` →
`LambdaAdminRole`).

```bash
nhi-hunter scan --input examples/sample_iam_dump.json --start-role CIRunner
nhi-hunter list-identities --input examples/sample_iam_dump.json
```

---

## Console commands

```
nhi-hunter scan --input <file> --start-role <name> [options]   find escalation paths
nhi-hunter list-identities --input <file>                       list all identities + edges

Scan options:
  -i, --input            AWS IAM authorization-details JSON dump (required)
  -s, --start-role       identity (role or user) name to start from (required)
  -o, --output           write full results as JSON
      --aegistrace-url   report escalation paths to an AegisTrace instance
      --aegistrace-key   AegisTrace ingest API key
```

---

## How the graph is built

| Edge technique | Condition | MITRE ATT&CK |
|---|---|---|
| `sts:AssumeRole` | A's policy allows `sts:AssumeRole` on B's ARN **and** B's trust policy allows A (by ARN, account root, or `*`) | [T1078.004](https://attack.mitre.org/techniques/T1078/004/) Valid Accounts: Cloud Accounts |
| `iam:PassRole + lambda:*` | A's policy allows `iam:PassRole` on B's ARN **and** A can `lambda:CreateFunction`/`UpdateFunctionCode`/`InvokeFunction` | [T1078.004](https://attack.mitre.org/techniques/T1078/004/) |

An identity is flagged **admin** if it has `AdministratorAccess` or
`PowerUserAccess` attached, has a statement granting `Action: "*"` on
`Resource: "*"`, or its name contains "admin"/"poweruser".

**V1 limitations** (documented, not silently swallowed):
- Statements using `NotAction`/`NotResource` are skipped.
- `Condition` blocks are ignored — a reported edge means "policy allows
  this", not "no condition would block it in practice".
- Only identity-to-identity edges are modeled; resource policies (S3
  bucket policies, Lambda resource policies, etc.) are not considered.

---

## AegisTrace integration

[AegisTrace](https://github.com/Prasanna-27eng/AegisTrace)'s Identity Graph
+ Risk Engine models identities and relationships across an environment.
Point `nhi-hunter` at a real account and report any discovered escalation
paths directly:

```bash
nhi-hunter scan \
  --input aws_iam_dump.json \
  --start-role GitHubActionsOIDC \
  --aegistrace-url https://your-aegistrace-instance \
  --aegistrace-key $AEGISTRACE_INGEST_KEY
```

Discovered paths are POSTed to `/api/ingest/nhihunter-event`, creating
`AgentAction(agent_name="nhi-hunter")` entries visible in AegisTrace's
AI Action Approval Queue (`/app/agent-security`) — the same workflow used
for `mcp-aegis` and `prompt-fuzz` findings.

---

## Testing

```bash
pip install -e ".[dev]"
pytest
```

---

## Companion projects

- [mcp-sploit](https://github.com/Prasanna-27eng/mcp-sploit) — Metasploit-style exploitation framework for MCP servers (attacks the AI's tools).
- [prompt-fuzz](https://github.com/Prasanna-27eng/prompt-fuzz) — async LLM jailbreak/prompt-injection fuzzer (attacks the AI's brain).
- [AegisTrace](https://github.com/Prasanna-27eng/AegisTrace) — Trust OS that makes AI agent actions auditable and human-approved.
- [mcp-aegis](https://github.com/Prasanna-27eng/mcp-aegis) — MCP security gateway; blocks dangerous tool calls by default.

---

## License

MIT
