Skip to main content

toolseal

Secure-by-default scaffolding and a cross-framework tool registry for agentic systems.

CI PyPI Python License

Setting up an agent means reconciling a provider SDK, a framework's tool-binding idiom, and MCP server configuration. That reconciliation is usually done by copying a quickstart — and it is where the system's permanent security posture gets written, in the first ten minutes, by someone optimising for "does it run".

toolseal makes the secure arrangement the default one, and makes the insecure arrangement visible when it already exists.

$ toolseal audit .

+--------------------------------------------------+
| score 32/100   BLOCKING: 1 critical check failed |
| 1 critical, 6 high, 2 medium, 1 low              |
+--------------------------------------------------+

  CRITICAL   A1  Credential literal in project file
             .env:1 - OpenAI-style key found in .env
             fix  Move the value into the OS keychain and revoke the exposed
                  credential; it must be treated as compromised.

  HIGH       C1  Unpinned dependency
             langchain is declared as >=0.1.0
             fix  Pin langchain to an exact version.

  HIGH       E2  Agent inherits the full host environment
             Cloud CLI profiles, SSH agent sockets and every exported secret
             are visible to the agent and to any tool it calls
             fix  Launch with an explicit, minimal environment.

Install

pip install toolseal          # or: uv tool install toolseal
toolseal doctor               # verify the install

Requires Python 3.11+. Three runtime dependencies (typer, rich, keyring) — a tool that counts other people's dependencies should be able to justify each of its own.

Quickstart

Create a hardened project:

toolseal init myagent --framework crewai --provider anthropic
cd myagent
toolseal audit .              # 100/100 — the scaffold passes its own checks

Or point it at a project you already have — toolseal did not need to create it:

toolseal audit /path/to/existing-project
toolseal audit . --json       # machine-readable
toolseal audit . --sarif      # SARIF 2.1.0, for GitHub code scanning

Start under a regulatory regime instead of the baseline policy:

toolseal init myagent --profile hipaa      # or gdpr, dora
toolseal policy apply gdpr                 # or adopt one later

What it does

Scaffold — secure defaults, not a blank page

toolseal init wires a provider and framework together with least-privilege configuration, credentials resolved from the OS keychain instead of a file on disk, a redacting log filter, a pinned dependency set, and a generated SBOM.

toolseal add framework and add mcp extend a project that already exists. Everything written is recorded, and toolseal revert removes exactly what was added — including restoring files that existed beforehand, and refusing to clobber edits you made since.

add mcp resolves a server's package name against npm and PyPI before writing it anywhere, and refuses a name that resolves nowhere:

$ toolseal add mcp @invented/definitely-not-real
error: '@invented/definitely-not-real' resolves in no registry checked. A name
that does not exist today is one an attacker can register tomorrow. Re-run with
--skip-verify if you are certain. (exit 2: usage)

Audit — 28 checks, mapped to published standards

toolseal audit scores any project against a misconfiguration taxonomy of 28 checks in seven families:

Family Concern
A Credential exposure
B Capability overprovisioning
C Supply-chain integrity
D Transport and endpoint
E Execution containment
F Accountability
G Translation integrity

Every check documents itself, including which external obligations it serves:

$ toolseal policy explain B3

+- B3 - Filesystem capability with unbounded or home-directory root -+
|                                                                    |
| How to fix it                                                      |
|   Confine filesystem access to the workspace.                      |
|                                                                    |
| Obligations this serves                                            |
|   owasp-llm-top10:LLM06      Excessive Agency                      |
|   owasp-agentic-threats:T3   Privilege Compromise                  |
|   owasp-agentic-top10:ASI03  Identity & Privilege Abuse            |
+--------------------------------------------------- severity: high -+

A check that could not be evaluated is reported as not evaluated — data unavailable, not a pass. The distinction is deliberate and load-bearing: a missing answer is never quietly scored as a good one.

Registry — normalised, provenance-checked tool descriptors

toolseal registry indexes open-source tools and MCP servers into a Unified Tool Descriptor carrying capability schema, security annotations, and provenance. Every entry ships with its own assessment — the security review is the entry, not an afterthought bolted on:

$ toolseal registry search context7

+--------------------------------------------------------------------------+
|  | score | name                 | package@version     | registry | tools |
| -+-------+----------------------+---------------------+----------+------ |
|  |    90 | io.github.upstash... | @upstash/context... | npm      |     - |
+--------------------------------------------------------------------------+

-  tools not enumerated (would require running the server)

A curated set ships inside the package, so search and show work immediately after install — before registry sync has ever run. Curation criteria are fixed and published, applied by a script rather than a person, and deliberately blind to the audit score: a registry that selects entries because they scored well and then reports that its entries score well has measured nothing.

Nothing in the index is ever executed. Enumerating a server's tools means running it, so entries record tools_enumerated: false rather than implying an empty tool set. A gap you can see beats a number you cannot trust.

Translate — compensating guards for what a framework cannot express

This is the part that does not exist elsewhere. A tool declares security properties at its source; each target framework can represent some subset of them. The difference is translation loss, and toolseal computes it instead of letting you discover it in production.

Measurement (probe P0) found the loss is adapter-dependent, not inherent: langchain-mcp-adapters preserves MCP annotation hints, crewai-tools drops all of them and rewrites every description. Because the loss is a choice rather than a law, it can be repaired.

$ toolseal add tool mcp/example/db@1.0.0 --framework crewai

Lowered delete_records into crewai (compensated)
  + tools/delete_records.py
  + compensation.json

guards emitted:
  - require_approval: G1: the source declared destructiveHint, which this
    framework cannot carry. The consequence is restored as an approval step.
  - preserve_description: G5: this framework rewrites tool descriptions, so the
    author's text is preserved verbatim as SOURCE_DESCRIPTION.

