Skip to content

xCloud Pulse stores API bearer token in local cache #1

Description

@wnstfy

xCloud Pulse stores API bearer token in local cache

Severity

High

Summary

While testing xCloud Pulse, I found that the API bearer token is written to the local macOS CFNetwork cache.

The app says the token is stored in macOS Keychain, but after saving a token and using the app, the bearer token was also present here:

~/Library/Caches/host.xcloud.xCloudPulse/Cache.db-wal

The token was still there after I quit the app and moved xCloud Pulse.app to the Bin.

This means another process running as the same macOS user could read the token from disk without needing Keychain access.

Impact

xCloud API tokens can be created with Full Access, and I do not see an expiration/TTL option when creating a token.

If a full-access token is recovered from this cache file, it may allow access to both read and write API actions, including server and site operations.

Evidence

After using the app, these cache folders existed:

~/Library/Caches/host.xcloud.xCloudPulse
~/Library/HTTPStorages/host.xcloud.xCloudPulse

I checked for token-related strings without printing the token:

rg -a -i -l 'Authorization|Bearer|api[_-]?token|xcloud api token|token' \
  ~/Library/Caches/host.xcloud.xCloudPulse \
  ~/Library/HTTPStorages/host.xcloud.xCloudPulse

Output:

/Users/webnestify/Library/Caches/host.xcloud.xCloudPulse/Cache.db-wal

A redacted check of the file showed request metadata containing:

Authorization
Bearer [redacted]
https://app.xcloud.host/api/v1/...

Steps to Reproduce

  1. Create an xCloud API token.
  2. Install and open xCloud Pulse.
  3. Save the token in the app.
  4. Click Test Connection and load sites/servers.
  5. Quit xCloud Pulse.
  6. Move xCloud Pulse.app to the Bin.
  7. Run:
rg -a -i -l 'Authorization|Bearer|api[_-]?token|xcloud api token|token' \
  ~/Library/Caches/host.xcloud.xCloudPulse \
  ~/Library/HTTPStorages/host.xcloud.xCloudPulse
  1. Cache.db-wal still contains bearer-token request metadata.

Expected Result

The API token should only be stored in Keychain and should not be written to local URLSession/CFNetwork cache files.

Actual Result

The bearer token is written to the local CFNetwork cache and remains there after the app is closed and removed.

Suggested Fix

Use an ephemeral URLSession or disable caching for authenticated API requests. Requests that include an Authorization header should not be cached.

Also clear the app cache when the token is removed or the user logs out.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions