Skip to content

fix(session-bridge): read MDM channel policy and fail closed when unreadable - #8218

Merged
kyle-sexton merged 5 commits into
mainfrom
work-resolve-issue/issue-6108-39106118208-1
Oct 19, 2026
Merged

kyle-sexton merged 5 commits into
mainfrom
work-resolve-issue/issue-6108-39106118208-1

Conversation

@melodic-automation-lanes

Copy link
Copy Markdown
Contributor

Closes #6108

Hold: a human merges this

Summary

Opened by the work-resolve-issue lane. The run's own summary:

managed_policy() now reads the macOS com.anthropic.claudecode managed preferences and the HKLM Settings value, ranked after server-managed settings and above the managed files. An MDM source that exists but cannot be read selects loopback. The file tier now combines lists and merges nested blocks across drop-ins, and allowedChannelPlugins is taken whole from the highest-ranked source.

Not verified

  • The plist path /Library/Managed Preferences/com.anthropic.claudecode.plist and the CLAUDE_CODE_REMOTE=true cloud-session signal are not stated on the managed-settings page; they are my inference. Per-user managed-preferences plists are not read.
  • No live run on a managed macOS or Windows machine (out of scope per the issue); the winreg and reg.exe readers are untested here.
  • sync-shared-copies --check-bump runs only in CI.
  • Fragments were written by hand because new-changelog-fragment refuses a detached HEAD; check-changelog-fragments accepts them.

Fix

  • lib/session-bridge/session_bridge.py: MDM readers (plist, HKLM via winreg or reg.exe on WSL), UNREADABLE handling in managed_policy and select_transport, file-tier deep merge, basis citation with as-of date and recheck trigger
  • lib/session-bridge/test_session_bridge.py: tests with stubbed plist and registry readers for allowing, not allowing, unreadable and absent policy; drop-in list combine; higher-ranked list replace; HKCU never consulted; WSL gating; cloud skip
  • lib/session-bridge/README.md: organization check row and policy notes updated
  • plugins/{planning/surface,planning/view-bridge,work-items/view-bridge,review/view-bridge}/session_bridge.py: regenerated copies
  • .changes/{planning,review,work-items}/fix-session-bridge-mdm-channel-policy-6a1c3e5d.md: patch fragments

Verification

The run reports:

  • read https: //code.claude.com/docs/en/managed-settings: source ranking (remote, MDM, files, HKCU), plist domain and HKLM Settings value, unreadable HKLM counts as present, file-tier merge rules, allowedChannelPlugins taken whole from the highest-ranked source, HKCU excluded from admin sources
  • run-test-file lib/session-bridge/test_session_bridge.py: 68 passed
  • sync-shared-copies --check: all 493 copies match
  • check-changelog-fragments: all 9 fragments valid
  • cant-fail-scan on the test file: pass; one advisory mock-only-oracle finding in an existing test I did not touch
  • fresh-context subagent review: three findings (reg.exe decode crash, WSL launch-failure and access-denied classification, malformed plist crash), all fixed before the final run
  • The lane run: https://github.com/melodic-software/claude-code-plugins/actions/runs/39106118208

Left out: the items under Not verified.

Related

#6108

…eadable

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Comment thread lib/session-bridge/session_bridge.py Outdated
@github-actions

github-actions Bot commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

claude-security-review needs no new review of 73bacc766cb1e519fa39d52038fccfa9f67fd92b: no file of this pull request changed since the review of 44a2a79.

Security review: incremental (e0ed38e..44a2a79), plugins/planning/shared/session_bridge.py

No security findings.

The change adds macOS plist and Windows HKLM registry (WSL via reg.exe) policy reading to managed_policy, a file-tier merge (merge_files), and a fail-closed branch in loopback.

  • No injection: hive is only ever the literal "HKLM", and reg.exe is called with a list argument (no shell), a timeout and stdin=DEVNULL.
  • Fail-closed on unreadable sources: An unreadable or malformed plist or registry value yields UNREADABLE, and loopback keeps channels off. Only reg.exe's English "unable to find" counts as absent. Any other failure, including a localized not-found, fails closed.
  • Privilege ordering preserved: The user-writable HKCU hive is not read. HKLM counts on WSL only with wslInheritsWindowsSettings: true. Server-managed settings still rank first, then MDM, then the managed settings files.
  • merge_files is safe: It copies nested dicts and lists, so it doesn't mutate shared state. It applies replace-whole and merge-by-name only to the keys the cited merge rules name.

