Concepts

Security model

Trust boundaries

ThingTrustWhy
src/dex_trove (the code)trusted, reviewedours; linted, type-checked, tested, scanned
sources.yamltrusted, revieweddecides what is learned and how
Upstream reposuntrustedwritten by others; can change at any time
trove/untrusted content, reviewed snapshotverbatim upstream bytes, reviewed per PR
Generated files (ananke.yaml, dex.json, catalogs)derivedregenerated by dex learn; checked by dex validate

Dex never executes upstream content

  • dex learn only clones, reads and copies. It parses YAML with yaml.safe_load and JSON with json.loads. It never imports or runs anything from a source.
  • dex install only copies files.
  • Ananke’s Python importer reads manifests statically and never imports the package.

Learn-time guards

GuardRuleOutcome
Symlinksnot followed (files or folders)skipped, noted in dex.json notes
Junk.git*, .DS_Store, __pycache__, *.pyc, node_modules, .venvskipped
Size≤ 5 MB per file, ≤ 20 MB per itemexcluded (size)
Real credentialsAWS 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 rulesAnanke’s broader registration scanner, mirroredkept, 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.jsontagged 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-code tag. Read the scripts before letting an agent run them.
  • Hooks run automatically when session events fire. dex install refuses 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

ControlWhere
Locked dependenciesuv.lock; uv sync --all-extras in CI
Lint, format, strict typing, tests (≥ 80 % coverage)ci.yml on Python 3.11–3.14
Trove integritydex 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, gitleakssecurity.yml (weekly + every PR)
CodeQL, OpenSSF Scorecardcodeql.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 OIDCrelease-*.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.

Edit this page on GitHub ↗