Skip to content

Mattermost fifteen-leg coordinated wave: OAuth-session account switch, unsigned SAML RelayState, fan-out secret leaks, and config-test credential recall

Sources: GitHub Security Advisories published 2026-10-16 09:30Z. Leg links: GHSA-hhjm-mg95-jr6g / CVE-2026-19076 (MMSA-2026-00758), GHSA-x9f3-cqmx-7phq / CVE-2026-16453 (MMSA-2026-00727, high), GHSA-9mh4-36gv-g7wx / CVE-2026-19621 (MMSA-2026-00766), GHSA-f4q7-3g3r-qrg8 / CVE-2026-18799 (MMSA-2026-00757), GHSA-7v3h-fv85-64q9 / CVE-2026-19541 (MMSA-2026-00761), GHSA-hqj7-4xc2-7mc7 / CVE-2026-19601 (MMSA-2026-00764), GHSA-j732-3464-9jvm / CVE-2026-18223 (MMSA-2026-00747), GHSA-rh7p-pp3q-6cf8 / CVE-2026-18551 (MMSA-2026-00752), GHSA-mqc4-5px9-95jm / CVE-2026-18256 (MMSA-2026-00748), GHSA-7ggq-hqj4-w5vc / CVE-2026-19603 (MMSA-2026-00765), GHSA-3m39-x8xr-762f / CVE-2026-18560 (MMSA-2026-00754), GHSA-c5qm-9j4f-82mg / CVE-2026-18795 (MMSA-2026-00756), GHSA-pqq2-2w3v-m8j5 / CVE-2026-19600 (MMSA-2026-00763), GHSA-9h79-c924-x83x / CVE-2026-19867 (MMSA-2026-00773), GHSA-9vq4-jrpg-w3w2 / CVE-2026-16251 (MMSA-2026-00726).

Fix bands split inside the wave: most legs fixed in 11.7.10 / 11.8.5 / 11.9.1 / 11.10.0 bands; the token-in-logs, LDAP-bind, OAuth-secret, status-API, and mention-keys legs carry the next band (11.7.10 / 11.8.5 / 11.9.1 / 11.10.1). Two bands in one wave = per-leg fingerprinting, not one version check.

This wave is durable because it is a collaboration-platform lifecycle map: which session types may call which identity-mutating endpoints, which unsigned protocol fields become authorization inputs, which fan-out read paths forget to re-scrub, and which "test connection" buttons re-send stored secrets to whatever destination was just edited.

Headline legs

  • OAuth application sessions drive the account-type switch endpoint (CVE-2026-19076, medium but impact-critical): POST /api/v4/users/login/switch does not reject OAuth-app bearer sessions. A valid OAuth token for a target user lets the attacker set an attacker-controlled password and detach the account from its identity provider — permanent, IdP-independent ATO of an SSO-backed account. The OAuth token is usually scoped for API access, never imagined as a credential-management credential.
  • Unsigned SAML RelayState is an authorization input (CVE-2026-16453, high): the SAML RelayState POST parameter's team_id / invite_id fields are never integrity-checked, so an authenticated SAML user forges them to join any team, including invite-only teams. The SAML assertion is signed; the RelayState riding beside it is attacker-writable and treated as trusted routing state.
  • Fan-out paths keep integration secrets (CVE-2026-19621): action-integration secrets are not stripped from post payloads before post_deleted websocket broadcasts and thread API responses — any channel member harvests server-side webhook URLs and their auth context from interactive-message posts. The post store keeps the secrets; only the primary render path scrubs them.
  • Slack import is an identity-binding sink (CVE-2026-18799): import account binding is not restricted to admin-initiated imports, so a team admin uploads a crafted Slack export containing target users' email addresses and force-adds existing users to their team and forges posts attributed to those identities — email-address matching becomes account linking with no consent step.
  • Saved secrets re-transmit on validation flows (two legs, one invariant): outgoing-OAuth validation does not require re-entry of the stored client secret, so an integrations manager points the token URL at an attacker endpoint and triggers validation to replay the secret (CVE-2026-19541); and the AD/LDAP bind password is not invalidated when the server address changes, so Test Connection sends the plaintext bind credential to an attacker-chosen LDAP server (CVE-2026-19601). Destination and credential are edited in the same form; the credential survives the destination change.
  • Invitation tokens carry no recipient binding (CVE-2026-18223): team/guest invite redemption never validates the invited email, so any forwarded or leaked invite link joins a team or reaches private channels.
  • Role-combination gap (CVE-2026-18551): the member-roles PUT validates each role but not the guest × admin scheme combination — a guest escalates to team/channel admin.
  • Oracles — private team ID/name via a modified team-search request (CVE-2026-18256); any user's active private channel ID via the user-status endpoints (CVE-2026-19603); a post's flagged status via direct API call without reviewer permission (CVE-2026-18560). DM/GM server-side check missing lets non-reviewers quarantine DM/GM posts (CVE-2026-18795).
  • Log and resource legs — debug logs write unsanitized session/OAuth tokens (log access = user impersonation, CVE-2026-19600); unbounded notify_props.mention_keys with quadratic multibyte matching = cross-channel CPU exhaustion on any shared channel (CVE-2026-19867); image-proxy direct fetch buffers unbounded remote responses (CVE-2026-16251).

