You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
runtime_extensions manifest field — let kit manifests declare custom runtime types via Python import path, with a trust-gated load mechanism so listing remains safe.
This issue carries forward acceptance criterion AC7 from #32 (RunnerRegistry), which was the only AC of #32 not shipped in v0.7.13. AC7 is being broken out into its own ticket because (a) it's a substantial feature in its own right with security implications, and (b) the user has explicitly directed it to ship LAST, after a careful conversation about the listing-is-safe principle.
Tracked as 4c-T3 in the closeout master plan (2026-04-29__07-41-11__claude-plan__0-7-x-closeout-ultraplan.md).
The original Phase 4c design (2026-04-15__18-29-28__dev-workflow-process_phase4c-polyglot-dispatch-docker-and-runtime-extensions.md §"Security note: runtime_extensions deferral") flagged this concern:
The runtime_extensions manifest field (letting kits declare custom runtime types via JSON) creates an arbitrary code execution path triggered by kit listing, not tool execution.
The concern: a user adds a third-party kit via dz kit add org/repo. Next dz list invocation reads the kit manifest. If the manifest declares "runtime_extensions": {"unity": "kit.runners.unity"}, the engine does importlib.import_module("kit.runners.unity") — executing arbitrary Python from that git repo. The user never ran a tool; they just listed them.
This conflicts with Principle #14 of the architecture (2026-04-02__20-12-22__DISCUSS_Rnd4_FINAL_ASSESSMENT_aggregator-engine.md):
Listing is safe; execution is not. Discovery, listing, info, and tree commands NEVER execute third-party code. Only running a tool (dispatch) or explicitly running dz setup exposes the user to the tool's behavior.
The user's directive (captured in the ultraplan): "ship LAST and only after careful conversation about the listing-is-safe principle."
Proposed solution
Trust-gated extension loading. The runtime_extensions field is parsed at discovery time but extensions are NEVER auto-loaded. Loading happens only when:
The user has explicitly trusted the kit via dz kit trust <kit>
AND a tool from that kit is being dispatched (not listed/inspected)
dz kit trust <kit> # mark kit's runtime_extensions as trusted
dz kit untrust <kit> # remove trust
dz kit list --untrusted # show kits with declared but untrusted runtime_extensions
Engine behavior
Listing/info/tree: read runtime_extensions field, store in kit metadata, but DO NOT call importlib.import_module on any factory path.
Tool dispatch: when dispatching a tool whose runtime type is declared in runtime_extensions:
If kit is trusted: import the factory, register, dispatch (one-time per session)
If kit is NOT trusted: print Error: kit '<kit>' declares custom runtime type '<type>' but is not trusted. Run: dz kit trust <kit> and exit
Newly-added kits: when dz kit add <url> brings in a kit with runtime_extensions, prompt user (interactive only): "Kit declares custom runtimes: [unity, godot]. Trust now? (y/N)". Default to NO.
Cycle detection: runtime_extensions cannot reference factories from another kit's runtime_extensions (no chained loading).
Acceptance criteria
runtime_extensions field parsed from kit manifest at discovery time (stored in metadata, NOT loaded)
dz kit trust <kit> writes to trusted_extensions in user config
dz kit untrust <kit> removes trust
dz kit list --untrusted shows kits with declared-but-untrusted extensions
At dispatch time: trusted kit → factory imported and registered; untrusted kit → friendly error + exit
dz kit add <url> prompts for trust when kit declares runtime_extensions (interactive only)
dz list, dz info, dz tree, dz kit list <kit> NEVER execute extension factory code (verified by test that uses a malicious-import-path fixture)
Extensions cannot transitively load from another kit's runtime_extensions (cycle / chain prevention)
Human test checklist: tests/checklists/v0.7.NN__Phase4c_T3__runtime-extensions-trust-gated.md
Documentation: docs/guides/kit-trust.md covering when/why to trust; security model
Required design conversation (per user direction)
Before implementation, we need to settle:
Scope of trust: per-kit (recommended) vs per-extension-name vs global allowlist?
First-time UX: prompt on dz kit add, on first dz list after kit is added, or on first dispatch? Default = NO trust regardless of channel.
Trust persistence: what happens when a trusted kit is updated and adds new extension types? Re-prompt? Keep trust? (Recommendation: re-prompt since trust covers a specific extension surface.)
Summary
runtime_extensionsmanifest field — let kit manifests declare custom runtime types via Python import path, with a trust-gated load mechanism so listing remains safe.This issue carries forward acceptance criterion AC7 from #32 (RunnerRegistry), which was the only AC of #32 not shipped in v0.7.13. AC7 is being broken out into its own ticket because (a) it's a substantial feature in its own right with security implications, and (b) the user has explicitly directed it to ship LAST, after a careful conversation about the listing-is-safe principle.
Tracked as 4c-T3 in the closeout master plan (
2026-04-29__07-41-11__claude-plan__0-7-x-closeout-ultraplan.md).Background — why AC7 was deferred from #32
The original Phase 4c design (
2026-04-15__18-29-28__dev-workflow-process_phase4c-polyglot-dispatch-docker-and-runtime-extensions.md§"Security note: runtime_extensions deferral") flagged this concern:This conflicts with Principle #14 of the architecture (
2026-04-02__20-12-22__DISCUSS_Rnd4_FINAL_ASSESSMENT_aggregator-engine.md):The user's directive (captured in the ultraplan): "ship LAST and only after careful conversation about the listing-is-safe principle."
Proposed solution
Trust-gated extension loading. The
runtime_extensionsfield is parsed at discovery time but extensions are NEVER auto-loaded. Loading happens only when:dz kit trust <kit>Manifest schema
{ "runtime_extensions": { "unity": "mykit.runners.make_unity_runner", "godot": "mykit.runners.make_godot_runner" } }User-config schema
~/.dazzlecmd/config.json:{ "trusted_extensions": { "unity-tools": true, "godot-tools": false } }CLI surface
Engine behavior
runtime_extensionsfield, store in kit metadata, but DO NOT callimportlib.import_moduleon any factory path.runtime_extensions:Error: kit '<kit>' declares custom runtime type '<type>' but is not trusted. Run: dz kit trust <kit>and exitdz kit add <url>brings in a kit withruntime_extensions, prompt user (interactive only): "Kit declares custom runtimes: [unity, godot]. Trust now? (y/N)". Default to NO.runtime_extensionscannot reference factories from another kit'sruntime_extensions(no chained loading).Acceptance criteria
runtime_extensionsfield parsed from kit manifest at discovery time (stored in metadata, NOT loaded)dz kit trust <kit>writes totrusted_extensionsin user configdz kit untrust <kit>removes trustdz kit list --untrustedshows kits with declared-but-untrusted extensionsdz kit add <url>prompts for trust when kit declaresruntime_extensions(interactive only)dz list,dz info,dz tree,dz kit list <kit>NEVER execute extension factory code (verified by test that uses a malicious-import-path fixture)runtime_extensions(cycle / chain prevention)tests/checklists/v0.7.NN__Phase4c_T3__runtime-extensions-trust-gated.mddocs/guides/kit-trust.mdcovering when/why to trust; security modelRequired design conversation (per user direction)
Before implementation, we need to settle:
dz kit add, on firstdz listafter kit is added, or on first dispatch? Default = NO trust regardless of channel.~/.dazzlecmd/extension-load-log.jsonrecord every extension load with timestamp + source SHA, for forensic analysis?Related issues
Analysis
2026-04-15__18-29-28__dev-workflow-process_phase4c-polyglot-dispatch-docker-and-runtime-extensions.md§"Security note: runtime_extensions deferral"private/claude/_oracle/2026-04-29__issue-32-runner-registry-acceptance-inspection.md2026-04-29__07-41-11__claude-plan__0-7-x-closeout-ultraplan.md(4c-T3 in Tier 8)