Considered, not reported:

  • CLAUDE_CODE_REMOTE=true skips MDM. It is user-controlled but only changes this advisory bridge's view, and it mirrors the documented Claude Code behaviour.
  • reg.exe is resolved through PATH. The caller already controls its own environment, so no privilege is gained.
  • PLIST_PATH.exists() could raise on a permission error. That is a robustness edge, not an exploitable path.

The instruction-surface lens doesn't apply, since no rule or guardrail is deleted or softened. No workflow or Actions files changed.

@github-actions

github-actions Bot commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

claude-review needs no new review of 73bacc766cb1e519fa39d52038fccfa9f67fd92b: no file of this pull request changed since the review of 44a2a79.

No findings. This is an incremental review of 44a2a79b against e0ed38e7, which touches only plugins/planning/shared/session_bridge.py.

  • The change: That file is a regenerated copy of lib/session-bridge/session_bridge.py. I diffed the two, and the copy differs only by the two-line GENERATED from ... header, so it matches the canonical source. I also diffed the surface copy against shared, and they were identical.
  • What it does: The new code adds MDM policy ranking to managed_policy: the macOS plist and the Windows HKLM registry, including a WSL read through reg.exe. It also adds a file-tier merge (merge_files) and a fail-closed loopback when a policy source exists but is unreadable.
  • What I traced, by reading the code only:
    • Unreadable plist or registry values fail closed.
    • The WSL wslInheritsWindowsSettings gate only drops HKLM when its value is a readable dict.
    • merge_files shallow-copies nested dicts before recursing and handles lists and the replace-whole and by-name key sets.
    • The new settings is None guard in select_transport runs before any settings.get call.
  • Not verified: I did not run the test suite or ruff.
  • Docs: I did not re-fetch the managed-settings docs, so I did not check the ranking and merge claims in the new comments.

@melodic-automation-lanes

Copy link
Copy Markdown
Contributor Author

pr-unblock / address-feedback finished round 1 of 3 on 9c0a446.

@melodic-automation-lanes melodic-automation-lanes Bot added the needs-human Human-in-the-loop required; autonomous sessions must not resolve items carrying this. label Oct 18, 2026
@melodic-automation-lanes

Copy link
Copy Markdown
Contributor Author

The pr-unblock lane stopped on this pull request and needs a person: the lane did not record a disposition for every review thread it kept, so none was posted.

  • Reason: feedback-incomplete
  • Resume key: 9c0a446232b1113a16c9b9dc27f86c50a5a73241 (the head the lane stopped on)

To resume, deal with the reason above, remove the needs-human label (and do-not-merge, if set), then dispatch the pr-unblock workflow with pr-number=8218 and activity=address-feedback:

gh workflow run pr-unblock.yml -R melodic-software/claude-code-plugins -f pr-number=8218 -f activity=address-feedback

kyle-sexton and others added 4 commits October 18, 2026 23:23
… failure

On WSL, a reg.exe that hangs or exits non-zero with anything but the
not-found message now reads as UNREADABLE (loopback) instead of absent,
so a localized access-denied no longer falls through to the file tier.
A missing reg.exe stays absent. Tests stub subprocess.run for the
success parse, not-found, missing binary, timeout and localized errors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…in merge

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kyle-sexton
kyle-sexton added this pull request to the merge queue Oct 19, 2026
Merged via the queue into main with commit 6b277f8 Oct 19, 2026
31 checks passed
@kyle-sexton
kyle-sexton deleted the work-resolve-issue/issue-6108-39106118208-1 branch October 19, 2026 04:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-human Human-in-the-loop required; autonomous sessions must not resolve items carrying this.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(session-bridge): fail closed on MDM-only channel policy and merge allowedChannelPlugins across sources

1 participant