The guards are behaviour, not annotation. Restoring destructiveHint into a framework with no field for it means wrapping the call in an approval step — re-establishing the consequence of the hint, since the hint itself has nowhere to live:

# G1: the source declared destructiveHint, which this framework cannot carry.
# The consequence is restored as an approval step.
@require_approval("declared destructive by its author")
@tool
def delete_records(**kwargs: object) -> object:
    """Permanently delete rows matching a filter. This cannot be undone."""
    return DISPATCH("delete_records", kwargs)

Whatever happened is written to a compensation manifest, which toolseal audit reads back through family G — so a property that was dropped with no guard in its place becomes a finding rather than a silence.

Policy, regimes, and sealing

$ toolseal policy list

standard              | coverage | checkable
----------------------+----------+----------
iso-42001             |     33%* |       1/3
nist-ai-rmf           |     80%* |       4/5
owasp-agentic-threats |     100% |       6/6
owasp-agentic-top10   |     100% |       5/5
owasp-llm-top10       |     100% |       5/5

* curated subset of the standard, not a full enumeration -
  the percentage measures our selection, not the standard's reach.

Regulatory regimes — GDPR, HIPAA, DORA — pin severities on top of the baseline. They are never scored, and a report run under one never ends in a verdict, only in not_assessed. A configuration auditor cannot certify compliance, and this one does not pretend to: it produces evidence toward an assessment, never the assessment itself.

Two more commands close the loop:

  • toolseal policy relax <check> — a justified, expiring deviation, written into toolseal.toml with its reason and expiry date.
  • toolseal policy enforce / verify — seal a resolved policy, then later prove nothing has drifted from what was sealed.

Command reference

Command Purpose
init Create a new agent project with secure defaults
audit Score a project against the misconfiguration taxonomy
add framework Write a framework's configuration into an existing project
add mcp Add an MCP server, refusing a name that resolves nowhere
add tool Lower a registry entry into the project, compensating what is lost
revert Undo what toolseal wrote into this project
policy list / explain / show Inspect checks, standards, and regimes
policy apply / relax / enforce / verify Adopt, deviate from, and seal a policy
registry sync / search / show Crawl, query, and inspect the tool index
doctor Report environment information for diagnosing a problem

Supported targets

Axis Supported
Providers Anthropic, OpenAI, Gemini, Ollama
Frameworks LangGraph, CrewAI, Claude Code
Regulatory regimes GDPR, HIPAA, DORA
Standards mapped OWASP LLM Top 10, OWASP Agentic Threats (T1–T15), OWASP Agentic Top 10 (ASI01–ASI10), NIST AI RMF, ISO/IEC 42001
Output formats Human-readable, --json, SARIF 2.1.0

Out of scope, deliberately: runtime proxying, sandboxing, malicious-code detection, and trust scoring. Each is covered by existing work, and toolseal is a configuration tool — it reasons about what a project declares, not about what its code does at runtime.

Using it in CI

Exit codes are a stable contract: 0 clean, 1 findings, 2 usage error, 3 internal error.

- run: pip install toolseal
- run: toolseal audit . --min-severity high

Or upload SARIF to GitHub code scanning:

- run: toolseal audit . --sarif > toolseal.sarif
  continue-on-error: true
- uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: toolseal.sarif

Contributing

Contributions are welcome. See CONTRIBUTING.md for the full guide.

git clone https://github.com/5Tarun3/ToolSeal
cd ToolSeal
uv sync
uv run pre-commit install

CI runs exactly four commands — run them locally first:

uv run ruff check .
uv run ruff format --check .
uv run mypy
uv run pytest

Two project-specific rules worth knowing before your first PR:

  • toolseal audit . must report 100/100 on this repository. A security tool that fails its own checks is not making an argument.
  • --json and SARIF output are inviolable machine contracts, as are the exit codes above. A research harness parses this output.

Documentation

Security

To report a vulnerability in toolseal, see SECURITY.md.

For how this project handles vulnerabilities it finds in other people's quickstarts, templates, and MCP servers during its own research, see DISCLOSURE.md.

License

Apache-2.0.

Download files

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

Source Distribution

toolseal-0.1.1.tar.gz (253.1 kB view details)

Uploaded Source

Built Distribution

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

toolseal-0.1.1-py3-none-any.whl (301.9 kB view details)

Uploaded Python 3

File details

Details for the file toolseal-0.1.1.tar.gz.

File metadata

  • Download URL: toolseal-0.1.1.tar.gz
  • Upload date:
  • Size: 253.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for toolseal-0.1.1.tar.gz
Algorithm Hash digest
SHA256 3b5cbf717930e33b6da9479e166ec0f1d5e43a8d9c1f5d0d068ef02587df8dc8
MD5 e1eafbce4ac45718ab1113357a4e6148
BLAKE2b-256 ae947d31e01031fba08046fee8db0af89c9f2edba6aba060ad02723cfe6e7f17

See more details on using hashes here.

Provenance

The following attestation bundles were made for toolseal-0.1.1.tar.gz:

Publisher: release.yml on 5Tarun3/ToolSeal

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

File details

Details for the file toolseal-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: toolseal-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 301.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for toolseal-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e453866a01ee9eb9ad5f8d4d82416798b91e315c0b750a95daf39607b029d63c
MD5 9b299cd3e51c59b510a5cbc25c8393b3
BLAKE2b-256 25b3b5f4948a99e9281d23863c140b2cbf5a833da5c9e341d57e599e528797f8

See more details on using hashes here.

Provenance

The following attestation bundles were made for toolseal-0.1.1-py3-none-any.whl:

Publisher: release.yml on 5Tarun3/ToolSeal

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

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page