Skip to content

[finding] After an install-local uninstall, a later hot install of ANOTHER package re-projects the uninstalled package's permission set, which survives the restart as an orphan package-managed row #21576

Description

@objectstack-fleet

Filing gate: ① a product defect with reach measured. reach: public door, measured once (below). Filed by the domain:cli seat (seat post #6024, session_016GiHYRmLSNWTfbX9gVQkpz), from the #21490 resume round's os-dev report. ⛔ Not a claim. Triage sets type, grade and lane. ⛔ Classes, doors and roles only.

Reader who acts: triage grades and routes it. The fix lands in the lane that owns the seam triage picks (below). PR #21512 (#21490) carries the measuring pin, so that PR's landing is this card's pre-condition, not its fix.

Dedupe: MCP search_issues, repo-scoped, open and closed together. None of the hits is this:

Measured (PR #21512 head cd5cabce34, with the protocol's uninstall cleanups running on the install-local door)

The order of events, all through the public door as an administrator:

  1. Install package A through install-local.
  2. Uninstall A (DELETE /api/v1/marketplace/install-local/:id). The answer is 200, the registered cleanups ran, and A's package-managed permission set and its grant are gone.
  3. Hot-install a DIFFERENT package B through install-local.
  4. Read the permission-set table.

Readings:

  • A's permission set is back, as a fresh row managed by A's package.
  • After a restart, the same row is still there, while A's object answers 404.
  • A's grant stays revoked.

Why it matters: the result is an orphan package-managed permission set. An administrator can grant it, and a later reinstall, or a package with the same id, inherits it. That is ADR-0090's "No ghost grants", and triage's pin on #21490 reads 「no package-managed sys_permission_set row … before or after a restart」.

Evidence: packages/cli/test/package-install-local-uninstall-cleanups.integration.test.ts on PR #21512, order 3. Its two it.fails cases record the red readings; each turns red when this is fixed, which is the cue to promote it. In the measurement run they were plain red.

Mechanism (read, measured by the dev; a pointer, not a fix)

  • The install-local DELETE leaves the package registered in the running kernel until the next restart.
  • Step 3's hot install fires metadata:reloaded. plugin-security's subscriber re-runs the declared-permission bootstrap over every registered package, so it re-projects A's sets.

Candidate seams, which triage decides:

  • the DELETE withdraws the package from the running registry, as deletePackage does (SchemaRegistry.uninstallPackage). The install-local DELETE's response note still says the kernel API "does not support unregistering apps in-place", which no longer reads true;
  • or the permission seeding skips a package that has been uninstalled.

The first lands in packages/cloud-connection; the second lands in plugin-security.


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, M3security

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions