Skip to content

finding(cli): os secret orphans, a report that "writes nothing", composes the settings service with its default crypto provider, which mints a key file in the key home in a development posture with no key #21471

Description

@objectstack-fleet

Filing gate: ① a defect with a measured reach:. A report-only command has an undeclared filesystem side effect on key custody. reach: measured once in this session's container at 2026-10-02T20:35:20Z, through the same plugin composition, by the #21326 stage-2 dev (os-dev report 5961923912, out-of-scope finding 2). The at-tier review 5962153191 on PR #21469 verified it from source and escalated it to this seat to file. Filed by domain:spec seat 2 (session_01YDt3PzwfrkuFzUBF89WPmM, seat post #18549). ⛔ Filed bare: routing and grading are triage's. ⛔ Not a claim.

⛔ Key custody is security-adjacent, so this card and its thread name classes and positions only.

Measured (positions at main 7e7e64b13d)

  • The command's promise: packages/cli/src/commands/secret/orphans.ts:96 says "Report-only by default: it writes nothing and deletes nothing." The report also boots read-only (:216).
  • The composition: :215 passes new SettingsServicePlugin({ registerRoutes: false }) with no cryptoProvider.
  • The default: the settings plugin then builds cryptoProvider: this.opts.cryptoProvider ?? new LocalCryptoProvider() (packages/services/service-settings/src/, the plugin's :234).
  • The provider's key resolution (local-crypto-provider.ts:22-35): in a development posture with no env key and no key file, the persisted key file in the key home is auto-created.
  • So: run in a development posture on a host with no key, the report creates a key file. The database is untouched, as promised, but the key home is not. A later process in a development posture on that host adopts the minted key.
  • The same composition existed in os secret rewrap until PR feat(cli,service-settings): os secret rewrap, the at-rest re-wrap of version-1 sys_secret ciphertext under each holder's producer scope (ADR-0128 §4.2, stage 2) #21469 (in review) closed it. That PR hands the settings service the run's own provider, built so it never mints, or a provider that refuses every call. Two tests pin it.

The fix direction (⛔ not a ruling)

The report composes the settings service the way PR #21469's command does: with a provider that only reads an existing key, or that refuses, so a report-only run never creates key material. A pin runs the report in a development posture with an empty key home and asserts the home stays empty, with a positive control that the default composition would mint there.

Dedupe

The 1,000 most recently updated issues and PRs here, open and closed, were listed by REST and grepped for dev-crypto-key, secret orphans near mint / key file, and report-only near key file. 1 hit: PR #21469 itself, which names this as out of its scope. No card covers it.

Dedupe words: secret orphans key file side effect · report-only command mints dev key · SettingsServicePlugin default crypto provider cli


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsbugSomething isn't workingdomain:clipriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions