Graph cross-origin continuation URLs receive the account OAuth bearer token
Categories
(MailNews Core :: Networking: Exchange, defect)
Tracking
(Not tracked)
People
(Reporter: tjddbdud1, Unassigned)
Details
(Keywords: sec-low)
Attachments
(1 file)
Summary
Thunderbird's Microsoft Graph delta synchronization accepts the complete URL from a server-supplied @odata.nextLink, creates a new request to that URL, and attaches the configured account's OAuth access token without checking that the request has the same origin as the Graph endpoint.
A Graph response can therefore direct Thunderbird to another HTTPS origin and disclose Authorization: Bearer .... The same code is used for message, folder, and calendar delta synchronization. Persisted @odata.deltaLink URLs need the same validation before a later authenticated sync.
Impact
Graph access tokens can carry mailbox read/write and send scopes. A destination that receives the token can reuse it against the resource server until expiration, subject to the granted scopes.
Suggested severity: High (at minimum Moderate). Suggested CVSS 3.1: 8.1 (AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N). Suggested CWE: CWE-200/CWE-522 and CWE-918.
Affected code
rust/ms_graph_tb/src/pagination.rs:163-173,193-197accepts the complete next-link URI and builds a GET from it.rust/graph_xpcom/src/client/sync_messages_for_folder.rs:167-171rust/graph_xpcom/src/client/sync_folder_hierarchy.rs:112-115rust/graph_xpcom/src/client/sync_calendar_items.rs:103-107rust/protocol_shared/src/operation_sender/send_request.rs:56-89,135-149attaches the OAuth token after checking only HTTPS/loopback, not configured-origin equality.
This is a new authenticated request, not an HTTP redirect, so redirect-layer stripping does not protect it.
Reproduction
The attached local-only xpcshell PoC starts two loopback servers on different ports. The configured Graph origin returns an empty delta page whose @odata.nextLink points to the second origin. The second origin records the request and returns a terminating page.
Verified on Thunderbird Daily 161.0a1, BuildID 20261103100812, and current comm-central 1e798c885fd5fddbad1da12c73a589b8b8a04f60:
originsDiffer=true
accountRequests=1
captureRequests=1
accountAuthorization=Bearer access_token
capturedAuthorization=Bearer access_token
exactBearerCopied=true
completed=true
operationErrors=0
Passed: 1
Failed: 0
Loopback HTTP is explicitly permitted by the current token transport check, allowing the test to stay offline. The same sender accepts any HTTPS continuation URL. The token is synthetic; the PoC contacts no Microsoft or third-party service.
Related report
Bug 2083220 covers a repeated same-origin @odata.nextLink causing an unbounded loop. This report needs only one cross-origin link and demonstrates token disclosure. A visited-link or page-count guard does not fix this trust-boundary issue.
Recommended fix
Validate and canonicalize both nextLink and deltaLink before obtaining credentials or sending a request. Require HTTPS and exact origin equality with the configured Graph base URL; reject cross-origin values rather than following them without credentials. Add cross-host, cross-port, downgrade, and stored-delta-link regression tests for all three sync paths.
AI assistance was used for source review and drafting; the attached proof and observations were executed locally with synthetic data.
Attachment SHA-256: 137657E890E23EAF4EFA4ADB07C89BD86BE3E03E0D3795E293878689F44404A8.
Comment 1•12 days ago
|
||
We already check that the domain is the same. The claim we accept "any HTTPS continuation URL" is false. (It's technically not full validation, since it could be on a different port, but I'm not worried about leaking Graph credentials to the same Graph server on another port, since we're enforcing HTTPS.) Even if we didn't check this, this isn't really a security issue, since the server receiving the token is the only entity that would be in a position to change the delta request next link.
Description
•