{"id":"e9bdc4b2-5f36-435a-84a1-f607240c9bb1","slug":"t2i-skillguard","kind":"skill","name":"t2i-skillguard","summary":"Security scanner for AI skill files (SKILL.md) and bundled code (scripts/, tools/). It helps you catch high-risk patterns before publishing or running a skill.","owner":"Tech2Insights","repoUrl":"https://github.com/Tech2Insights/t2i-skillguard","license":"MIT","licenseTier":"permissive","trust":"community","stars":5,"match":null,"fewStars":false,"format":"skill","createdAt":"2026-03-31T08:46:17.000Z","addedAt":"2026-10-14T06:32:10.562Z","logoUrl":"https://avatars.githubusercontent.com/u/246903876?v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["developer-tools","files-documents"],"tags":["ai-security","ai-security-tool","cli-tool","command-injection","devsecops","llm","prompt-injection","python"],"runtime":"python","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-20T23:39:06.183Z","sample":false,"url":"https://conduits.dev/tools/t2i-skillguard","language":"Python","transports":["stdio"],"install":{"pypi":"t2i-skillguard"},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# t2i-skillguard\n\nSecurity scanner for AI skill files (`SKILL.md`) and bundled code (`scripts/`, `tools/`).\n\nIt helps you catch high-risk patterns before publishing or running a skill.\n\n![Python](https://img.shields.io/badge/python-3.10%2B-blue)\n![Output](https://img.shields.io/badge/output-terminal%20%7C%20json-brightgreen)\n![License](https://img.shields.io/badge/license-MIT-black)\n\n## TL;DR\n\n```bash\n# 1) Install\npip install t2i-skillguard\n\n# 2) Scan default locations\nt2i-skillguard scan -v\n\n# 3) JSON report with CVSS + payment aggregation\nt2i-skillguard scan --format json --aggregate-payment --output report.json\n```\n\nExample execution output:\n\n![t2i-skillguard scan example](docs/assets/example.png)\n\n## Why this project\n\n- Focused on real AI-skill risks (prompt injection, third-party content abuse, unsafe code execution).\n- Scans both skill metadata and executable code paths.\n- Clear terminal output + machine-readable JSON for CI.\n- Opinionated severity model to support go/no-go decisions.\n\n## Features\n\n- 13 built-in security rules for AI skill ecosystems.\n- Scans both `SKILL.md` and bundled code in `scripts/` + `tools/`.\n- CVSS metadata per vulnerability in JSON output.\n- Optional aggregation of repetitive payment findings (`--aggregate-payment`).\n- Severity/category filters for focused triage.\n- CI-friendly exit codes (`0` clean, `1` findings).\n\n## What it detects\n\nt2i-skillguard currently ships with **13 security rules** across CRITICAL/HIGH/MEDIUM/LOW.\n\n| Severity | Rule | Category | Typical risk |\n|---|---|---|---|\n| CRITICAL | `prompt_injection` | Injection | Override safety instructions / exfiltrate context |\n| CRITICAL | `command_injection` | Injection | Arbitrary command execution |\n| HIGH | `secret_exposure` | Exposure | Hardcoded keys, tokens, passwords, private keys |\n| HIGH | `malicious_patterns` | Dangerous Patterns | `eval`/`exec`/unsafe deserialization paths |\n| HIGH | `supply_chain` | Supply Chain | Downloading/executing untrusted code |\n| HIGH / MEDIUM | `third_party_exposure` | Dangerous Patterns | External content driving AI behavior |\n| MEDIUM | `insecure_flags` | Configuration | TLS/cert bypass, unsafe runtime flags |\n| MEDIUM | `path_traversal` | Configuration | Access outside allowed file roots |\n| MEDIUM | `credential_exposure` | Exposure | Secrets leaked in logs, errors, output |\n| MEDIUM | `external_content` | Exposure | Unsafe processing of untrusted web/user content |\n| LOW | `payment_capability` | Supply Chain | Financial capability signal for extra review |\n| MEDIUM | `system_alteration` | Configuration | Service/firewall/startup/system modifications |\n| LOW | `frontmatter` | Metadata | Missing/invalid skill metadata |\n\nFull rule docs: [`docs/rules/README.md`](docs/rules/README.md)\n\n## Installation\n\n### Option A: install from PyPI (recommended for usage)\n\n```bash\npip install t2i-skillguard\n```\n\n### Option B: local development (recommended for contributors)\n\n```bash\npoetry install\n```\n\n## Quick start\n\nScan default skill locations:\n\n```bash\nt2i-skillguard scan\n```\n\nScan one skill:\n\n```bash\nt2i-skillguard scan-skill /path/to/skill\n```\n\nScan custom paths:\n\n```bash\nt2i-skillguard scan /path/to/skills-a /path/to/skills-b\n```\n\n## CLI usage\n\n### Output modes\n\n```bash\n# Terminal (default)\nt2i-skillguard scan --format terminal\n\n# JSON\nt2i-skillguard scan --format json\n\n# Terminal + JSON\nt2i-skillguard scan --format both\n\n# Compact JSON (single line)\nt2i-skillguard scan --format compact\n```\n\n### Common filters\n\n```bash\n# Only HIGH and CRITICAL findings\nt2i-skillguard scan --min-severity HIGH\n\n# Only one rule category\nt2i-skillguard scan --category prompt_injection\n\n# Ignore a whole category\nt2i-skillguard scan --ignore-rule prompt_injection\n\n# Ignore a specific pattern in a category\nt2i-skillguard scan --ignore-rule prompt_injection.role_confusion\n\n# Repeat or use comma-separated values\nt2i-skillguard scan --ignore-rule insecure_flags.http_url --ignore-rule path_traversal\nt2i-skillguard scan --ignore-rule insecure_flags.http_url,path_traversal\n\n# Load scoped ignores from YAML file\nt2i-skillguard scan --ignore-file .t2i-skillguard-ignore.yml\n\n# Disable warnings for unmatched ignore entries\nt2i-skillguard scan --no-warn-unused-ignores\n\n# Skip scripts/tools analysis\nt2i-skillguard scan --no-scripts\n```\n\n### Ignore rules\n\nUse `--ignore-rule` when you need to suppress known/accepted findings for a specific run.\n\n- Accepted format: `category` or `category.pattern`\n- Repeatable: `--ignore-rule a --ignore-rule b.c`\n- Comma-separated supported: `--ignore-rule a,b.c`\n- Works with both `scan` and `scan-skill`\n- You can combine with `--ignore-file` for file/line-scoped suppression\n\nExamples:\n\n```bash\n# Ignore all prompt injection findings\nt2i-skillguard scan --ignore-rule prompt_injection\n\n# Keep only prompt_injection category, then ignore one noisy pattern\nt2i-skillguard scan --category prompt_injection --ignore-rule prompt_injection.role_confusion\n\n# Single-skill scan with ignores\nt2i-skillguard scan-skill /path/to/skill --ignore-rule insecure_flags.http_url\n```\n\n### Ignore file (YAML)\n\nThe scanner will auto-load `./.t2i-skillguard-ignore.yml` if it exists. You can also set a custom path with `--ignore-file`.\n\nSupported schema (`version: 1`):\n\n```yaml\nversion: 1\nignores:\n  - category: prompt_injection\n  - category: insecure_flags\n    pattern: http_url\n  - category: credential_exposure\n    file: skills/skill-creator/scripts/aggregate_benchmark.py\n  - category: prompt_injection\n    pattern: concealment_instruction\n    file: skills/skill-creator/SKILL.md\n    line: 327\n    reason: \"Known accepted case\"\n```\n\nFields:\n\n- `category` (required)\n- `pattern` (optional)\n- `file` (optional)\n- `line` or `lines` (optional, requires `file`)\n- `reason` (optional)\n\nNote: ignore rules (CLI and YAML) affect the final report and exit code for that run. They do not modify detector logic.\n\n### Unused ignore warnings\n\nBy default, the CLI warns when an ignore entry does not match any finding in the current run.\n\n- Default: `--warn-unused-ignores`\n- Disable warnings: `--no-warn-unused-ignores`\n\nExample warning output:\n\n```text\nIgnored findings: 3\n\nWarning: 2 ignore entries did not match any finding.\n  - prompt_injection.role_confusion @ /repo/skills/skill-a/SKILL.md:120\n  - external_content\n```\n\n### Reporting\n\n```bash\n# Verbose terminal output\nt2i-skillguard scan -v\n\n# Save JSON report\nt2i-skillguard scan --output report.json\n\n# Aggregate repetitive payment capability findings in terminal and JSON output\nt2i-skillguard scan --format both --aggregate-payment\n\n# Aggregate for a single skill scan\nt2i-skillguard scan-skill /path/to/skill --format json --aggregate-payment\n\n# Show default locations that will be scanned\nt2i-skillguard list-paths\n```\n\n## Exit codes (CI-friendly)\n\n- `0` -> no vulnerabilities found\n- `1` -> one or more vulnerabilities found\n\nThis makes it easy to fail CI pipelines when findings are detected.\n\n## CI integration (GitHub Actions)\n\n```yaml\nname: Skill Security Scan\n\non:\n  pull_request:\n  push:\n    branches: [main]\n\njobs:\n  scan-skills:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-python@v5\n        with:\n          python-version: \"3.11\"\n\n      - name: Install Poetry\n        run: pipx install poetry\n\n      - name: Install dependencies\n        run: poetry install\n\n      - name: Run scanner\n        run: poetry run t2i-skillguard scan --format json --aggregate-payment --output skillguard-report.json\n```\n\n## Release and PyPI publish\n\nWhen a GitHub Release is published, `.github/workflows/publish-pypi.yml` runs and publishes the package to PyPI.\n\nImportant:\n\n- Release tag must match `tool.poetry.version` in `pyproject.toml`.\n- Both `1.0.0` and `v1.0.0` tag formats are accepted.\n- Publish job runs lint (`poetry run ruff check .`) and tests (`poetry run pytest`) before build/upload.\n- Trusted Publisher must be configured in PyPI for this repository/workflow.\n\n## Scoring model\n\nEach skill gets a score on a `0-10` scale:\n\n```text\nraw_score = min(10, max_severity + vulnerability_count * 0.5)\nscore = min(raw_score, severity_cap[max_severity])\n\nseverity_cap = {\n  CRITICAL: 10,\n  HIGH: 9,\n  MEDIUM: 7,\n  LOW: 4,\n  INFO: 0,\n}\n```\n\nThis cap keeps score bands coherent with max-severity verdicts (for example, many LOW findings cannot become CRITICAL by count alone).\n\nVerdict bands:\n\n- `0` -> OK\n- `1-4` -> LOW\n- `5-7` -> MEDIUM\n- `8-9` -> HIGH\n- `10` -> CRITICAL\n\n## Default scan locations\n\nIf no path is provided, scanner checks existing directories in this order.\n\nProject scope:\n\n- `./.opencode/skills/`\n- `./.claude/skills/`\n- `./.agents/skills/`\n\nGlobal scope:\n\n- `~/.config/opencode/skills/`\n- `~/.claude/skills/`\n- `~/.agents/skills/`\n\nCompatibility (when present):\n\n- `${XDG_CONFIG_HOME}/opencode/skills/`\n- `${XDG_CONFIG_HOME}/claude/skills/`\n- `${XDG_CONFIG_HOME}/agents/skills/`\n- `${APPDATA}/opencode/skills/` (Windows)\n- `${APPDATA}/claude/skills/` (Windows)\n- `${APPDATA}/agents/skills/` (Windows)\n- `~/.config/claude/skills/` (legacy)\n- `~/.config/anthropic/skills/` (legacy)\n\nTip: run `t2i-skillguard list-paths` to see exactly which paths were found on your machine.\n\n## Supported environments\n\n- **OS**: Linux, macOS, Windows (including `APPDATA` path discovery support).\n- **Python**: 3.10+ recommended.\n- **Execution modes**:\n  - local development via Poetry,\n  - CI pipelines (GitHub Actions example included above).\n- **Input layout**:\n  - project-local skill folders (`.opencode`, `.claude`, `.agents`),\n  - global skill folders (`~/.config/opencode`, `~/.claude`, `~/.agents`),\n  - compatibility paths (`XDG_CONFIG_HOME`, legacy config paths).\n\n## CVSS in JSON output\n\nEach vulnerability in JSON output includes CVSS metadata:\n\n- `cvss_vector`\n- `cvss_score`\n- `cvss_severity`\n\nCVSS is resolved per `category.pattern` (with category fallback coverage).\n\nWhen using `--aggregate-payment`, output also includes grouped-vs-raw counters:\n\n- report level: `raw_total_vulnerabilities`\n- skill level: `raw_vulnerability_count`, `raw_payment_vulnerability_count`\n\nAggregation is presentation-only; detection logic, score, and verdict are unchanged.\n\nExample:\n\n```json\n{\n  \"id\": \"CMDI-001\",\n  \"severity\": \"CRITICAL\",\n  \"category\": \"command_injection\",\n  \"pattern\": \"subprocess_shell_true\",\n  \"cvss_vector\": \"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H\",\n  \"cvss_score\": 10.0,\n  \"cvss_severity\": \"CRITICAL\"\n}\n```\n\n## Development\n\n```bash\n# Install dependencies\npoetry install\n\n# Run lint\npoetry run ruff check .\n\n# Run tests\npoetry run pytest\n\n# Run scanner locally\npoetry run t2i-skillguard scan -v\n```\n\n## Contributing\n\nContributions are welcome.\n\n- Open an issue for bugs, false positives, or rule improvements.\n- Submit focused PRs with tests for behavior changes.\n- Keep rule docs in `docs/rules/` aligned with detector changes.\n- Pull requests run CI checks (`.github/workflows/tests.yml`) that execute lint + tests and fail the PR check if either command fails.\n- Run the same checks locally before opening PR:\n\n```bash\npoetry run ruff check .\npoetry run pytest\n```\n\nRecommended contribution scope:\n\n- one detector fix/improvement per PR,\n- documentation updates in the same PR,\n- include before/after examples when tuning detection patterns.\n\n## Security policy\n\nSee [`SECURITY.md`](SECURITY.md) for supported versions, private reporting instructions, and disclosure policy.\n\n## Documentation\n\n- Rules index: [`docs/rules/README.md`](docs/rules/README.md)\n- Rule deep-dives: [`docs/rules/`](docs/rules)\n\n## License\n\nMIT\n"}