Skip to content

[pkg firewall] wire up endor-vscode.sh - #28

Open
dekkagaijin wants to merge 1 commit into
vscode-fw-4-watcherfrom
vscode-fw-5-bash-wiring
Open

[pkg firewall] wire up endor-vscode.sh#28
dekkagaijin wants to merge 1 commit into
vscode-fw-4-watcherfrom
vscode-fw-5-bash-wiring

Conversation

@dekkagaijin

Copy link
Copy Markdown
Contributor

Merge after #27

Fourth chunk, and the one that makes the previous three do something. Adds the shared block, the ecosystem template, the generator wiring, the removal path, and an end-to-end suite over the actual generated scripts.

shared/blocks/vscodegallery.txt the two-line contract: set serviceUrl,
delete extensionUrlTemplate, with the
fail-closed rationale inline
bash/templates/vscode.sh fills the install-time token, loops the
discovered installs, installs the watcher
bash/generate.sh VSCODE_GALLERY_BASE, the block assignment,
--no-vscode-watcher, the repatch builder
bash/templates/remove.sh watcher first, then unpatch per install

The gallery token is built at install time, not generation time, because it embeds this machine's attribution label — the same pattern as GO_PROXY_URL. token = base64url(":"), where the attributed user is the existing endor_attr_username value, so VS Code events carry @ like every other ecosystem.

The watcher payload is not cp "$0". MDM tools routinely pipe scripts to bash or exec them from a temp file that is already unlinked by the time a watcher fires, so generate.sh builds the repatch script first, base64s it into the installer, and the installer decodes it to a stable path at 700. out/endor-vscode-repatch.sh is also emitted standalone, purely so an admin can read what gets installed.

--no-vscode-watcher opts out loudly but still exits 0. Failing every MDM check-in over a deliberate setting is alert fatigue, and alert fatigue is how real warnings end up ignored.

endor-vscode.sh is deliberately not folded into endor-all.sh. It is the only script that writes inside an application bundle and the only one that installs a persistent daemon, so folding it in would silently widen the blast radius of every existing endor-all deployment on the next regeneration.

README documents the three new prerequisites, none of which the repo has had before:

  • macOS Ventura+ needs the App Management (SystemPolicyAppBundles) TCC grant for the MDM agent. Root is not exempt.
  • The gallery token lands in world-readable product.json (0644) and cannot not. VS Code offers no indirection there, so any local user can read a working firewall credential. Mitigation is blast radius only: use a dedicated, separately revocable API key for VS Code.
  • codesign --verify will report the bundle as modified. Expected. Do not re-sign — ad-hoc re-signing strips hardened-runtime entitlements and would durably break stored GitHub auth.

Also notes that extension downloads still come from Microsoft's CDN by design (enforcement is filtering-by-omission, so *.vsassets.io must stay reachable), and that enforcement is discovery-time — already-installed and sideloaded extensions are not retroactively caught.

Tests: 54 assertions over the generated scripts. install -> idempotent re-run ->
simulated update -> watcher repatch -> the count surfacing in MDM output -> --dry-run -> credential rotation -> --no-vscode-watcher -> byte-exact removal -> idempotent removal. The suite refuses to run until it has verified that install discovery is redirected into its sandbox; without that it would patch the real VS Code on the machine running it.

https://endorlabs.atlassian.net/browse/LM-452

@dekkagaijin dekkagaijin changed the title package-firewall: wire up endor-vscode.sh [pkg firewall] wire up endor-vscode.sh Aug 4, 2026
Fourth chunk, and the one that makes the previous three do something. Adds the
shared block, the ecosystem template, the generator wiring, the removal path,
and an end-to-end suite over the actual generated scripts.

  shared/blocks/vscodegallery.txt   the two-line contract: set serviceUrl,
                                    delete extensionUrlTemplate, with the
                                    fail-closed rationale inline
  bash/templates/vscode.sh          fills the install-time token, loops the
                                    discovered installs, installs the watcher
  bash/generate.sh                  VSCODE_GALLERY_BASE, the block assignment,
                                    --no-vscode-watcher, the repatch builder
  bash/templates/remove.sh          watcher first, then unpatch per install

The gallery token is built at *install* time, not generation time, because it
embeds this machine's attribution label — the same pattern as GO_PROXY_URL.
token = base64url("<attributed-user>:<secret>"), where the attributed user is the
existing endor_attr_username value, so VS Code events carry
<console-user>@<machine> like every other ecosystem.

The watcher payload is not `cp "$0"`. MDM tools routinely pipe scripts to bash or
exec them from a temp file that is already unlinked by the time a watcher fires,
so generate.sh builds the repatch script first, base64s it into the installer,
and the installer decodes it to a stable path at 700. out/endor-vscode-repatch.sh
is also emitted standalone, purely so an admin can read what gets installed.

--no-vscode-watcher opts out loudly but still exits 0. Failing every MDM check-in
over a deliberate setting is alert fatigue, and alert fatigue is how real
warnings end up ignored.

endor-vscode.sh is deliberately *not* folded into endor-all.sh. It is the only
script that writes inside an application bundle and the only one that installs a
persistent daemon, so folding it in would silently widen the blast radius of
every existing endor-all deployment on the next regeneration.

README documents the three new prerequisites, none of which the repo has had
before:

  - macOS Ventura+ needs the App Management (SystemPolicyAppBundles) TCC grant
    for the MDM agent. Root is not exempt.
  - The gallery token lands in world-readable product.json (0644) and cannot not.
    VS Code offers no indirection there, so any local user can read a working
    firewall credential. Mitigation is blast radius only: use a dedicated,
    separately revocable API key for VS Code.
  - `codesign --verify` will report the bundle as modified. Expected. Do *not*
    re-sign — ad-hoc re-signing strips hardened-runtime entitlements and would
    durably break stored GitHub auth.

Also notes that extension downloads still come from Microsoft's CDN by design
(enforcement is filtering-by-omission, so *.vsassets.io must stay reachable), and
that enforcement is discovery-time — already-installed and sideloaded extensions
are not retroactively caught.

Tests: 54 assertions over the generated scripts. install -> idempotent re-run ->
simulated update -> watcher repatch -> the count surfacing in MDM output ->
--dry-run -> credential rotation -> --no-vscode-watcher -> byte-exact removal ->
idempotent removal. The suite refuses to run until it has verified that install
discovery is redirected into its sandbox; without that it would patch the real
VS Code on the machine running it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@dekkagaijin
dekkagaijin force-pushed the vscode-fw-5-bash-wiring branch from 0e6e8e8 to 5b5eb23 Compare August 6, 2026 16:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant