Skip to content

fix: MS Teams OAuth on Windows and browser.cdpUrl security redaction#68077

Closed
nightq wants to merge 1 commit intoopenclaw:mainfrom
nightq:fix/issue-67738-windows-oauth-v2
Closed

fix: MS Teams OAuth on Windows and browser.cdpUrl security redaction#68077
nightq wants to merge 1 commit intoopenclaw:mainfrom
nightq:fix/issue-67738-windows-oauth-v2

Conversation

@nightq
Copy link
Copy Markdown
Contributor

@nightq nightq commented Apr 17, 2026

Summary

This PR fixes two issues reported in #67738:

  1. MS Teams OAuth on Windows fails because explorer.exe exits with code 1
  2. browser.cdpUrl is not included in sensitive URL config paths for security redaction

Root Cause

  1. Windows OAuth: explorer.exe <url> delegates to the running Explorer shell and exits with code 1, causing the OAuth promise to reject even though the browser opened correctly.
  2. Security: .cdpUrl config paths (Chrome DevTools Protocol URLs) can contain sensitive credentials but were not being redacted.

Fix

  1. Windows OAuth: Use cmd /c start "" URL instead of explorer.exe, which exits 0 on success.
  2. Security: Added .cdpUrl to the list of sensitive URL config paths.
  3. Tests: Updated test assertions to handle all three platforms (darwin, win32, linux) and added test coverage for the new .cdpUrl path.

Test Plan

  • Unit tests pass for msteams setup-surface
  • Unit tests pass for redact-sensitive-url
  • Test assertions cover all three platforms

Closes #67738

Fixes openclaw#67738

Root cause: explorer.exe <url> on Windows delegates to the running Explorer shell and exits with code 1, causing OAuth promise rejection even though the browser opened correctly.
Fix: Use cmd /c start "" URL instead, which exits 0 on success. Also updates test assertions to handle all three platforms (darwin, win32, linux).

Additionally adds .cdpUrl to sensitive URL config paths for security redaction.
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 17, 2026

Greptile Summary

This PR fixes two issues: it adds a proper Windows code path to openDelegatedOAuthUrl using cmd /c start "" url (replacing the non-functional xdg-open fallback that would fail on Windows), and adds .cdpUrl to the sensitive URL redaction list to prevent CDP credentials from leaking in logs.

Both fixes are correct and well-scoped. The cmd /c start "" url pattern with shell: false is established convention in the Node.js ecosystem for opening URLs on Windows and correctly relies on Node's CreateProcess argument quoting to prevent cmd.exe metacharacter injection.

Confidence Score: 5/5

Safe to merge — both fixes are correct, minimal, and well-tested for non-Windows platforms.

No P0 or P1 issues. The single P2 comment flags that the updated test mirrors production logic rather than independently verifying each platform branch, so the new Windows path is untested on Linux/macOS CI — a test-coverage concern, not a correctness issue. The code changes themselves are sound.

extensions/msteams/src/setup-surface.test.ts — the platform-conditional test approach means the win32 branch is never exercised on Linux/macOS CI.

Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/msteams/src/setup-surface.test.ts
Line: 70-81

Comment:
**Test mirrors production logic — Windows branch untested on Linux/macOS CI**

The test derives `expectedCmd`/`expectedArgs` using the same `process.platform` conditionals as the production code, so the test is a near-tautology: it will pass on Linux (only verifying the `xdg-open` path) without ever executing the `cmd /c start "" url` branch. If the Windows args were typo'd in production, the test would still green on Linux CI.

Consider stubbing `process.platform` with `vi.spyOn(process, 'platform', 'get')` to drive each platform branch independently, e.g.:

```typescript
for (const [platform, expectedCmd, expectedArgs] of [
  ["darwin", "open", [url]],
  ["win32", "cmd", ["/c", "start", '""', url]],
  ["linux", "xdg-open", [url]],
] as const) {
  vi.spyOn(process, "platform", "get").mockReturnValue(platform);
  // ... spawn and assert
}
```

This would give real coverage of the new Windows code path regardless of where CI runs.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix: MS Teams OAuth on Windows uses cmd ..." | Re-trigger Greptile

