Skip to content

fix(desktop): prevent proxy password mask corruption - #3704

Open
Sun-GLiang wants to merge 1 commit into
apache:mainfrom
Sun-GLiang:fix/3696-proxy-password-editing
Open

fix(desktop): prevent proxy password mask corruption#3704
Sun-GLiang wants to merge 1 commit into
apache:mainfrom
Sun-GLiang:fix/3696-proxy-password-editing

Conversation

@Sun-GLiang

@Sun-GLiang Sun-GLiang commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Summary

  • keep saved proxy credentials out of persisted settings and Renderer input values
  • add an explicit keep/replace/delete credential contract with a shared Runtime Host operation lane
  • keep password editing local until blur or Enter, make Eye reveal the current draft, and remove Copy only from the proxy password field
  • preserve schema-v1 config import/export compatibility with preflight validation

Fixes #3696

Verification

  • all workspace tests passed in serial scheduling; Desktop 1518/1518
  • Runtime Host 1144/1144 with package-level test concurrency set to 1 to avoid its known cache-cleanup race
  • focused proxy password and Settings cache tests — 56/56
  • offline authenticated proxy E2E — 1/1
  • npm run lint
  • npm run format:check
  • npm run build
  • npm run typecheck
  • npx knip --workspace apps/desktop
  • npx knip --workspace packages/ui

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: OpenAI Codex implemented the fix, tests, verification, and review-driven corrections.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@Sun-GLiang
Sun-GLiang force-pushed the fix/3696-proxy-password-editing branch from b94e9ab to c5ec403 Compare August 25, 2026 02:09
@Sun-GLiang
Sun-GLiang marked this pull request as ready for review August 25, 2026 02:32

@jackwener jackwener left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed exact head c5ec40335dcaa0d19756bff067bced9cf2cf687c. I found two blocking correctness issues in the new proxy-credential write path: one cross-client race that can recreate a credential after authentication was disabled, and one partial-commit path that applies proxy policy even though the API reports failure. The hosted checks are green and the branch merges cleanly, but these state-consistency issues need to be resolved before approval.

else await setCredential(client, PROXY_CREDENTIAL, proxy.password);
}
else if (proxy.credential?.kind === "replace")
await setCredential(client, PROXY_CREDENTIAL, proxy.credential.secret);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Make proxy policy and credential replacement one Host-owned operation across clients. The new queue is local to one RuntimeHostSettingsModule, so two supported Desktop clients have independent lanes. Client A can start a replacement and pause at the credential CAS; client B can then set authEnabled=false and delete the credential; when A receives credential_stale, its retry rereads the now-empty locator and recreates the secret with expected: null. A production-adapter/CAS probe ended with authEnabled=false while the vault again contained A's replacement secret. The existing "disable wins" test uses one module and therefore cannot cover this inter-client ordering. Please move the policy decision plus keep/replace/delete into one Runtime Host atomic or recoverable operation that validates both the policy revision and credential basis, and add a two-client test asserting the vault remains empty after disable.

): Promise<void> {
if (patch.network?.proxy) {
const proxy = patch.network.proxy;
await client.updateRuntimePolicy((policy) => ({

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Do not commit proxy policy before the credential write can still fail. A normal update containing both policy fields and credential: replace/delete first commits set_network_proxy here, then performs vault persistence below. If that second step rejects, the caller receives an error even though the Host is already using the new host/auth/username with the old credential. This is also reachable from the schema-v1 settings-plus-credentials import path. A production-adapter failure probe observed the rejected call with enabled=true, authEnabled=true, username=new-user, and the old secret still stored; the success control stored the replacement. Existing failure coverage sends a credential-only patch, so it never checks policy after the failure. Please make this a single Host-side compound operation, or define an explicit recoverable commit protocol, and test each persistence cut for committed/unchanged/known recovery semantics.

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.

bug(desktop): proxy password editing stores the masking sentinel and corrupts credentials

2 participants