Metadata-Version: 2.4
Name: blastcontain-verify
Version: 0.4.0
Summary: Pre-deployment compliance scanner for AI agents — 27 security checks, SARIF output, signed audit packets
Project-URL: Homepage, https://github.com/blastcontain/verify
Project-URL: Repository, https://github.com/blastcontain/verify
Project-URL: Issues, https://github.com/blastcontain/verify/issues
Project-URL: Documentation, https://github.com/blastcontain/verify/blob/main/docs/spec.md
Author: BlastContain Contributors
License: Apache-2.0
License-File: LICENSE
License-File: NOTICE
Keywords: agent-security,ai-safety,compliance,mcp,mit-ai-risk,presidio,sarif,scanner
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.11
Requires-Dist: blastcontain-core<1.0,>=0.1
Requires-Dist: click>=8.1
Requires-Dist: httpx>=0.27
Requires-Dist: pyyaml>=6.0
Provides-Extra: agt
Requires-Dist: agent-governance-toolkit>=4.1; extra == 'agt'
Provides-Extra: cisco
Requires-Dist: cisco-ai-skill-scanner>=2.0.12; extra == 'cisco'
Provides-Extra: dev
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest-timeout>=2.3; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Provides-Extra: full
Requires-Dist: agent-governance-toolkit>=4.1; extra == 'full'
Requires-Dist: presidio-analyzer>=2.2; extra == 'full'
Requires-Dist: presidio-anonymizer>=2.2; extra == 'full'
Provides-Extra: pii
Requires-Dist: presidio-analyzer>=2.2; extra == 'pii'
Requires-Dist: presidio-anonymizer>=2.2; extra == 'pii'
Provides-Extra: skill
Requires-Dist: cisco-ai-skill-scanner>=2.0.12; extra == 'skill'
Description-Content-Type: text/markdown

# blastcontain-verify

Pre-deployment compliance scanner for AI agents. 27 security checks across 14 categories. Outputs Markdown reports, signed JSON audit packets, and SARIF for GitHub Code Scanning.

```
pip install blastcontain-verify
blastcontain-verify --agent-id my-agent --env prod --search-path ./src
```

## What it checks

| Group | Checks |
|---|---|
| Environment | kernel isolation, egress restriction, model weight mutability |
| Filesystem | workstation rootfs, container rootfs |
| Credentials | secrets on disk, secrets in process env, wildcard API capability |
| Process | running as root, dangerous Linux capabilities |
| Network | DNS exfiltration channel, external listeners |
| Persistence | writable startup/cron paths |
| Memory | unmasked PII in context, vector store tenant isolation, viable PII exfil path |
| Skills | exfiltration-capable tools, Cisco AI Skill Scanner findings |
| APIs | destructive endpoints, unauthenticated endpoints |
| MCP | unapproved tools, missing auth, dangerous tool combinations |
| Code | dangerous execution patterns (eval/exec/pickle/yaml.load) |
| Supply chain | unattested model weights |
| Transport | plaintext HTTP endpoints |
| Local | developer workstation indicators |

