Skip to main content

Perceptual AI security — scan images, PDFs, and web content for adversarial injections

Project description

Nulvec

Nulvec is a local-first security scanner for agent inputs.

It scans files and repositories for high-signal attack patterns before they reach an LLM or agent runtime:

  • SKILL.md supply-chain attacks
  • prompt injection in MCP payloads and code comments
  • credential exfiltration patterns
  • hidden PDF and image payloads
  • image scaling and steganography attacks

Install

pip install nulvec

For image scanning, install Tesseract on the host:

brew install tesseract

Quick Start

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

Python API

import nulvec

result = nulvec.scan("document.pdf")
print(result.decision)

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:

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:

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:

[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:

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

Equivalent CLI shape:

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:

{
  "$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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nulvec-0.1.0.tar.gz (46.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nulvec-0.1.0-py3-none-any.whl (45.1 kB view details)

Uploaded Python 3

File details

Details for the file nulvec-0.1.0.tar.gz.

File metadata

  • Download URL: nulvec-0.1.0.tar.gz
  • Upload date:
  • Size: 46.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for nulvec-0.1.0.tar.gz
Algorithm Hash digest
SHA256 7bf012f7751b7fd148084c64bd03dd7d84cf4b1de3bb4521b39559517415e9a8
MD5 f946ff376978948ca2ca4a1030fc621e
BLAKE2b-256 c1bce2a72e2769e2f9fddb208bb9d6e8198261d875362f3d6080cd4cb4552375

See more details on using hashes here.

Provenance

The following attestation bundles were made for nulvec-0.1.0.tar.gz:

Publisher: publish-nulvec.yml on aryan5v/nulvec

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file nulvec-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: nulvec-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 45.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for nulvec-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d875b347ca3d30df6e3f4b89e54eae18ac3b8b975119db6a7218e8b0512f9fae
MD5 bb62d6ce844fe208dfda6e4d5f706f49
BLAKE2b-256 7cb98f34bf3953d855c5fcc8ad1bc5d079d4295196910cd89b15b23f0f5fe74c

See more details on using hashes here.

Provenance

The following attestation bundles were made for nulvec-0.1.0-py3-none-any.whl:

Publisher: publish-nulvec.yml on aryan5v/nulvec

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page