You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add 'devproxy system-proxy reset' and restore previous system proxy settings - #2100
A graceful shutdown turns the system proxy off, but a killed or crashed Dev Proxy leaves the OS pointing at a dead port. Even a graceful shutdown only flipped ProxyEnable/proxy state off and left Dev Proxy's ProxyServer value behind, and it turned off any proxy the user had configured before (e.g. a corporate proxy). Crash recovery only existed for detached instances (via state files); a killed foreground instance left nothing to recover from.
Changes
Snapshot before taking over.SystemProxyManager.Enable records the current OS proxy settings plus the owning PID in system-proxy-backup.json in the Dev Proxy config folder:
macOS: per network service web/secure web proxy server, port, and enabled state (networksetup -get[secure]webproxy).
An existing snapshot is kept, so a re-enable after a crash doesn't overwrite the original settings with Dev Proxy's.
Restore instead of just disabling.Disable puts the snapshot back (Windows: set/delete registry values + WinINET refresh; macOS: toggle-proxy.sh off, then networksetup to restore previous servers/states). Without a snapshot it behaves as before. If restoring fails, the snapshot is kept so it can be retried.
New command: devproxy system-proxy reset [--force]. Restores the settings Dev Proxy changed and removes stale instance records. Refuses (exit 1) when a live Dev Proxy owns the system proxy unless --force is passed. On Linux, where Dev Proxy doesn't change the system proxy, it's a no-op.
Automatic recovery on startup. Startup reconciliation now also runs for foreground starts (previously only --detach) and treats a snapshot whose PID is dead as a stale registration, so killed foreground instances are recovered too. It never touches settings owned by a live instance.
Notes / decisions
Command name: the issue suggested devproxy proxy reset (name TBD). I went with devproxy system-proxy reset since devproxy proxy is ambiguous with Dev Proxy itself. Happy to rename.
Startup cleanup is automatic in all sessions rather than prompting in interactive ones, consistent with the existing detached-mode reconciliation and to avoid blocking startup on input.
Linux: Dev Proxy doesn't configure gsettings today (it only logs a hint), so there's nothing to snapshot/restore there.
Unit tests for networksetup output parsing, restore command generation, and snapshot store round-trip/corrupt-file handling.
dotnet build + full DevProxy.Tests pass. Verified devproxy system-proxy reset --help and detached start/stop with --as-system-proxy false. I didn't run the restore against this machine's real system proxy settings.
…ettings
Dev Proxy now records the OS proxy settings it is about to replace (Windows
ProxyEnable/ProxyServer, macOS networksetup web/secure web proxies) together
with the owning PID, and restores them when it stops instead of just turning
the system proxy off.
Because the snapshot outlives the process, a killed or crashed instance
(foreground or detached) can be recovered:
- 'devproxy system-proxy reset' restores the settings on demand
- Dev Proxy restores a stale registration automatically on startup
Closesdotnet#2060
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Proxy recovery can silently fail and delete its backup, while forced resets can disable a restored corporate proxy and configuration errors can block recovery entirely.
- Run 'system-proxy reset' before loading config/plugins
- Don't let an instance's shutdown undo a forced reset or another owner
- Treat networksetup timeouts/nonzero exits and toggle-proxy.sh failures as
restore failures so the snapshot is kept
- Skip disabled macOS services in toggle-proxy.sh and propagate failures
- Report the Linux no-op before checking proxy ownership
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- Clear system-proxy ownership on live instances after a forced reset
- Report failed orphan restores distinctly and keep records for retry
- Continue restoring remaining macOS services after a failure
- Fail toggle-proxy.sh when listing network services fails
- Parse standalone reset args with System.CommandLine
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
A partial proxy-disable failure can skip snapshot restoration, leaving affected network services without their previous corporate proxy settings even after retries.
No open issues 🎉
4 previously missed issues
In code that hasn't changed since last review
Restore proxy snapshots even when disabling a service fails
DevProxy/Proxy/SystemProxyManager.cs:154
If toggle-proxy.sh off fails for one network service, it can still successfully disable the proxies on the other services. This condition then skips RestoreMacOS entirely, leaving those working services without their previous corporate proxy; retrying repeats the same problem while the failing service remains. Please attempt snapshot restoration even when the disable pass fails, and combine both results so the backup is still retained on either failure.
Recognize recovery commands with global options in any position
DevProxy/Commands/DevProxyCommand.cs:148
The standalone recovery path is still bypassed when a recursive global option appears between the commands. For example, devproxy system-proxy --no-color reset is valid for the registered command tree, but this positional check returns false. It then builds the application host, where an empty plugins configuration throws before recovery runs. Please recognize the parsed command path independently of global-option placement so these valid invocations also work with broken configurations.
Enforce enum validation for standalone options
DevProxy/Commands/SystemProxyCommand.cs:56
The registered command validates --output and --log-level as enums, but the standalone path accepts arbitrary strings here. For example, devproxy system-proxy reset --force --log-level typo changes the OS proxy settings instead of rejecting the invalid option before any side effects. Please retain the enum option types in this parser as well.
Validate process start time to prevent stale PID ownership
DevProxy/Proxy/SystemProxySnapshot.cs:20
After a crash or reboot, the OS can reuse the saved PID for an unrelated process, causing startup recovery to skip restoration and an unforced reset to refuse it. Persist the owner's process start time alongside its PID, refresh both on takeover, and validate both in the ownership and orphan checks. The snapshot's existing CreatedAt cannot identify the current owner because it is preserved across takeovers.
Addressing the previously missed issues from the latest review, fixed in d14a489:
Restore snapshots even when disabling fails: fixed. RestoreMacOS now always runs when a snapshot exists, and either failure keeps the snapshot.
Global options in any position: fixed. IsSystemProxyResetCommand skips --output/--log-level (and their values) and --no-color before matching the command path.
Enum validation in the standalone parser: fixed. It now uses Option<OutputFormat?> and Option<LogLevel?>, so --log-level typo is rejected before any OS change.
PID start-time validation: not changing this here. The existing instance state (StateManager.IsProcessRunning, GetOrphanedSystemProxyStatesAsync, stop, status) identifies instances by PID only. The snapshot follows the same model on purpose, so ownership checks stay consistent across the code. If a PID is reused, the worst case is that automatic cleanup is skipped and reset asks for --force, which the error message explains. Validating start time for every PID-based check is a broader change that belongs in a separate issue.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Attached option values cause valid system-proxy reset commands to bypass the standalone recovery path, allowing broken configuration to block the reset.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Human review is needed to assess interacting recovery, ownership, and command-routing risks that could lose recovery records or unexpectedly alter system proxy settings.
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
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.
Resolves #2060
Problem
A graceful shutdown turns the system proxy off, but a killed or crashed Dev Proxy leaves the OS pointing at a dead port. Even a graceful shutdown only flipped
ProxyEnable/proxy state off and left Dev Proxy'sProxyServervalue behind, and it turned off any proxy the user had configured before (e.g. a corporate proxy). Crash recovery only existed for detached instances (via state files); a killed foreground instance left nothing to recover from.Changes
SystemProxyManager.Enablerecords the current OS proxy settings plus the owning PID insystem-proxy-backup.jsonin the Dev Proxy config folder:ProxyEnable/ProxyServerregistry values (including "value didn't exist").networksetup -get[secure]webproxy).Disableputs the snapshot back (Windows: set/delete registry values + WinINET refresh; macOS:toggle-proxy.sh off, thennetworksetupto restore previous servers/states). Without a snapshot it behaves as before. If restoring fails, the snapshot is kept so it can be retried.devproxy system-proxy reset [--force]. Restores the settings Dev Proxy changed and removes stale instance records. Refuses (exit 1) when a live Dev Proxy owns the system proxy unless--forceis passed. On Linux, where Dev Proxy doesn't change the system proxy, it's a no-op.--detach) and treats a snapshot whose PID is dead as a stale registration, so killed foreground instances are recovered too. It never touches settings owned by a live instance.Notes / decisions
devproxy proxy reset(name TBD). I went withdevproxy system-proxy resetsincedevproxy proxyis ambiguous with Dev Proxy itself. Happy to rename.devproxy system-proxy resetonce this ships.Testing
networksetupoutput parsing, restore command generation, and snapshot store round-trip/corrupt-file handling.dotnet build+ fullDevProxy.Testspass. Verifieddevproxy system-proxy reset --helpand detached start/stop with--as-system-proxy false. I didn't run the restore against this machine's real system proxy settings.