Every check is mapped to the [MIT AI Risk Repository](https://airisk.mit.edu/) taxonomy.

> **Two checks are conditional:** SKILL-02 (Cisco AI Skill Scanner) needs the opt-in `[cisco]` extra — see [Augmentation](#augmentation); MCP-01 (unapproved tools) is not yet implemented and currently SKIPs. The rest run out of the box.

## Container (recommended)

The official image bundles `[full]` with the spaCy `en_core_web_lg` model. The image copies both `verify/` and the sibling `core/`, so the build context is the `blastcontain-oss` repo root:

```
# from the blastcontain-oss/ root
podman build -t blastcontain-verify:latest -f verify/Containerfile .
podman run --rm \
  --read-only --cap-drop ALL --security-opt no-new-privileges \
  --network none --tmpfs /tmp:rw,noexec,nosuid,size=64m \
  -v "$PWD:/scan:ro,z" -v "$PWD/reports:/reports:rw,z" \
  blastcontain-verify:latest \
  --agent-id my-agent --env prod \
  --search-path /scan --report /reports/report.md \
  --output /reports/audit.json --sarif /reports/scan.sarif \
  --acknowledge-risk
```

## CLI flags (most common)

```
--agent-id              Agent identifier (required)
--env                   dev | uat | staging | prod | local_developer_workstation
--search-path           Root walked for source/secret/code/TLS scanning
--skills-dir            Skill code directory (SKILL-01/02)
--api-spec              OpenAPI 3.0 YAML/JSON path (API-01/02)
--mcp-config            MCP server config JSON (MCP-01/02/03)
--model-dir             Model weights directory (ENV-03, SUP-01)
--context-file          Session context text for PII scanning (MEM-01)
--output PATH           Write signed JSON audit packet
--report PATH           Write Markdown report
--sarif PATH            Write SARIF 2.1.0 for GitHub Code Scanning
--skip-checks IDs       Comma-separated check IDs to suppress
--api-live-probe        Enable live OPTIONS probe in API-01 (off by default)
--egress-probe-target   host:port for ENV-02/NET-01 probes
--acknowledge-risk      Exit 0 even on CRITICAL
--require-signing       Exit 3 unless a real signing key is set (no advisory packet)
```

Usage guide & examples: [docs/usage.md](docs/usage.md) · Full spec: [docs/spec.md](docs/spec.md) · Design notes: [docs/architecture.md](docs/architecture.md) · Custom checks: [docs/plugins.md](docs/plugins.md)

## GitHub Code Scanning integration

`--agent-id` should be a **stable logical identifier for the agent being scanned** (e.g. `support-bot-prod`), not the repository slug — it is the key your audit packets are attributed to over time, so it must stay constant even if the repo is renamed or forked. Store it as a repository or org Actions **variable** (Settings → Secrets and variables → Actions → Variables):

```yaml
# .github/workflows/security.yml
- name: BlastContain Verify
  run: blastcontain-verify --sarif scan.sarif --agent-id "${{ vars.AGENT_ID }}"
- uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: scan.sarif
```

## Augmentation

Verify works standalone; optional packages unlock deeper checks. Every
augmentation — default and opt-in — is **CVE-clean** as of 2026-06.

| Extra | Adds | Clean |
|---|---|---|
| `[pii]`   | Microsoft Presidio NER for MEM-01 | ✅ |
| `[agt]`   | Agent Governance Toolkit | ✅ |
| `[full]`  | `[pii]` + `[agt]` — the default supported set | ✅ |
| `[skill]` / `[cisco]` | Cisco AI Skill Scanner (SKILL-02) | ✅ |

```
pip install "blastcontain-verify[full]"          # default: Presidio + AGT
pip install "blastcontain-verify[full,cisco]"     # + SKILL-02 (Cisco skill scanner)
```

> The Cisco **MCP** scanner (the MCP-01 backend) is not currently packaged — it
> still pins a CVE-bearing `litellm` and MCP-01 is dormant without a Charter. See
> [SECURITY.md](SECURITY.md).

Without the relevant extra, the dependent check SKIPs with a hint on how to enable it.

## Suppressing findings — `.blastcontainignore`

Drop a `.blastcontainignore` at the root of `--search-path`:

```
tests/fixtures/      # entire directory tree
*.mock.json          # filename glob
**/snapshots/**      # path glob
```

Honoured by CRED-01, CODE-01, TLS-01.

## Verifying audit packets

```python
import json
from blastcontain_core.signing import verify_packet

packet = json.load(open("audit.json"))
assert verify_packet(packet)
```

Ed25519 packets carry their public key inline — verification needs nothing else. HMAC packets require `BLASTCONTAIN_SIGNING_KEY` in the environment.

**Be clear about what the default signature means:** with no key configured,
packets are signed with a built-in key and marked `"advisory": true` — that
proves *integrity* (the packet wasn't modified), **not attestation** (anyone
can produce one). Attestation requires an Ed25519 key you manage. CI pipelines
that must never emit an advisory packet should pass `--require-signing`, which
exits 3 before scanning if no real key is configured.

## License

[Apache 2.0](LICENSE). See [NOTICE](NOTICE) and [THIRD_PARTY_NOTICES.txt](THIRD_PARTY_NOTICES.txt).

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md). All contributions require a DCO sign-off (`git commit -s`).
