Behavioral execution engine for MCP-based AI agent skills
Project description
skillscan-trace
Behavioral execution engine for MCP-based AI agent skills.
skillscan-trace runs a skill against a real language model inside an instrumented, isolated environment and records everything the model does: every file it reads, every network request it makes, every environment variable it accesses, every binary it probes. The output is a structured, machine-readable trace report.
It is the dynamic analysis counterpart to skillscan, which performs static analysis. Together they form two legs of the skillscan family:
skillscan family
├── skillscan — static analysis (pattern matching, ML classifier)
├── skillscan-trace — behavioral execution engine ← this repo
└── skillscan-lint — schema and format validation (planned)
What it does
A skill is a Markdown file that becomes a system prompt for an AI agent. Most skills are benign. Some are malicious — they instruct the agent to exfiltrate credentials, probe the filesystem, call attacker-controlled servers, or hijack the agent's behavior through prompt injection embedded in tool output.
Static analysis catches the obvious cases. Behavioral analysis catches the rest: conditional payloads that only activate in certain environments, obfuscated instructions that decode at runtime, and prompt injection delivered through external content the skill fetches.
skillscan-trace works by:
- Loading the skill's
SKILL.mdas the system prompt for a local language model - Sending a realistic user prompt that exercises the skill's stated functionality
- Driving the model's tool-use loop through an instrumented MCP server that intercepts every tool call
- Checking each call against a canary taxonomy (credential files, wallet paths, ENV vars, binary probing, network destinations)
- Emitting a structured trace report (JSON + SARIF) with every observed behavior and any findings
The model runs locally via Ollama — no API key required, no cloud dependency. API providers (OpenAI, OpenRouter, Anthropic) are supported for users who prefer them or want access to more capable models.
Status
v0.1.0 — core CLI complete. Phases 1–5 are implemented and 144/144 tests pass. The tool is installable and usable today.
See SPEC.md for the full behavioral specification.
See ARCHITECTURE.md for the system design.
See IMPLEMENTATION_PLAN.md for the build plan and phase status.
Quick start
# Install from source
git clone https://github.com/kurtpayne/skillscan-trace
cd skillscan-trace
pip install -e .
# Run a trace with OpenAI
export OPENAI_API_KEY=sk-...
skillscan-trace run ./path/to/skill/
# Run with OpenRouter (200+ models via one key)
export OPENROUTER_API_KEY=sk-or-...
skillscan-trace run ./skill/ --provider openrouter --model mistralai/mistral-7b-instruct
# Run with a local Ollama model (no API key required)
skillscan-trace run ./skill/ --provider ollama --model qwen2.5:7b
# Run with explicit base URL (Azure, Mistral, etc.)
skillscan-trace run ./skill/ --base-url https://api.mistral.ai/v1 --api-key $MISTRAL_KEY
# Output formats
skillscan-trace run ./skill/ --format sarif # SARIF 2.1.0 for CI
skillscan-trace run ./skill/ --format json # native trace format
skillscan-trace run ./skill/ --format text # human-readable summary
# Verify connectivity
skillscan-trace check
skillscan-trace check --provider openrouter
skillscan-trace check --provider ollama
Skill format support
skillscan-trace handles all skill formats found in the wild:
| Format | Description | Example |
|---|---|---|
Single SKILL.md |
Standard Claude Code / MCP skill | ./my-skill/SKILL.md |
Single .md file |
Flat file, no directory | ./my-skill.md |
Directory with SKILL.md |
Standard with supporting files | ./my-skill/ |
| Frontmatter + body | YAML frontmatter + Markdown body | name:, allowed-tools: |
| Plain Markdown | No frontmatter | Any .md file |
| Multi-file skill | Directory with multiple .md files |
Loaded in alphabetical order |
Output: Trace Report
Every trace produces a JSON trace report and optionally a SARIF report.
{
"schema_version": "1.0.0",
"trace_id": "trc_20260320_abc123",
"skill": {
"path": "./my-skill/SKILL.md",
"name": "git-helper",
"sha256": "a1b2c3..."
},
"model": {
"provider": "ollama",
"model": "qwen2.5:7b",
"version": "..."
},
"prompt": "Help me commit my changes",
"duration_ms": 4823,
"tool_calls": [...],
"findings": [...],
"summary": {
"total_tool_calls": 7,
"finding_count": 1,
"severity_max": "HIGH",
"clean": false
}
}
Relationship to skillscan-security
skillscan-trace is a sibling project to skillscan-security. The two projects share:
- Finding schema: The same finding IDs (
EXF-001,MAL-001,IOC-001, etc.) and severity levels - Canary taxonomy: The same list of high-value target paths and ENV var names
- Domain allowlist:
trace/domains/verified.ymlfrom skillscan-security is the source of truth; skillscan-trace consumes it - Corpus feedback loop: Traces that produce findings can be reviewed and added to the skillscan-security corpus as
sandbox_verified/examples, improving the ML classifier's recall on behavioral patterns that static analysis misses
Privacy & Key Handling
Your API key goes directly to the LLM provider you chose. The canary server runs in-process on your machine. Nothing leaves your network except the LLM API calls you explicitly authorize. SkillScan has no server-side component in local mode.
See PRIVACY.md for the full data flow explanation.
Contributing
See CONTRIBUTING.md.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file skillscan_trace-0.1.0.tar.gz.
File metadata
- Download URL: skillscan_trace-0.1.0.tar.gz
- Upload date:
- Size: 66.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
17dbad9799a6c3fc761c6f3d1d75ad105595a5143a4e9fb4da2d3323d0bf0e02
|
|
| MD5 |
823d4d519201f19ca794946671e69362
|
|
| BLAKE2b-256 |
96c4dfd26d10b63f5efb91bd35163018d706f60fd8c22a6337816ffff42bac64
|
Provenance
The following attestation bundles were made for skillscan_trace-0.1.0.tar.gz:
Publisher:
release-pypi.yml on kurtpayne/skillscan-trace
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
skillscan_trace-0.1.0.tar.gz -
Subject digest:
17dbad9799a6c3fc761c6f3d1d75ad105595a5143a4e9fb4da2d3323d0bf0e02 - Sigstore transparency entry: 1189879791
- Sigstore integration time:
-
Permalink:
kurtpayne/skillscan-trace@e726c4b64c4254da85c1d9147c2fad4f335b8240 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/kurtpayne
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-pypi.yml@e726c4b64c4254da85c1d9147c2fad4f335b8240 -
Trigger Event:
release
-
Statement type:
File details
Details for the file skillscan_trace-0.1.0-py3-none-any.whl.
File metadata
- Download URL: skillscan_trace-0.1.0-py3-none-any.whl
- Upload date:
- Size: 56.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
14232351c1dac273451f00a2aedf1e4159e1ba50c4c0934d3ac8cefe5cb7baf9
|
|
| MD5 |
c53938f096583bce4285ed1405f9a15a
|
|
| BLAKE2b-256 |
77bd11403a7287c2a14100ef12c84ed3bc968de465c742f826f6f56ff9601306
|
Provenance
The following attestation bundles were made for skillscan_trace-0.1.0-py3-none-any.whl:
Publisher:
release-pypi.yml on kurtpayne/skillscan-trace
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
skillscan_trace-0.1.0-py3-none-any.whl -
Subject digest:
14232351c1dac273451f00a2aedf1e4159e1ba50c4c0934d3ac8cefe5cb7baf9 - Sigstore transparency entry: 1189879840
- Sigstore integration time:
-
Permalink:
kurtpayne/skillscan-trace@e726c4b64c4254da85c1d9147c2fad4f335b8240 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/kurtpayne
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-pypi.yml@e726c4b64c4254da85c1d9147c2fad4f335b8240 -
Trigger Event:
release
-
Statement type: