`auth login -s` / `--services` silently drops unknown service names and injects `cloud-platform` scope without documentation
Body
Version: gws v0.22.5 (Windows x86_64 binary from GitHub Releases)
Environment:
- OS: Windows 10/11
- Auth flow: OAuth 2.0 desktop client, consent screen in External / Testing mode
Summary
gws auth login -s <list> is a service-picker filter that accepts a comma-separated list of service names and resolves each to a default scope. In practice, the flag has two undocumented behaviors:
- Unknown names in the list are silently dropped. No warning, no error. The surviving names are granted; the dropped names are not.
- An undocumented
cloud-platformscope is injected whenever any of the surviving services have a sanitization layer dependency. This happens even when the user explicitly omittedcloud-platformfrom their intent.
The combined effect: a user who runs a single auth login -s command gets a token containing a scope set materially different from what they typed, with no diagnostic indicating the mismatch.
Reproduction
Case A: Silent-drop of unknown names
gws auth login -s gmail,drive,calendar,calendar.events,documents,spreadsheets,tasks,contacts,contacts.other.readonlyExpected: Grant all nine named scopes. The help text example (-s drive,gmail,sheets) suggests the flag takes service names, and several items in the list (calendar.events, contacts.other.readonly) are valid scope URI suffixes, so a user could reasonably interpret the flag as accepting either form.
Actual: After browser consent, gws auth status shows the valid service aliases each resolved to one default scope — plus cloud-platform which was not in the list. The names contacts and contacts.other.readonly were silently dropped. No stderr warning. Exit code 0.
Cross-check: Running gws contacts --help after the re-auth fails with a Known services: ... error — so the CLI has the data to validate service names at parse time but does not use it during auth login -s.
Case B: Undocumented cloud-platform injection
Same command as Case A. gws auth status shows cloud-platform in the granted-scope list even though it was not requested. No step of the auth login -s flow surfaced this addition.
Working path (no injection): Deleting token_cache.json and re-running with --scopes (plural) using explicit scope URIs:
gws auth login --scopes https://www.googleapis.com/auth/gmail.modify,https://www.googleapis.com/auth/drive,...This produces a clean grant of exactly the intended scopes with no cloud-platform added.
Hypothesis
The -s code path maps each input token through a lookup table, silently skips tokens that miss the lookup, and post-processes the resulting scope set to add cloud-platform when any resolved service has a sanitization dependency. The --scopes code path bypasses both the lookup and the post-processing.
Impact
- Scope drift. Users get a different scope set than they requested. The only way to catch it is to run
gws auth statusafterward and manually diff against the intended list. - Re-auth friction. Fixing scope drift requires deleting
token_cache.jsonand repeating the browser consent flow. For accounts with test-user restrictions or organizational OAuth policies, that friction is non-trivial. - Potential policy violation.
cloud-platforminjection can silently grant a scope the user deliberately excluded, which conflicts with least-privilege security practices.
Requested behavior
- Reject unknown service names at parse time. The validation data already exists in the binary (
gws contacts --helpproduces aKnown services: ...error). Wire that same validation intoauth login -s. Print an error listing valid service names and exit non-zero before opening the browser consent flow. - Document the
cloud-platforminjection inauth login --help. At minimum: a note that certain services pull incloud-platformas an internal dependency, with a list of which services trigger it. - Gate the injection behind an explicit opt-in (e.g., an
--allow-gcpflag). A user who runs-swithout that flag should receive only the user-facing service scopes.
Source: googleworkspace/cli