Operator rules

  1. Build a session-type × endpoint matrix on any SSO-backed platform. Enumerate session classes (cookie, PAT, OAuth user token, OAuth app token, SSO-minted, bot) and probe every identity-mutating endpoint (password set, MFA enroll, IdP detach/switch, email change, recovery reset) from each class. A token type accepted by a credential-management endpoint is this leg exactly. Same page genealogy: the Sept 18 token page's credential-class uplift and the Oct 9 SmarterMail stale-role refresh — credentials outlive and out-scope their minting intent.
  2. Sign ≠ complete coverage: check what rides beside the signed object. SAML RelayState, OIDC state, OAuth redirect_uri extras — unsigned companions to signed assertions frequently carry routing/authorization decisions. On authorized SAML tests, mutate team_id-class fields in RelayState after a valid login and record which destinations the app honors. (SAML surface page sibling.)
  3. Scrub parity is per read path. For any stored object containing a secret field, enumerate every way it leaves the server — primary API, thread/reply API, websocket broadcast events (create/update/delete variants), search results, exports — and diff the field set per path. The delete event is the classic forgotten sibling: nobody designs redaction for a payload that is "just announcing removal."
  4. Treat every "Test/Validate connection" button as an outbound request you control the destination of (in labs). If the form saves the destination and reuses the stored secret, you have a saved-credential recall oracle reachable by any integrations-manager-tier role. Audit rule: stored secrets must be write-only after save (masked, re-entry required, or bound to destination hash). Cross-ref the July 30 URL-policy page — here the destination edit is the attack, not the URL parse.
  5. Invite/link redemption must bind recipient identity. Any capability token that redeems for team/channel membership without an email/username binding is a forwarding vulnerability; treat forwarded-link behavior as a test case on every invite flow.
  6. Import/export mappers are account-linking sinks. Any feature that matches imported rows against local identities by email (Slack/Mattermost cross-instance import, CSV user load, migration tools) needs the admin-initiated + consent gates; without them, a mid-tier admin forges identity attribution. Same invariant as the Oct 13 Docker Hub GhostPat page: transitions that re-attach identities/credentials need consent-of-receiver.
  7. Validate role combinations, not members. PUT-role APIs that check "may assign admin" and "may assign guest" separately but never the pair produce guest-admin escalation. Battery: assign every pair of scheme roles your role permits assigning, then probe the intersection's effective permissions.
  8. Version-band fingerprinting: run per-CVE, not per-product. The two fix bands in this wave (11.10.0 vs 11.10.1) mean a "patched" 11.10.1 readout still leaves nothing of these, but an 11.10.0 readout keeps the five later legs — report per-leg bands.

Validation boundaries

  • Lab Mattermost instances only, two disposable accounts/teams plus synthetic private channels; prove switch-endpoint acceptance against your own second account, never a real SSO tenant.
  • Capture token/webhook material as fingerprints (length + sha256 prefix), never full values, in notes or reports.
  • Invite-forward, status-oracle, and team-search legs prove with read-only requests and synthetic IDs; no real channel membership changes outside disposable teams.
  • DoS legs: mention_keys/oversized-image proofs in a lab instance only; never trigger latency on shared servers.