Skip to content

wslc: prevent session name squatting for default WSLc sessions#40144

Merged
benhillis merged 2 commits intofeature/wsl-for-appsfrom
user/benhill/wslc_default_session
Apr 13, 2026
Merged

wslc: prevent session name squatting for default WSLc sessions#40144
benhillis merged 2 commits intofeature/wsl-for-appsfrom
user/benhill/wslc_default_session

Conversation

@benhillis
Copy link
Copy Markdown
Member

@benhillis benhillis commented Apr 9, 2026

Summary

Prevents malicious users from squatting reserved WSLc session names (wslc-cli, wslc-cli-admin) by moving default session name and settings resolution to the server.

Changes

  • Server-side default sessions: CreateSession(nullptr) and OpenSessionByName(nullptr) resolve the default session name from the caller's token and username (e.g. wslc-cli-alice, wslc-cli-admin-bob). The client no longer knows or sends session names for default sessions.
  • Reserved name rejection: Explicit use of reserved names via CreateSession returns WSLC_E_SESSION_RESERVED. Invalid session names return WSLC_E_INVALID_SESSION_NAME.
  • User impersonation: Settings.yaml is loaded under the caller's identity via wil::impersonate_token.
  • Dedicated EnterSession API: Custom sessions (wslc session enter) use a separate API that reads settings.yaml server-side and sets NoCreate storage flags.
  • wslcsettings shared library: Extracted UserSettings into a shared library used by both wslc.exe and wslservice.exe. SettingsCommand now calls UserSettings directly instead of duplicating file creation logic.
  • Cleanup: Removed SessionOptions class, SessionModel.cpp, WslcSettingsTemplate.h. Moved EnumVariantMap.h to common. SessionSettings is NON_MOVABLE (uses unique_ptr to avoid c_str() pointer invalidation).

Testing

  • E2E test verifies reserved names are rejected and default session creation still works.
  • All E2E tests updated for username-qualified session names.

Copilot AI review requested due to automatic review settings April 9, 2026 16:23
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

@benhillis benhillis changed the base branch from master to feature/wsl-for-apps April 9, 2026 16:26
@benhillis benhillis requested a review from Copilot April 9, 2026 16:26
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 23 out of 24 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (2)

src/windows/wslc/services/SessionService.cpp:45

  • When attaching to the default session (empty sessionName -> nullptr passed to OpenSessionByName), failure paths still format errors using sessionName.c_str(), which is an empty string. This produces user-facing messages like "Session '' not found". Consider special-casing the empty-name/default-session case and emitting a clearer localized message (e.g., "Default session not found" / "Failed to open default session") instead of printing an empty name.
    HRESULT hr = manager->OpenSessionByName(sessionName.empty() ? nullptr : sessionName.c_str(), &session);
    if (FAILED(hr))
    {
        if (hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND))
        {
            wslutil::PrintMessage(Localization::MessageWslcSessionNotFound(sessionName.c_str()), stderr);
            return 1;
        }

        auto errorString = wsl::windows::common::wslutil::ErrorCodeToString(hr);
        wslutil::PrintMessage(
            Localization::MessageErrorCode(Localization::MessageWslcOpenSessionFailed(sessionName.c_str()), errorString), stderr);
        return 1;

src/windows/wslc/services/SessionService.cpp:186

  • TerminateSession now treats an empty displayName as "default session" (nullptr passed to OpenSessionByName), but the "not found" / "terminate failed" messages still use displayName.c_str() and can end up printing an empty name. Please special-case the default-session call path so the error message is meaningful when no session name was provided.
    wil::com_ptr<IWSLCSession> session;
    HRESULT hr = sessionManager->OpenSessionByName(displayName.empty() ? nullptr : displayName.c_str(), &session);
    if (FAILED(hr))
    {
        if (hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND))
        {
            wslutil::PrintMessage(Localization::MessageWslcSessionNotFound(displayName.c_str()), stderr);
            return 1;
        }

@benhillis benhillis force-pushed the user/benhill/wslc_default_session branch from 6df494e to c991c9d Compare April 9, 2026 22:50
Copilot AI review requested due to automatic review settings April 9, 2026 22:54
@benhillis benhillis force-pushed the user/benhill/wslc_default_session branch from c991c9d to 46d783e Compare April 9, 2026 22:54
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 24 out of 25 changed files in this pull request and generated 1 comment.

@benhillis benhillis force-pushed the user/benhill/wslc_default_session branch 2 times, most recently from 46c11a9 to 7cb7ef9 Compare April 10, 2026 00:31
Copilot AI review requested due to automatic review settings April 10, 2026 00:31
@benhillis benhillis force-pushed the user/benhill/wslc_default_session branch from 7cb7ef9 to 784b41f Compare April 10, 2026 00:34
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 24 out of 25 changed files in this pull request and generated 5 comments.

