free2pa
Enables verification of agent control file provenance (signature, integrity, certificate, and trust group) via MCP tools before loading.
README
Free2PA
Agent frameworks put developers in the driver's seat. Free2PA is the seat belt for the files that steer the agent.
Free2PA puts a signed receipt beside the files that tell an AI agent who it is and what it can do. Before the agent uses one, Free2PA checks that the file has not changed and that it came from someone this group trusts.
It is an Apache-2.0 developer tool for making an agent's critical control files tamper-evident inside an ad-hoc trust group. A class, project team, short-term collaboration, or agent operator runs its own verifier and chooses whose files that particular group will accept.
What does Free2PA do?
Free2PA is a load gate for agent control files. You put it between the files that steer an agent and the code that loads those files.
For example, suppose your application loads SOUL.md, SKILL.md, or a tool
configuration into an agent. Free2PA gives your application one decision
before it does that:
control file + signed sidecar + this group's public certificates
|
v
PASS / LOAD or FAIL / REJECT
The workflow is:
- A publisher signs a control file. Free2PA writes a neighboring
.c2pa.jsonsidecar containing its signed provenance receipt. - The group operator places that publisher's public certificate in the verifier's trust directory.
- Before an agent loads the file, the host calls Free2PA through the CLI, MCP, or HTTP API.
- Free2PA checks the signature, the exact file bytes, certificate dates, and membership in this verifier's local trust group.
- The host loads only a
PASSresult. OnFAIL, it can stop, repair from the signed original, alert and continue, or log according to its own policy.
Free2PA does not monitor a folder in the background and it does not alter the agent framework. The developer adds the verification call at the point where the application reads a critical file. The included Codex skill can locate that point and wire the check into an existing agent application.
How do I set it up?
Fastest path: let Codex implement it
Install the toolkit and its implementation skill:
git clone https://github.com/kilroyblockchain/free2pa-devtool.git
cd free2pa-devtool
npm install
npm link
free2pa codex-skill install
Then open the agent application's repository in Codex and ask:
Use $free2pa-protect-agent. First fact-gather this application's entry point,
Nerve Center files, and load boundaries. Show me the Free2PA fact sheet. Then
implement a fail-closed Free2PA gate using .free2pa/trusted-publishers, and
prove trusted, changed, and outside-group behavior.
Codex first reports what it found. After the publisher list and failure policy are established, it installs the pinned release, creates the project layout, wires the gate into the real loader or startup path, and adds the three boundary tests. It must not guess who belongs to the trust group or silently sign edits.
See Implementation runbook for the exact download-to-done workflow and completion criteria.
Manual path
This example protects an existing SOUL.md. Substitute the path to any text
file your agent loads.
1. Install Free2PA
Prerequisites: macOS or Linux, Node.js 20 or newer, and OpenSSL on PATH.
git clone https://github.com/kilroyblockchain/free2pa-devtool.git
cd free2pa-devtool
npm install
npm link
free2pa --version
Before configuring anything, run the included examples to see the contract:
# Unchanged file from a publisher in this demo's trust group: exits 0
free2pa verify public/demo/trusted/SKILL.md --trust-store demo_certs
# File changed after signing: exits nonzero and reports CONTENT_CHANGED
free2pa verify public/demo/tampered/SKILL.md --trust-store demo_certs
The first command prints PASS; the second prints FAIL. That same exit-code
decision is what an agent startup hook or file loader consumes programmatically.
2. Create a publisher identity
The private key signs files. Keep it private. The public certificate is what you give to groups that should trust your files.
free2pa keygen \
--name "My Project Publisher" \
--id my-project \
--days 30 \
--out-dir .free2pa
3. Admit that publisher to this project's trust group
free2pa trust add .free2pa/my-project.crt \
--store .free2pa/trusted-publishers \
--id my-project
Each developer or deployment controls its own trusted-publishers directory.
To trust a teammate, add their public .crt file to the same directory. Never
add their private key.
4. Sign the file
free2pa sign ./path/to/SOUL.md \
--cert .free2pa/my-project.crt \
--key .free2pa/my-project.key \
--purpose "Agent identity and behavior instructions"
This creates ./path/to/SOUL.md.c2pa.json beside the file. Commit the control
file and sidecar. Do not commit .free2pa/my-project.key.
5. Gate the agent's load operation
Run this immediately before the application reads SOUL.md:
free2pa verify ./path/to/SOUL.md \
--trust-store .free2pa/trusted-publishers \
--json
Exit code 0 means the host may load the file. A nonzero exit means it must
apply its failure policy. The JSON result explains whether the signature,
file-integrity, certificate, or group-trust check failed.
For an agent-native integration, launch the local verifier:
free2pa serve \
--trust-store .free2pa/trusted-publishers \
--skills ./path/to \
--port 4001
The application can now call the verify_asset MCP tool at
http://127.0.0.1:4001/mcp with the exact file and sidecar bytes. Consume its
structured decision: load on LOAD; apply the configured failure policy on
REJECT.
Which integration tool should I use?
| Application shape | Free2PA tool | Where it runs |
|---|---|---|
| Custom Node harness | loadVerifiedFile() from free2pa/load-gate |
In the loader, immediately before content enters model context |
| OpenClaw or another harness with a controllable start command | free2pa verify or free2pa scan |
In a fail-closed preflight wrapper before the harness starts |
| Framework with an MCP client or shared verifier | free2pa serve plus verify_asset |
At each protected file-load boundary; continue only on LOAD |
| Pull requests and releases | Free2PA GitHub Action | In CI, before changed agent controls can merge |
| Optional behavioral review | free2pa audit with an operator-installed LLM provider |
After provenance verification; never as a replacement for it |
For a custom Node loader, the gate is one import:
import { loadVerifiedFile } from 'free2pa/load-gate';
const systemInstructions = await loadVerifiedFile({
assetPath: 'agent/SOUL.md',
trustStore: '.free2pa/trusted-publishers',
});
startAgent({ systemInstructions });
loadVerifiedFile returns the content only when every check passes. Otherwise
it throws Free2PALoadError before the harness receives the untrusted text.
Karen Kilroy, co-chair of the C2PA AI/ML Task Force, conceived the original research
demo in response to a practical need: college students collaborating on
OpenClaw agentic nerve centers needed temporary, ad-hoc publisher trust groups.
Here, the Nerve Center is the agent's critical control surface: its skills,
SOUL.md, and the other instructions and configuration that shape what the
agent can do. Those files can change because of an external attack, an edit by
someone outside the group, or an agent rewriting its own control files.
Free2PA calls the signed receipt a sidecar. It is bound to the exact file,
makes any later change visible, and lets the local verifier decide whether the
Nerve Center may load that file.
This happens programmatically. An agent runner, startup hook, CI job, or MCP client consumes Free2PA's exit code or structured result at load time. The host application can block or quarantine the file, alert and continue, or only log the event. For critical instructions, fail-closed blocking is the recommended default; Free2PA reports the facts and the developer chooses the response.
For a changed file whose receipt is still valid, current, and locally trusted,
free2pa repair can restore the signed original programmatically while keeping
the rejected version as evidence. It refuses repair from an invalid, expired,
or outside-group receipt. This supports a fourth policy: stop, repair, and
report without silently trusting new content.
Trust is local and opt-in. There is no global registry and no permanent trust relationship. Adding a public certificate admits that publisher. Removing it revokes trust on the next verification.
Free2PA's signing, verification, trust, repair, and load-gate features are model-independent and run without ChatGPT or an OpenAI API. An optional GPT-5.6 audit can review what a skill asks an agent to do. The model can identify behavioral risks, but it cannot override a failed cryptographic check.
Live judge demo
https://free2pa-buildweek.azurewebsites.net
This deployment is a reference implementation and judge sandbox, not a hosted trust authority. The product is the toolkit in this repository. Developers run Free2PA in their own environment, supply their own publisher certificate set, and connect its CLI, CI action, HTTP API, or MCP tools to the agent workflow they want to protect.
The hosted verifier is read-only so visitors cannot change its trust policy or use its signing identity. Its deployment trust store contains only the scoped Build Week demo publisher and expires after judging. The home page is a live Agentic Factory that runs the same Nerve Center file through agent lanes with and without Free2PA:
- Run Changed with Block. The unprotected agent loads the file, while
the live Free2PA lane returns
SIGN PASS,FILE FAIL,GROUP PASS, andQUARANTINE. - Select Repair + report and run Changed again. The host can restore the signed original and preserve the rejected copy as evidence.
- Run Outside group. The signature and file pass, but local group trust fails and the protected lane rejects the file.
- Run Trusted. Every gate passes and the protected lane loads the file.
The original sign, verify, diff, and GPT-5.6 audit interface remains available through Research workbench in the header. Its Demo files menu provides the exact public fixtures used by the factory.
The same integrity gate can protect other text-based Nerve Center controls,
including SOUL.md; SKILL.md is the focused reference implementation used
by this release and demo.
No account, rebuild, or paid service is required for judge testing.
Hello World reference integration
The separate
Hello World reference page
shows one minimal application placing the same general load gate before a real
Azure-hosted LLM consumes SOUL.md. It is an integration example, not the
Free2PA product boundary.
Its signed soul permits only Hello, <optimistic adjective> world!. A changed
soul requests bitter adjectives. Under Block, Free2PA detects the edited bytes
and skips the protected model call. Under Repair + report, it recovers the
hash-verified signed original before starting the protected agent. A valid soul
from a publisher outside the verifier's temporary group is also rejected before
model context.
Run the packaged example with the operator's own OpenAI or Azure OpenAI account:
npm run demo:hello -- trusted
npm run demo:hello -- changed
npm run demo:hello -- changed repair
The changed file proves a change, not a particular cause. It could result from an attack, an engineering mistake, or an agent rewriting its own Nerve Center after a misunderstanding. The cryptographic Free2PA toolkit requires no LLM; the model belongs to this reference application, not the trust decision.
The three checks
Every verification answers three separate questions:
| Check | Question |
|---|---|
| Signature | Was this claim signed by the private key for the embedded certificate? |
| Integrity | Does the current file still match the signed SHA-256 asset hash? |
| Group trust | Is that publisher's certificate in this verifier's trust store and currently valid? |
All three must pass. A valid signature proves authorship, not trust. A trusted publisher cannot make a modified file pass. A behaviorally safe GPT audit cannot make an unsigned file pass.
Why ad-hoc trust
The idea came from college classes: people form a group, trust one another for a particular assignment or semester, and then let that relationship end. Free2PA expresses that social decision as a verifier configuration.
Examples include:
- a two-person collaboration that exchanges public certificates;
- a project team whose verifier trusts every team member;
- a class verifier populated from an instructor-curated certificate bundle;
- one-way trust where a consuming team accepts a producing team's skills; and
- a temporary collaboration using a short-lived certificate.
Anyone outside the configured group fails the trust check. The same signed skill may pass one group's verifier and fail another's. That is intentional: the verifier, not a universal authority, defines the trust boundary.
CLI reference
Run free2pa --help to see the complete command surface. The setup workflow
above uses keygen, trust add, sign, and verify; the remaining sections
show shared verifiers, audits, scanning, CI, MCP, and HTTP integration.
Launch an ad-hoc verifier
Create a trust store and admit a publisher by adding only their public certificate:
free2pa trust add .free2pa/karen-build-week.crt \
--store ./study-group-certs \
--id karen
free2pa trust list --store ./study-group-certs
Verify directly against the group's policy:
free2pa verify ./skills/weather/SKILL.md \
--trust-store ./study-group-certs
Restore the trusted signed version after a failed integrity check:
free2pa repair ./skills/weather/SKILL.md \
--trust-store ./study-group-certs \
--json
Or launch a browser and MCP verifier backed by that same directory:
free2pa serve \
--trust-store ./study-group-certs \
--skills ./skills \
--port 4001
Open http://127.0.0.1:4001. To revoke the publisher immediately:
free2pa trust remove karen --store ./study-group-certs
The signature remains mathematically valid, but the next group verification
fails with UNTRUSTED_ISSUER.
Optional LLM security auditors
The Free2PA core requires no LLM account. A verifier operator may bring an OpenAI, Azure OpenAI, OpenAI-compatible, local, or other account for independent behavioral review. Check the current state with:
free2pa auditor status
For direct OpenAI use, provide your own server-side account credential:
export OPENAI_API_KEY="..."
free2pa audit ./skills/weather/SKILL.md --model gpt-5.6
The server also supports Azure OpenAI v1 through AZURE_OPENAI_ENDPOINT and
AZURE_OPENAI_DEPLOYMENT. Local operators may provide
AZURE_OPENAI_API_KEY; Azure App Service can instead use a system-assigned
managed identity with the Cognitive Services OpenAI User role. The hosted
judge demo uses managed identity and stores no model credential.
Other LLM integrations are installable auditor modules. Install the adapter in
the Free2PA project, set FREE2PA_AUDITOR_MODULE and any account variables its
provider requires, then run the same free2pa audit command. See
optional auditor providers for the module contract
and security boundary.
The audit returns strict structured findings covering:
- prompt injection;
- secret or credential access;
- data exfiltration;
- destructive actions;
- excessive permissions;
- unsafe downloads and supply-chain behavior; and
- obfuscated instructions.
The built-in OpenAI provider presents skill content as delimited, untrusted
data. Every provider report records the model, audit time, filename, and SHA-256
of the reviewed content. Files larger than 64 KiB are rejected. critical and
high reports produce a nonzero CLI exit code.
Repository scanning and CI
scan recursively finds SKILL.md files. Missing sidecars, modified files,
invalid signatures, expired certificates, and publishers outside the supplied
trust store fail the command:
free2pa scan ./skills --trust-store ./study-group-certs
free2pa scan ./skills --trust-store ./study-group-certs --json
Human-readable output is designed for terminals. --json and process exit
codes are designed for CI, policy engines, and agent runtimes.
GitHub Action
Free2PA can reject a pull request when any discovered SKILL.md is unsigned,
modified, expired, or published outside the repository's chosen trust group.
Store only public certificates in the trust directory:
name: Verify agent skills
on: [pull_request]
permissions:
contents: read
jobs:
free2pa:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: kilroyblockchain/free2pa-devtool@v0.4.1
with:
path: skills
trust-store: .free2pa/trusted-publishers
The action writes free2pa-report.json, prints the structured report in the
job log, and fails closed when no skills are found or any verification gate
fails. The repository's own workflow runs the action against the judge fixture.
MCP tools
POST /mcp uses Streamable HTTP and exposes:
| Tool | Purpose |
|---|---|
verify_asset |
Verify any Nerve Center file plus sidecar and return structured PASS/FAIL and LOAD/REJECT. |
list_skills |
List skills visible to this verifier and whether each has a sidecar. |
verify_skill |
Verify one of the server's bundled demo skills by folder name. |
audit_skill |
Ask the configured optional LLM provider for an independent behavioral security review. |
The host calls verify_asset with the exact file bytes and neighboring
sidecar before placing the file into agent or model context. It consumes the
structured decision directly: LOAD means every deterministic gate passed;
REJECT includes separate signature, file-integrity, certificate-currentness,
and publisher-trust facts plus a stable reason code. A high-risk Nerve Center
can treat anything other than LOAD as unavailable; other applications may
repair, alert and continue, or log according to their explicit response
policy. verify_skill and list_skills remain convenient for the bundled
research fixtures.
HTTP API
| Endpoint | Purpose |
|---|---|
POST /api/sign |
Sign a skill and return its sidecar. |
POST /api/verify |
Verify a skill and sidecar against this server's trust store. |
POST /api/audit |
Run the configured optional LLM behavioral audit. |
GET /api/certs |
List the verifier's current trusted certificates. |
POST /api/certs/import |
Validate and admit one or more public certificates. |
POST /api/certs/generate |
Generate a signing identity for local development. |
GET /api/skills |
List skills available to the MCP verifier. |
GET /health |
Return application health and version. |
Private keys are never accepted by the trust-import endpoint. Only public X.509 certificates belong in a verifier's trust store.
C2PA relationship
C2PA has a formal conformance program. Conforming Content Credentials are verified by conforming verifiers, providing an interoperable provenance layer.
Free2PA 0.4.1 is C2PA-inspired, not a conforming C2PA implementation. It
uses sidecar files to carry C2PA-style provenance credentials in a Free2PA
format, not a C2PA Manifest Store, and does not claim interoperability with
conforming C2PA products. Like C2PA, its provenance claim is specifically about
origin and edits: a signed publisher identity traces origin, while asset binding
reveals whether the signed bytes changed. Free2PA then addresses an adjacent
local-policy question for an agentic nerve center: which publishers does this
temporary group choose to trust? It is not a replacement for C2PA conformance.
OpenAI Build Week
Free2PA existed before OpenAI Build Week as a research demo created for a
presentation to the University of Arkansas AI Club. The pre-hackathon baseline
is commit 1c2d88d from March 15, 2026.
Only work created after the submission period began is presented as Build Week work:
| Before Build Week | Added during Build Week |
|---|---|
| Express signing and verification demo | Installable free2pa CLI |
| Browser sign/verify panels | keygen, trust, sign, verify, scan, audit, and serve commands |
Local certs/ trust directory |
Complete ad-hoc verifier operator workflow |
| Two MCP tools | GPT-5.6 audit through CLI, HTTP, browser, and MCP |
| Manual happy-path testing | Automated crypto, tamper, trust, CLI, and API-contract tests |
| Prototype package metadata | Apache-2.0 release packaging and zero-advisory dependency tree |
| Boolean trust output | Certificate validity enforcement and structured trust reason codes |
The dated development record is in
docs/BUILD_WEEK.md. The submission checklist is in
docs/SUBMISSION_CHECKLIST.md.
For a two-minute, no-install evaluation path, see
docs/JUDGE_GUIDE.md.
How we collaborated with Codex
Karen Kilroy supplied the central product insight, trust semantics, intended audience, and scope: the verifier's local certificate set represents a small group's deliberate and revocable trust decisions. She also chose the Developer Tools direction and required that the existing research remain clearly distinguished from new work.
Codex accelerated the Build Week implementation by:
- auditing three related Free2PA repositories and their commit history;
- translating the existing trust model into a distributable CLI workflow;
- implementing certificate lifecycle, signing, verification, scanning, and server commands;
- adding GPT-5.6 structured security auditing across four interfaces;
- tightening algorithm, key-pair, certificate-expiration, and trust checks;
- writing end-to-end tests for tampering, outside-group failure, admission, and revocation;
- finding and updating vulnerable dependencies; and
- restructuring the product documentation around reproducible judge testing.
Codex was especially useful for rapid implementation and adversarial review. Karen made the consequential product and trust-policy decisions, corrected an early proposal that would have added an unnecessary signed group-policy format, and kept the implementation aligned with Free2PA's simpler principle: the verifier is where trust lives.
GPT-5.6 contributes directly to the shipped product as the behavioral skill auditor. Its findings supplement cryptographic verification; they never replace it.
Test and release checks
npm test
npm run check
npm audit
npm pack --dry-run
The tests use temporary identities and trust stores. No committed private key is required.
Security boundaries
- A public certificate is safe to share; its private key is not.
- Private keys previously committed to any public repository must be treated as compromised and rotated.
- Self-signed certificates identify keys, not real-world people. Exchange and identity validation remain social or institutional decisions.
- Local trust is intentionally non-transitive. Trusting Team A does not cause Team A's trusted publishers to become trusted.
- Removing a certificate affects future verification. It cannot undo an action already taken by a running agent.
- TLS, authentication, rate limits, and deployment access controls remain the responsibility of a public verifier operator.
- An LLM audit is probabilistic security analysis, not proof of safety.
License
Apache License 2.0. Free to use, inspect, modify, and redistribute under the
terms in LICENSE.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.