-
Notifications
You must be signed in to change notification settings - Fork 738
Description
Summary
The credential store at ~/.config/gws/ (including credentials.json and the associated keyring-derived encryption key) can be copied to any other machine and used to authenticate with full OAuth scope access. This bypasses device-based access controls that organizations rely on — such as Google Workspace's [Context-Aware Access](https://support.google.com/a/answer/9275380) and [device trust policies](https://support.google.com/a/answer/7587183) — which are designed to ensure data can only be accessed from managed, enrolled devices.
Steps to Reproduce
- Authenticate on Machine A:
gws auth login - Copy
~/.config/gws/to Machine B (unmanaged/personal device) - Run
gws drive files liston Machine B — succeeds without re-authentication
Expected Behavior
Credentials should be bound to the originating device. If the credential store is detected on a different device, the CLI should invalidate the session and force re-authentication.
Impact
- Organizational device trust policies (e.g. Google BeyondCorp / Context-Aware Access) can be circumvented entirely at the CLI layer
- Refresh tokens — which are long-lived — remain valid indefinitely after being exfiltrated, even if the device is de-enrolled from MDM
- This is a meaningful risk for enterprise users where
gwsis deployed with broad OAuth scopes (drive,gmail,admin, etc.)
Proposed Fix
Bind credentials to the device by incorporating a stable, machine-unique identifier into the encryption key derivation. On first auth, derive and store a device fingerprint. On each subsequent use, verify the fingerprint matches before decrypting credentials.
The re-auth error message should be explicit and actionable, e.g.:
Error: Credentials were created on a different device and cannot be used here.
Run `gws auth login` to authenticate on this machine.
Additional Context
- The README's [Headless / CI export flow](https://github.com/googleworkspace/cli#headless--ci-export-flow) (
gws auth export) explicitly documents copying credentials between machines, which is a valid use case. Any fix should preserve this workflow with an explicit opt-in flag (e.g.--portable) while making device-bound credentials the secure default. - Related: Google's own OAuth 2.0 documentation recommends that refresh tokens be stored in secure, device-local storage.