@benhillis benhillis force-pushed the user/benhill/wslc_default_session branch from 784b41f to d0b3819 Compare April 10, 2026 02:12
@benhillis benhillis changed the title Prevent session name squatting for default WSLc sessions wslc: prevent session name squatting for default WSLc sessions Apr 10, 2026
@benhillis benhillis marked this pull request as ready for review April 10, 2026 02:22
@benhillis benhillis requested a review from a team as a code owner April 10, 2026 02:22
Copilot AI review requested due to automatic review settings April 10, 2026 02:22
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 24 out of 25 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/windows/common/WSLCUserSettings.cpp:12

  • File header comment still says Module Name: UserSettings.cpp, but the file is now WSLCUserSettings.cpp. Please update the module name to match the actual filename to avoid confusion when tracing build/log output and code ownership.

@benhillis benhillis force-pushed the user/benhill/wslc_default_session branch from d0b3819 to 50b93fb Compare April 10, 2026 02:50
Copilot AI review requested due to automatic review settings April 10, 2026 17:46
@benhillis benhillis force-pushed the user/benhill/wslc_default_session branch from 50b93fb to bfd1cae Compare April 10, 2026 17:46
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 24 out of 25 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/windows/service/exe/WSLCSessionManager.h:80

  • CreateSession and OpenSessionByName now accept nullptr for default-session resolution (per the updated IDL), but the corresponding declarations here still use _In_ for the pointer parameters. Please update the SAL annotations to _In_opt_ (and similarly mark WslcSessionSettings as optional) so static analysis and code readers match the new contract.
    void GetVersion(_Out_ WSLCVersion* Version);
    void CreateSession(const WSLCSessionSettings* WslcSessionSettings, WSLCSessionFlags Flags, IWSLCSession** WslcSession);
    void EnterSession(_In_ LPCWSTR DisplayName, _In_ LPCWSTR StoragePath, IWSLCSession** WslcSession);
    void ListSessions(_Out_ WSLCSessionInformation** Sessions, _Out_ ULONG* SessionsCount);
    void OpenSession(_In_ ULONG Id, _Out_ IWSLCSession** Session);
    void OpenSessionByName(_In_ LPCWSTR DisplayName, _Out_ IWSLCSession** Session);

Copy link
Copy Markdown
Member

@dkbennett dkbennett left a comment

Choose a reason for hiding this comment

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

All the session changes as they relate to the CLI look good to me. Minor comments about having more specific error codes for better diagnosability. We can always add this later but would be easier to pay as we go.

Copilot AI review requested due to automatic review settings April 13, 2026 16:55
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 25 out of 26 changed files in this pull request and generated 4 comments.

Ben Hillis and others added 2 commits April 13, 2026 13:32
- Server now determines default session name and settings from caller's
  token, preventing malicious users from squatting reserved session names
- CreateSession rejects explicit use of reserved names (wslc-cli,
  wslc-cli-admin) with case-insensitive E_ACCESSDENIED check
- Null StoragePath remains valid for ephemeral sessions; empty string
  is rejected as E_INVALIDARG
- Add dedicated EnterSession API with null/empty parameter validation
- Early return optimization: skip YAML parse if default session exists
- Inline BuildFeatureFlags into SessionSettings constructor
- Extract UserSettings into shared wslcsettings library used by both
  wslc.exe and wslservice.exe
- Move EnumVariantMap.h to common
- Fix std::terminate crash in CustomDmesgOutput test when CreateSession
  fails by adding a scope_exit guard to join the reader thread
- Add session name squatting E2E test with case-insensitive coverage

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…rsonation

- Append username to default session names so different users don't
  collide (e.g. wslc-cli-alice, wslc-cli-admin-bob) [OneBlue]
- Impersonate caller when loading settings.yaml server-side [OneBlue]
- Factor name resolution into ResolveDefaultSessionName helper [OneBlue]
- Add WSLC_E_SESSION_RESERVED and WSLC_E_INVALID_SESSION_NAME error
  codes for better diagnosability [dkbennett]
- Use prefix-based reserved name check (blocks all wslc-cli-* names)
- Fix pre-existing HostFileShareMode namespace qualification bug
- Remove unused variable in GetDefaultStoragePath test helper [Copilot]
- Update all E2E tests for username-qualified session names

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 13, 2026 20:34
@benhillis benhillis force-pushed the user/benhill/wslc_default_session branch from cbc897e to 8d63613 Compare April 13, 2026 20:34
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 25 out of 26 changed files in this pull request and generated 4 comments.

@benhillis benhillis enabled auto-merge (squash) April 13, 2026 22:19
@benhillis benhillis merged commit cd05f5c into feature/wsl-for-apps Apr 13, 2026
11 checks passed
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.

5 participants