Conversation
The auto updater always fetched its manifest from the url baked into the build, so there was no way to point a prod or staging build at a local update feed for testing. Read an optional phoenix_override_config.json from a machine wide folder that only admin/root can write to, and prefer its app_update_url over brackets.config. The folder being admin owned is what makes the file trustworthy- a standard user, an extension or a project cannot forge it, so this cannot be used to redirect the updater at an attacker's server. windows: C:\Program Files\Phoenix Code Control\phoenix_override_config.json mac : /Library/Application Support/Phoenix Code Control/phoenix_override_config.json linux : /etc/phoenix-code-control/phoenix_override_config.json Only keys in OVERRIDABLE_KEYS are honoured, everything else in the file is ignored. Reads fail open- a missing or malformed file just means no override. Desktop only, the file is never read in the browser. Verified end to end on linux/electron: with the file in place the updater fetched its manifest from localhost and showed the served release notes, a non allowlisted key was dropped, and removing the file fell back to the baked in url.
The marker is what makes a core module part of the public extension API docs, which is easy to add by reflex to something meant to stay internal.
Overriding app_update_url alone was not enough to genuinely test an update on linux. Windows and mac download and install the artifact named in the manifest, but linux installs nothing from it- it pipes an installer script into bash and that script decides what to install. So detection used the overridden manifest while the install still fetched the production installer, which reported a fake version and then installed the real build. Add app_update_linux_installer_url to the allowlist and route the linux install through it, so every shipped platform can now be tested end to end. The url is taken as given. Whatever it points at is piped into bash anyway, so sanitising the url would buy nothing- it can only come from our own https constant or from a file that only root can create. Two guards so this cannot hurt the update path: - the config read is raced against a timeout. It is awaited at quit time, when the node process may already be gone, and a read that never settled would hang the quit rather than just the update. - the read is warmed at boot, because a window that only inherits an already scheduled update never runs an update check and would otherwise first touch the disk at quit time. Any failure reading the override falls back to the shipped default and the update proceeds as normal. Also add reference samples under appUpdater/unit-tests: an override config, a fake update manifest and a fake installer that just prints "update done". They point at each other over the dev server so they work as-is.
The cache manifest builder throws on any extension it has not been told about, and appUpdater/unit-tests now carries a sample .sh installer. Shell scripts are never fetched by the app, so they belong in the disallowed list rather than the cache.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Why
The auto updater always fetched its manifest from the url baked into the build, so there was no way to point a prod or staging build at a local update feed to test the update flow.
What
An optional
phoenix_override_config.jsonin a machine wide folder that only admin/root can write to overridesbrackets.configkeys.C:\Program Files\Phoenix Code Control\phoenix_override_config.json/Library/Application Support/Phoenix Code Control/phoenix_override_config.json/etc/phoenix-code-control/phoenix_override_config.json{ "app_update_url": "http://localhost:8000/.../localUpdateManifest.json", "app_update_linux_installer_url": "http://localhost:8000/.../linux-local-update-override-script.sh" }Two keys, because
app_update_urlalone is not enough on linux. Windows and mac download and install the artifact named in the manifest, so overriding the manifest is sufficient there. Linux installs nothing from the manifest — it pipes an installer script into bash and that script decides what to install. Overriding only the manifest therefore produced the worst outcome: it reported a fake version and then installed the real production build. Both are overridable now, so every shipped platform can be tested end to end.The installer url is taken as given, no sanitising. Whatever it points at is piped into bash anyway, so validating the url string would buy nothing — it can only come from our own https constant or from a file that only root can create.
Why this is safe
The folder being admin owned is the whole security model: a standard user, an extension or a downloaded project cannot create the file. Reads need no elevation and raise no OS prompt on any platform —
C:\Program Filesand/etcare world readable, and system/Library/Application Supportis not TCC protected (that only covers~/Documents,~/Desktopetc). Same trust model as the existing AI control file.Only keys in
OVERRIDABLE_KEYSare honoured; everything else in the file is ignored.Not breaking the update path
Updates are critical, so the override cannot degrade them:
Testing
Verified end to end on linux/electron:
localhostand the dialog rendered the served release notes —Update available: {"version":"99.9.9", ...} Detected platform: linux-x64OVERRIDABLE_KEYSwas dropped, andbrackets.configwas left untouchedgetOverrides()returns{}in 0 mswget -qO- "$UPDATE_URL" | bash -s -- --upgrade, runs the sample installer and exits 0Reference samples
src/extensionsIntegrated/appUpdater/unit-tests/holds three samples that point at each other over the dev server, so they work as-is with no setup:localOverride.json— copy to the admin folder asphoenix_override_config.jsonlocalUpdateManifest.json— fake manifest, version99.9.9so it always winslinux-local-update-override-script.sh— fake installer, just printsupdate doneshis added to the PWA cache's disallowed extension list, since the manifest builder throws on extensions it has not been told about and shell scripts are never fetched by the app.Notes for review
main.js) is left hardcoded since linux ships as electron. If that ever changes, note it goes through__TAURI__.shell.Command, whose argument regex lives in phoenix-desktop'stauri.conf.json.PH_LAST_UPDATE_CHECK_TIME, so after dropping in an override file you usually need Help → Check for Updates to see it take effect.dist. Theunit-testsexclusion in the gulpfile is specific tophoenix-pro, which is dropped from prod for an unrelated packaging reason. Happy to add a generic!src/**/unit-tests/**/*if we want that convention to be real.Related
Companion comment only PR in phoenix-pro marks the older
Phoenix AI Controlfolder as legacy and points new machine wide settings here.https://claude.ai/code/session_01UfWRCpcBZbfDd143DV1CxP