Metadata-Version: 2.4
Name: depsentinel
Version: 0.1.1
Summary: Supply chain attack scanner for PyPI packages — static AST + dynamic sandbox analysis before install
Home-page: https://github.com/Vishnunkumar/depsentinel
Author: Vishnu Nandalkumar
Author-email: vishnunkumar25@gmail.com
License: MIT
Project-URL: Bug Reports, https://github.com/Vishnunkumar/depsentinel/issues
Project-URL: Source, https://github.com/Vishnunkumar/depsentinel
Keywords: security supply-chain malware pypi scanner static-analysis sandbox
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Topic :: Security
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: requests
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: keywords
Dynamic: license
Dynamic: project-url
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# depsentinel 🛡️

**Supply chain attack scanner for PyPI packages.**

Most vulnerability scanners only check against known CVE databases — reactive by nature. `depsentinel` catches what they miss: malicious install hooks, obfuscated payloads, data exfiltration, CPU bombs, and dependency confusion attacks, **before** the package ever runs on your system.

---

## Install

```bash
pip install depsentinel
```

---

## Usage

```bash
# Drop-in replacement for pip install
depsentinel pip install requests
depsentinel pip install numpy pandas

# View scan history
depsentinel audit
```

---

## How It Works

Two phases run in sequence before any package is installed:

### Phase 1 — Static Analysis
Downloads the package without installing it, then inspects:

- **Typosquatting** — Levenshtein distance check against the top 5000 PyPI packages (`requets`, `djano`, etc.)
- **Provenance** — package age, download count, missing source repository
- **AST scan** — parses every `.py` file in the package for:
  - `exec()`/`eval()` with dynamic arguments at module level
  - `base64.b64decode` → `exec` chains (obfuscated payloads)
  - `subprocess`, `os.system`, `os.popen` calls
  - Network calls at module level (`requests.get`, `socket.connect`, etc.)
  - Reads of sensitive files (`.ssh/`, `.aws/credentials`, `.m2/settings.xml`)
  - Environment variable harvesting (`SECRET`, `TOKEN`, `API_KEY`, etc.)
  - High-entropy string literals (encrypted/encoded payloads)
  - `sys.path` mutation (path poisoning)
- **Metadata anomalies** — compiled binaries with no source, git URLs in dependencies

### Phase 2 — Dynamic Sandbox
Imports the package inside an isolated subprocess with:

- CPU time limit (10s hard cap via `RLIMIT_CPU`)
- Memory cap (512MB via `RLIMIT_AS`)
- Process limit (no fork bombs via `RLIMIT_NPROC`)
- Network fully blocked (socket.connect patched)
- Subprocess execution blocked
- Sensitive file reads intercepted

Reports on:
- Import time (infinite loop / CPU bomb detection)
- Background threads spawned on import (crypto miners, C2 beacons)
- Network connection attempts
- Subprocess execution attempts
- Sensitive file access attempts
- Memory growth on import (OOM bomb detection)

---

## Output

```
────────────────────────────────────────────────────
  Scanning: requets

  → requets v0.0.1

  [STATIC]
  ✗ Likely typosquat of 'requests' (edit distance 1)
  ✗ Published 2 days ago
  ✗ Very low downloads: 14/month
  ✗ setup.py calls subprocess.run at module level
  ✗ base64 import + exec() = obfuscated payload pattern

  🚫 Risk: CRITICAL

🚫 Install blocked: requets
```

```
────────────────────────────────────────────────────
  Scanning: requests

  → requests v2.33.1

  [STATIC]
  ✓ Risk: LOW

  [DYNAMIC]
  ✓ Import time OK (0.509s)
  ✓ No unexpected threads spawned
  ✓ No network attempts detected
  ✓ No subprocess calls detected
  ✓ No sensitive file access detected
  ✓ Memory growth OK (+0MB)

  ✓ Risk: OK

✓ All packages passed. Proceeding with install...
```

---

## Risk Levels

| Level    | Action                                      |
|----------|---------------------------------------------|
| OK / LOW | Proceeds automatically                      |
| MEDIUM   | Proceeds with warning logged to audit       |
| HIGH     | Prompts for confirmation before Phase 2     |
| CRITICAL | Hard block — install does not proceed       |

---

## Audit Log

Every scan is appended to `~/.depsentinel_audit.jsonl`:

```bash
depsentinel audit
# 2025-04-13T10:22:01  LOW       requests
# 2025-04-13T10:23:44  CRITICAL  requets
```

---

## Attack Types Detected

| Attack                        | Static | Dynamic |
|-------------------------------|--------|---------|
| Malicious install hooks        | ✅     | ✅      |
| Obfuscated payload (base64+exec) | ✅  | ✅      |
| Credential harvesting         | ✅     | ✅      |
| Network exfiltration          | ✅     | ✅      |
| Typosquatting                 | ✅     | —       |
| Dependency confusion          | ✅     | —       |
| CPU bomb / infinite loop      | ⚠️ partial | ✅  |
| OOM bomb                      | ❌     | ✅      |
| Thread spawning (miner/C2)    | ❌     | ✅      |
| Fork bomb                     | ❌     | ✅      |
| Monkey patching               | ⚠️ partial | ✅  |

---

## Limitations

- Dynamic sandbox uses `setrlimit` — full isolation requires Linux (`unshare --net`). On macOS/Windows, network blocking is applied via socket patching only.
- Transitive dependency scanning (sub-deps) is on the roadmap.
- Maven/Gradle support coming soon.

---

## License

MIT
