Metadata-Version: 2.4
Name: nulvec
Version: 0.1.6
Summary: Agent supply chain security — scan packages, code, images, PDFs, and MCP payloads for adversarial attacks
Author: Nulvec
License-Expression: MIT
Project-URL: Homepage, https://nulvec.dev
Project-URL: Repository, https://github.com/aryan5v/nulvec
Project-URL: Issues, https://github.com/aryan5v/nulvec/issues
Keywords: ai security,agent supply chain,prompt injection,supply chain attack,pth file,mcp security,llm security
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Security
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: Pillow>=10.0.0
Requires-Dist: pytesseract>=0.3.10
Requires-Dist: PyMuPDF>=1.23.0
Requires-Dist: reportlab>=4.0.0
Requires-Dist: typing-extensions>=4.0.0; python_version < "3.11"
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"

<h1 align="center">⊘ nulvec</h1>

<p align="center">
  Agent supply chain security.<br/>
  Scans packages, code, and agent inputs for attack patterns<br/>
  before they reach your LLM or agent runtime.
</p>

<p align="center">
  <a href="https://pypi.org/project/nulvec/"><img src="https://img.shields.io/pypi/v/nulvec?color=%233fb950" alt="PyPI" /></a>
  <a href="https://pypi.org/project/nulvec/"><img src="https://img.shields.io/pypi/pyversions/nulvec" alt="Python" /></a>
  <a href="https://github.com/aryan5v/nulvec/blob/main/LICENSE"><img src="https://img.shields.io/github/license/aryan5v/nulvec" alt="License" /></a>
</p>

---

- **`.pth` file execution attacks** — catches supply chain payloads like the [LiteLLM 1.82.8 compromise](https://nulvec.dev) that execute on Python startup without any import
- **SKILL.md supply-chain attacks** — pipe-to-shell, private IPs, credential reads
- **prompt injection** in MCP payloads, code comments, PDF layers, and image text
- **credential exfiltration patterns** — SSH keys, cloud configs, env vars
- **hidden PDF payloads** — invisible text, JavaScript actions, embedded files
- **image scaling and steganography attacks** — Trail of Bits style pixel attacks

## Install

```bash
pip install nulvec
```

For image scanning, install Tesseract on the host:

```bash
brew install tesseract
```

## Quick Start

```bash
nulvec scan suspicious-skill.md
nulvec scan . --block-on critical
nulvec install
nulvec skill install ./skills/my-skill
nulvec mcp-proxy -- python my_server.py
nulvec logs
nulvec config show
nulvec status
nulvec doctor
```

## .pth File Scanning (v0.1.5)

Python `.pth` files execute automatically on every interpreter startup — no
import needed. Attackers use them to hide credential-stealing payloads inside
legitimate-looking packages. Standard tools like `pip --require-hashes` and
VirusTotal miss them entirely.

Nulvec detects executable code in `.pth` files with 100% confidence. Legitimate
`.pth` files only contain directory paths — any `subprocess`, `exec`, `eval`,
`base64`, `__import__`, `os.system`, or `Popen` call is always malicious.

```bash
nulvec scan site-packages/  # scans all .pth files in a directory
nulvec scan suspicious.pth  # scan a single .pth file
```

## Python API

```python
import nulvec

result = nulvec.scan("litellm_init.pth")
if result.blocked:
    print(f"{result.decision} — {result.threats[0].type.value}")
    # blocked — supply_chain_exec

result = nulvec.scan("document.pdf")
print(result.decision)  # clean | suspicious | blocked
```

## Machine-Level Install

`nulvec install` creates a local policy file, event log, and Git protection
layer. It installs a Git shim earlier in `PATH`, configures Git template hooks
for future clones, and adds managed hooks to the current repository when run
inside one.

Current support matrix:

- Git clone scanning via temp clone + pre-finalize repo scan
- Git pull scanning for simple `git pull` flows via fetch + temp worktree scan
- Git post-checkout/post-merge hooks as a fallback repo scan layer
- Skill install protection via `nulvec skill install <path-or-url>`
- Approved skill artifact hash cache under the local Nulvec runtime
- Stdio MCP proxy via `nulvec mcp-proxy -- <server command>`
- Local audit events via `nulvec logs`
- Local policy inspection via `nulvec config show`

## Skill Protection Boundary

Nulvec does not automatically intercept arbitrary third-party skill installers.

The protected v1 path is:

```bash
nulvec skill install <path-or-url>
```

If you install a skill through some other CLI, Nulvec does not own that
execution path and cannot honestly claim automatic pre-install protection there.

## MCP Proxy Setup

The MCP proxy is manual in v1. You must point the supported client or server
launch command at:

```bash
nulvec mcp-proxy -- <real server command>
```

This is the right current story for local developer tools such as Codex CLI,
Claude Code, and OpenCode: configure each MCP server entry to launch through
the proxy so Nulvec can scan server responses before they reach the client.

### Codex CLI Example

Codex CLI supports MCP server configuration in TOML via:

- global config: `~/.codex/config.toml`
- per-project config: `.codex/config.toml` for trusted projects

Example stdio wrapper configuration:

```toml
[mcp_servers.context7]
command = "nulvec"
args = ["mcp-proxy", "--", "npx", "-y", "@upstash/context7-mcp"]
```

Notes:

- Codex uses an argv model, not a shell snippet, so wrapper commands must be
  tokenized correctly.
- In controlled environments, MCP allowlist or identity rules may need to be
  updated when the command changes from the original server launcher to
  `nulvec`.

### Claude Code Example

Claude Code supports stdio MCP servers through JSON config or the `claude mcp`
CLI.

Common MCP config locations:

- user/local scope MCP servers: `~/.claude.json`
- project scope MCP servers: `.mcp.json`

Example project config:

```json
{
  "mcpServers": {
    "airtable": {
      "type": "stdio",
      "command": "nulvec",
      "args": ["mcp-proxy", "--", "npx", "-y", "airtable-mcp-server"],
      "env": {}
    }
  }
}
```

Equivalent CLI shape:

```bash
claude mcp add --transport stdio airtable -- nulvec mcp-proxy -- npx -y airtable-mcp-server
```

Notes:

- Claude CLI flag ordering matters. Claude flags must come before the server
  name, and the wrapped server command must come after `--`.
- MCP scope storage is separate from general Claude settings. Do not assume MCP
  local scope lives under `.claude/settings.local.json`.
- In managed environments, exact command-array allowlists can block wrapped
  commands unless the allowlist is updated for the new `nulvec` launcher.

### OpenCode Example

OpenCode stores MCP servers in JSON config and uses a command-array model for
local servers.

Common config locations:

- global config: `~/.config/opencode/opencode.json`
- project config: `opencode.json`

Example local MCP config:

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "server-everything": {
      "type": "local",
      "command": ["nulvec", "mcp-proxy", "--", "npx", "-y", "@modelcontextprotocol/server-everything"],
      "enabled": true
    }
  }
}
```

Notes:

- OpenCode’s local MCP command is already an argv array, which makes wrapper
  insertion straightforward.
- If you later automate rewiring, be careful with config-path detection for
  `.json`, `.jsonc`, and older install-path variants documented by OpenCode.
