Observed since 21 Oct, 10:51 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
AI Native Agent Skill security auditing tool - an LLM-driven multi-stage code audit and vulnerability review pipeline
English | 中文
AI Native Agent Skill security auditing tool — an LLM-driven multi-stage code audit and vulnerability review pipeline.
aig-skill-scan is a subproject of Tencent AI-Infra-Guard, purpose-built for static, LLM-driven security auditing of AI Agent Skill projects (OpenClaw Skills, etc.).
suspicious. Clear normal and malicious results keep the fast path.--aig-mode (three-stage) mode: the full Info Collection → Code Audit → Vulnerability Review pipeline, used for the AI-Infra-Guard platform's step-by-step frontend display; no need to enable it manually otherwise.Vulnerability classification follows the SkillTrustBench T01–T09 taxonomy. Verdicts: malicious (clear attack intent) / suspicious (vulnerability present but no clear attack intent) / normal (benign).
# From PyPI
pip install aig-skill-scan
# Or from source (development)
git clone https://github.com/Tencent/AI-Infra-Guard.git
cd AI-Infra-Guard/skill-scan
pip install -e .
Requires Python ≥ 3.9.
# Set API key via environment variable
export LLM_API_KEY="your-api-key"
# Scan a local Skill project directory
aig-skill-scan --repo /path/to/your/skill \
-m deepseek-v4-flash \
--language en \
-o result.sarif.json
# Or invoke as a module
python -m skill_scan --repo /path/to/your/skill
Full options:
aig-skill-scan --help
| Option | Description | Default |
|---|---|---|
--repo | Path to the Skill project directory to scan (required) | — |
-m, --model | LLM model name | deepseek-v4-flash |
-k, --api_key | API key (falls back to env vars if omitted) | — |
-u, --base_url | API base URL | https://openrouter.ai/api/v1 |
-p, --prompt | Custom scan prompt (optional) | — |
--language | Output language: zh / en | zh |
--debug | Enable debug mode | false |
--aig-mode | Enable AIG integration mode: run the three-stage pipeline and emit structured JSON to stdout for the Go backend (not needed for standalone use) | false |
-o, --output | Save the scan result to a file; SARIF 2.1.0 JSON when --aig-mode is off, internal-schema JSON when it's on | — |
--aig-modeis intended for the AI-Infra-Guard platform backend. When enabled, it runs the three-stage pipeline (Info Collection → Code Audit → Vulnerability Review) and writesnewPlanStep/statusUpdate/toolUsedstructured JSON lines to stdout;-oalso saves the internal-schema JSON in this mode. Do not enable it when usingpip installstandalone — it will pollute your terminal with JSON.
When --aig-mode is off (default, standalone CLI use), the result saved via -o is SARIF 2.1.0 — the OASIS Static Analysis Results Interchange Format standard JSON, natively consumable by GitHub Code Scanning, Azure DevOps, GitLab Security Dashboard, VS Code's Problems panel, and other SARIF-aware tooling.
{
"version": "2.1.0",
"$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/main/Schemata/sarif-schema-2.1.0.json",
"runs": [{
"tool": {"driver": {"name": "aig-skill-scan", "version": "0.2.2", "rules": [...]}},
"results": [{
"ruleId": "T04",
"level": "error",
"message": {"text": "..."},
"locations": [{"physicalLocation": {"artifactLocation": {"uri": "scripts/setup.sh"}, "region": {"startLine": 12, "endLine": 18}}}],
"partialFingerprints": {"primaryLocationLineHash": "..."},
"fixes": [{"description": {"text": "..."}}]
}]
}]
}
ruleId comes from the vulnerability's risk_type (the SkillTrustBench T01–T09 category code)level is normalized from the free-text severity (Critical/High/Medium/...) into SARIF's error/warning/notelocations relies on optional structured fields (file path + line numbers) emitted by the LLM; when they can't be determined, uri falls back to "."--aig-mode mode is unaffected and continues to save the original internal JSON structure via -o (consumed by the platform internally).
import asyncio
import json
import os
from skill_scan.agent.agent import Agent
from skill_scan.utils.llm import LLM
from skill_scan.utils.sarif_formatter import to_sarif
async def run():
# API key must be read from environment variables, never hardcoded
api_key = os.environ.get("LLM_API_KEY")
if not api_key:
raise RuntimeError("LLM_API_KEY environment variable must be set")
llm = LLM(model="deepseek-v4-flash",
api_key=api_key,
base_url="https://openrouter.ai/api/v1",
context_window=128_000)
# Default pipeline with conditional suspicious-verdict review, aig_mode=False
agent = Agent(llm=llm, debug=False, language="en", aig_mode=False)
result = await agent.scan("/path/to/your/skill", "", "en")
# Convert to SARIF 2.1.0 format
sarif_doc = to_sarif(result, tool_version="0.2.2", language="en")
print(json.dumps(sarif_doc, ensure_ascii=False, indent=2))
asyncio.run(run())
All configuration is injected via environment variables or a .env file. aig-skill-scan looks for .env in this order:
site-packages/skill_scan/.env — rarely used post-install)./.env — recommended)Key environment variables:
| Variable | Description | Default |
|---|---|---|
LLM_API_KEY / OPENAI_API_KEY | LLM API key (must be set via environment variable, never hardcode) | — |
LLM_MODEL / OPENAI_MODEL | Default model | deepseek-v4-flash |
LLM_BASE_URL / OPENAI_BASE_URL | Default base URL | https://openrouter.ai/api/v1 |
DEFAULT_MODEL_CONTEXT_WINDOW | Main model context window | 128000 |
LOG_LEVEL | Log level | INFO |
skill_scan/
├── agent/ # Agent scan pipeline (conditional verdict review by default; three stages with --aig-mode)
│ ├── agent.py # Agent class, scan entry point + stage dispatch
│ └── base_agent.py # LLM loop + tool-calling base class
├── tools/ # XML-schema tool registry
│ ├── registry.py # @register_tool decorator
│ ├── dispatcher.py # ToolDispatcher, routes tool calls
│ ├── file/ ls/ grep/ dir/ base64_decode/ thinking/ finish/
│ └── *_schema.xml # XML schemas consumed by the LLM
├── utils/
│ ├── llm.py # OpenAI-compatible client
│ ├── prompt_manager.py# Prompt template loader (from skill_scan/prompt/)
│ ├── aig_logger.py # AIG integration logger (off by default, enabled via --aig-mode)
│ ├── extract_vuln.py # <vuln> XML extraction and parsing
│ ├── sarif_formatter.py # Internal result → SARIF 2.1.0 conversion (used when --aig-mode is off)
│ ├── project_analyzer.py # Language detection + calc_skill_score
│ ├── text_decoder.py # Bounded text decoding with charset smuggling detection
│ └── pre_scan.py # Pre-scan: project summary + charset/encoding anomaly detection + bytecode (.pyc) & dependency/cache/build dir reference flagging
├── prompt/ # Packaged prompt templates
│ ├── system_prompt.md
│ ├── compact.md next_prompt.md format_report.md
│ └── agents/ # Per-stage prompts
└── main.py # CLI entry point (cli / main / parse_args)
calc_skill_score mirrors mcp-scan's calc_mcp_score:
| Severity | Deduction |
|---|---|
| Critical | -100 |
| High | -40 |
| Medium | -25 |
| Low / Info | -10 |
Final skill score = max(0, 100 - Σ deductions).
# Install dev dependencies
pip install -e ".[dev]"
# Lint / format
ruff check skill_scan
ruff format skill_scan
# Build locally
python -m build
# Install and test locally
pip install dist/aig_skill_scan-0.1.0-py3-none-any.whl
aig-skill-scan --help
Apache License 2.0. Any redistribution or derivative work must clearly state "Based on Tencent Zhuque Lab AI-Infra-Guard" in its documentation or UI and link to the original repository at https://github.com/Tencent/AI-Infra-Guard. See NOTICE for details.
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.2.2 | 16 Sept 2026 | 10 |
This describes our collected data; it is not a security assessment.
Observed since 21 Oct, 10:51 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:7aa1221eeee518026533feb203406e0a791ae65b54a28e89dad29f00d26125dd