Comment on lines +70 to 81
const expectedCmd =
process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
const expectedArgs =
process.platform === "darwin"
? [url]
: process.platform === "win32"
? ["/c", "start", '""', url]
: [url];
expect(spawn).toHaveBeenCalledWith(expectedCmd, expectedArgs, {
stdio: "ignore",
shell: false,
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Test mirrors production logic — Windows branch untested on Linux/macOS CI

The test derives expectedCmd/expectedArgs using the same process.platform conditionals as the production code, so the test is a near-tautology: it will pass on Linux (only verifying the xdg-open path) without ever executing the cmd /c start "" url branch. If the Windows args were typo'd in production, the test would still green on Linux CI.

Consider stubbing process.platform with vi.spyOn(process, 'platform', 'get') to drive each platform branch independently, e.g.:

for (const [platform, expectedCmd, expectedArgs] of [
  ["darwin", "open", [url]],
  ["win32", "cmd", ["/c", "start", '""', url]],
  ["linux", "xdg-open", [url]],
] as const) {
  vi.spyOn(process, "platform", "get").mockReturnValue(platform);
  // ... spawn and assert
}

This would give real coverage of the new Windows code path regardless of where CI runs.

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/msteams/src/setup-surface.test.ts
Line: 70-81

Comment:
**Test mirrors production logic — Windows branch untested on Linux/macOS CI**

The test derives `expectedCmd`/`expectedArgs` using the same `process.platform` conditionals as the production code, so the test is a near-tautology: it will pass on Linux (only verifying the `xdg-open` path) without ever executing the `cmd /c start "" url` branch. If the Windows args were typo'd in production, the test would still green on Linux CI.

Consider stubbing `process.platform` with `vi.spyOn(process, 'platform', 'get')` to drive each platform branch independently, e.g.:

```typescript
for (const [platform, expectedCmd, expectedArgs] of [
  ["darwin", "open", [url]],
  ["win32", "cmd", ["/c", "start", '""', url]],
  ["linux", "xdg-open", [url]],
] as const) {
  vi.spyOn(process, "platform", "get").mockReturnValue(platform);
  // ... spawn and assert
}
```

This would give real coverage of the new Windows code path regardless of where CI runs.

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c8d68107e8

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

process.platform === "darwin"
? ["open", [url]]
: process.platform === "win32"
? ["cmd", ["/c", "start", '""', url]]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Quote URL when calling cmd /c start on Windows

On Windows this passes the OAuth URL to cmd as an unquoted command argument (["/c", "start", '""', url]), but MS Teams auth URLs are built with multiple query params (...?...&...) in buildMSTeamsAuthUrl (extensions/msteams/src/oauth.flow.ts:47). In cmd, unquoted metacharacters like & are command separators, so the URL can be truncated and extra tokens are parsed as separate commands, which breaks the browser-open flow and can execute unintended command fragments from the URL text. The URL should be safely quoted/escaped before handing it to cmd start.

Useful? React with 👍 / 👎.

@steipete
Copy link
Copy Markdown
Contributor

Codex deep review: this should be narrowed before merge.

Current state on main:

The Windows launcher fix here is the right direction: cmd /c start "" <url> avoids the explorer.exe non-zero-exit problem. The remaining issue is test quality: the test still mirrors process.platform, so Linux/macOS CI does not actually exercise the win32 branch.

Best mergeable shape:

I would not close #67659 until that narrow current patch lands.

@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented Apr 30, 2026

Thanks for the context here. I swept through the related work, and this is now duplicate or superseded.

Close as superseded. The CDP redaction half of this PR is already on current main, while the remaining MS Teams Windows OAuth launcher bug is tracked by the focused open issue/PR pair #67659/#67660; this branch also introduces a concrete Windows cmd.exe URL parsing risk and should not be the branch maintainers merge.

So I’m closing this here and keeping the remaining discussion on the canonical linked item.

Review details

Best possible solution:

Close this PR and keep the remaining work centered on #67659/#67660 or an equivalent narrow replacement. The accepted fix should be MS Teams-only, avoid routing OAuth URLs through cmd.exe, preserve the extension boundary, add platform-stubbed win32 regression coverage, and leave the already-shipped CDP redaction implementation untouched.

Do we have a high-confidence way to reproduce the issue?

Yes. The current-main bug is reproducible by stubbing process.platform to win32 and calling openDelegatedOAuthUrl(), which still selects xdg-open; the PR’s security regression is source-reproducible because buildMSTeamsAuthUrl() emits query-string URLs that this branch passes through cmd /c start.

Is this the best way to solve the issue?

No. This PR mixes an already-shipped redaction fix with a Windows launcher change that conflicts with prior OpenClaw hardening against cmd.exe URL parsing; the narrower maintainable path is #67660 or a similar plugin-boundary-safe Windows opener with independent platform tests.

Security review:

Security review needs attention: The PR introduces a concrete Windows command-parsing concern by sending OAuth URLs through cmd /c start.

  • [high] cmd.exe parses OAuth URL text — extensions/msteams/src/setup-surface.ts:38
    The win32 branch passes an OAuth URL to cmd /c start, reintroducing the same command-interpreter surface that prior shared browser-open hardening removed for provider OAuth/browser URLs. Query separators and crafted URL text can break the browser-open flow or be parsed as command syntax on Windows.
    Confidence: 0.91

What I checked:

Likely related people:

  • steipete: Recent main history shows work on MS Teams setup hardening and Windows browser-open hardening, including fix(msteams): harden security-sensitive flows and fix: harden Windows browser open. (role: recent maintainer / security hardening owner; confidence: high; commits: c56b56e514f8, 30aa7e0d4d22; files: extensions/msteams/src/setup-surface.ts, extensions/msteams/src/setup-surface.test.ts, src/infra/browser-open.ts)
  • sudie-codes: Commit 355794c added MS Teams delegated auth flow and setup integration, including the OAuth setup surface that this PR changes. (role: introduced delegated auth behavior; confidence: high; commits: 355794c24a39; files: extensions/msteams/src/setup-surface.ts, extensions/msteams/src/oauth.flow.ts, extensions/msteams/src/oauth.ts)
  • Ziy1-Tan: Commit 4b59878 merged fix: redact credentials in browser.cdpUrl config paths #67679, which added browser CDP URL redaction coverage now present on main. (role: implemented already-landed redaction behavior; confidence: high; commits: 4b5987829d0f; files: src/shared/net/redact-sensitive-url.ts, src/shared/net/redact-sensitive-url.test.ts, src/config/redact-snapshot.test.ts)
  • coygeek: Commit 4938b2c fixed Windows provider OAuth/browser URL command injection by removing cmd.exe parsing from the shared open-url path, directly relevant to this PR’s proposed cmd /c start branch. (role: adjacent Windows OAuth/browser-open security owner; confidence: medium; commits: 4938b2cc43ec; files: src/infra/browser-open.ts, src/commands/onboard-helpers.test.ts)

Codex review notes: model gpt-5.5, reasoning high; reviewed against 7969f1f07ccc.

@clawsweeper clawsweeper Bot closed this Apr 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: msteams Channel integration: msteams size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants