Concepts
Security model
Trust boundaries
| Thing | Trust | Why |
|---|---|---|
src/dex_trove (the code) | trusted, reviewed | ours; linted, type-checked, tested, scanned |
sources.yaml | trusted, reviewed | decides what is learned and how |
| Upstream repos | untrusted | written by others; can change at any time |
trove/ | untrusted content, reviewed snapshot | verbatim upstream bytes, reviewed per PR |
Generated files (ananke.yaml, dex.json, catalogs) | derived | regenerated by dex learn; checked by dex validate |
Dex never executes upstream content
dex learnonly clones, reads and copies. It parses YAML withyaml.safe_loadand JSON withjson.loads. It never imports or runs anything from a source.dex installonly copies files.- Ananke’s Python importer reads manifests statically and never imports the package.
Learn-time guards
| Guard | Rule | Outcome |
|---|---|---|
| Symlinks | not followed (files or folders) | skipped, noted in dex.json notes |
| Junk | .git*, .DS_Store, __pycache__, *.pyc, node_modules, .venv | skipped |
| Size | ≤ 5 MB per file, ≤ 20 MB per item | excluded (size) |
| Real credentials | AWS access keys, private-key blocks with key material, GitHub/Slack/OpenAI/Anthropic/Google tokens (values containing EXAMPLE, xxxx, your-, <…> are ignored) | excluded (secret) |
| Ananke secret rules | Ananke’s broader registration scanner, mirrored | kept, recorded as secret_flags and tag ananke-secret-flag |
| Executable content | .sh .bash .zsh .ps1 .bat .cmd .py .js .mjs .cjs .ts files or hooks.json | tagged executes-code |
Why two secret scanners
Dex’s own patterns target real key formats and exclude on a hit. Ananke’s scanner is deliberately broader:
it also matches api_key = "<16+ chars>". On the first full run it refused 9 security-teaching items for
placeholders such as:
pc = Pinecone(api_key="PINECONE_API_KEY") # skills/pinecone-rag
const API_KEY = "sk_live_…"; # instructions/code-review-generic (a "don't do this" example)
API_KEY=actual_secret_… # agents/se-gitops-ci-specialist
Dropping those items would lose useful security content. Shipping them silently would make
ananke registry learn python:dex-trove fail. So Dex mirrors Ananke’s rules and records secret_flags
(rule path:line, never the value). dex ananke sync skips flagged items unless you pass --include-flagged.
The project’s Ananke policy ([secrets] mode = reject|redact|warn) then decides.
Executable items
- Items with scripts show runs code on their page and carry the
executes-codetag. Read the scripts before letting an agent run them. - Hooks run automatically when session events fire.
dex installrefuses to install a hook without--allow-exec. - Ananke manifests for code-bearing items do not declare permissions, so Ananke keeps warning
(
missing-permissions) until someone reviews them. Pure-instruction items declare empty permissions explicitly.
Rendering
The docs site renders upstream Markdown through rehype-sanitize, which strips scripts, event handlers, iframes
and inline styles. Relative links are rewritten to pinned upstream URLs, so nothing resolves to an unexpected
local path.
Supply chain of the package
| Control | Where |
|---|---|
| Locked dependencies | uv.lock; uv sync --all-extras in CI |
| Lint, format, strict typing, tests (≥ 80 % coverage) | ci.yml on Python 3.11–3.14 |
| Trove integrity | dex validate in CI, release and pre-commit |
| Trivy filesystem scan (blocking on CRITICAL/HIGH, package code + deps) | security.yml, both release workflows |
Trivy scan of trove/ content (non-blocking, Security tab) | security.yml |
| Semgrep SAST, pip-audit, gitleaks | security.yml (weekly + every PR) |
| CodeQL, OpenSSF Scorecard | codeql.yml, scorecard.yml |
| Workflow lint (actionlint, zizmor) | workflow-lint.yml; actions pinned by SHA; no credential persistence; no caches in release builds |
| Build once, attest, publish with OIDC | release-*.yml; actions/attest-build-provenance; PyPI trusted publishing |
The same distribution files that passed the gates are published. They are never rebuilt between validation and upload.
Reporting
See SECURITY.md.