Skip to content

security(plugins): govern ALL entry-point groups by the unified allow/block (total trust boundary)#297

Merged
fas89 merged 2 commits into
mainfrom
security/govern-all-entrypoint-groups
Jun 26, 2026
Merged

security(plugins): govern ALL entry-point groups by the unified allow/block (total trust boundary)#297
fas89 merged 2 commits into
mainfrom
security/govern-all-entrypoint-groups

Conversation

@fas89

@fas89 fas89 commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

What & why

Closes the single structural blocker the final re-assessment (8.6/10) named: a
uniform plugin trust boundary. After the round-2 work, six entry-point groups
still walked importlib.metadata and ep.load()'d plugin code outside the
unified manager — never calling is_allowed, invisible to fluid plugins, and
logging raw redact_secret_text(str(e)). Several execute plugin code, so
FLUID_PLUGINS_BLOCKLIST could not stop a malicious apply_hook,
extension_validator, modeling_technique, or source_adapter from running.

Changes

  • plugin_manager gains EXTRA_GROUPS + governed_groups() = ROLE_GROUPS ∪
    the six CLI-internal groups (commands, apply_hooks, extension_schemas,
    extension_validators, modeling_techniques, source_adapters) — the single
    source of truth for every group the allow/block policy governs.
  • All six walk sites now gate each entry-point through is_allowed(ep.name)
    before ep.load(), and log load/discovery failures by exception type only.
  • installed_plugins() / fluid plugins now surface all governed groups — none are
    invisible.

The "one allow/block policy for every plugin surface" invariant is now total:
no entry-point group that runs plugin code escapes the operator gate.

Verification

  • 1657+ copilot/validate/apply/provider/help-sync tests pass; 9 new gate pins
    (each of the 6 groups + governed-group coverage + inspection surface).
  • ruff + black==24.10.0 clean.
  • Security review (on the first 4-group commit): no findings — gate before
    load() at every site, type-only logging strictly more conservative, no import
    cycle; the reviewer explicitly identified modeling_techniques + source_adapters
    as the remaining ungated walks, which the second commit closes with the identical pattern.
  • Live test via fluid plugins + the CLI: the extension groups are now visible;
    FLUID_PLUGINS_BLOCKLIST=demoext blocks an extension-validator from loading and
    running (previously impossible).

fas89 added 2 commits June 27, 2026 01:25
…/block (no bypass)

The final re-assessment found the one structural blocker to a uniform trust
boundary: four CLI-internal entry-point groups — fluid_build.commands,
fluid_build.apply_hooks, fluid_build.extension_schemas,
fluid_build.extension_validators — walked importlib.metadata OUTSIDE the unified
manager, never called is_allowed, and were invisible to `fluid plugins`. Two of
them (apply_hooks, extension_validators) ep.load() and EXECUTE plugin code with
no operator policy, using best-effort redact_secret_text(str(e)) instead of the
type-only guarantee. So FLUID_PLUGINS_BLOCKLIST could not stop a malicious
apply_hook / extension-validator from loading and running.

- plugin_manager gains EXTRA_GROUPS (the four CLI-internal groups) + governed_groups()
  = ROLE_GROUPS ∪ EXTRA_GROUPS — the single source of truth for "every group the
  operator allow/block policy governs".
- All four walk sites (bootstrap.py commands, apply.py apply_hooks,
  extension_schemas.py schemas + validators) now gate each entry-point through
  is_allowed(ep.name) BEFORE ep.load(), and log load/discovery failures by
  exception TYPE only (was redact_secret_text(str(e))). Dropped the now-unused
  redact_secret_text import + stale comment in bootstrap.
- installed_plugins() (and thus `fluid plugins`) now surfaces all governed groups,
  so commands/apply_hooks/extension_* are no longer invisible.

The "one allow/block policy for every plugin surface" invariant is now total.
107 governance/validate/apply/provider/help-sync tests pass; 7 new pins
(governed-group coverage, inspection surface, extension schema/validator blocked
before load).
…+ source_adapters

The PR-I security review found two MORE code-executing entry-point walks that
still bypassed the gate (pre-existing): fluid_build.modeling_techniques
(_discover_entrypoints ep.load()) and fluid_build.source_adapters
(resolve_catalog_adapter_class lazy target.load()). To make the "one allow/block
policy for every plugin surface" invariant genuinely TOTAL:

- EXTRA_GROUPS gains modeling_technique + source_adapter (governed_groups + `fluid
  plugins` now cover all 11 groups: 5 roles + 6 CLI-internal).
- modeling_techniques._discover_entrypoints gates each ep through is_allowed BEFORE
  load; type-only failure logging.
- source_registry.resolve_catalog_adapter_class gates the lazy target.load() through
  is_allowed (raises a clear RuntimeError when blocked); type-only discovery logging.

1657 copilot/modeling/source tests pass; 2 new gate pins (source adapter + modeling
technique blocked before load). Now NO entry-point group that runs plugin code
escapes the operator allow/block.
@github-actions github-actions Bot added cli Changes to the CLI surface or implementation tests Test coverage or test infrastructure changes needs-docs Pull request needs a linked docs update or justification labels Jun 26, 2026
@github-actions

Copy link
Copy Markdown

📄 Documentation Reminder

This PR appears to be missing a documentation reference. Our docs live in a separate repo.

Please update the PR description with one of:

  • Link a docs PR — check the "Docs PR linked" box and paste the URL
  • Mark as no docs needed — check "No docs needed" with a justification
  • Acknowledge docs TODO — check "Docs TODO" and create the docs PR before merge

See the Contributing Guide for details.

@fas89
fas89 merged commit 6904f60 into main Jun 26, 2026
28 checks passed
@fas89
fas89 deleted the security/govern-all-entrypoint-groups branch June 26, 2026 23:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cli Changes to the CLI surface or implementation needs-docs Pull request needs a linked docs update or justification tests Test coverage or test infrastructure changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant