cloudflare / cloudflare/cloudflare-os

Google Gatekeeper falls through unsupported URLs to Gmail

Open
#63 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
9.9k
Forks
1.2k
Avg merge
1d 20h
Merged PRs (30d)
107

Description

## Summary

The Google Gatekeeper treats every URL that does not match its Docs, Sheets, Calendar, or BigQuery branches as a Gmail resource. Unsupported hosts and unsupported paths therefore receive a Gmail capability instead of being rejected.

## Evidence

`packages/gatekeeper-google/src/google.ts:832-955` checks the recognized resource branches, then falls through to `// Default: Gmail` and returns `GMAIL_RESOURCE` without checking `parsed.hostname`, protocol, or whether the URL matches the Gmail resource pattern (`https://mail.google.com/*`).

The capability boundary does not independently reject the mismatch. `packages/workshop-backend/src/overseer.ts:7447-7458` passes the caller-supplied `resourceUrl` to `UserDurableObject.getGatekeeperClassFor()` and stores that original URL in `GatekeeperCreationSpec`. `packages/workshop-backend/src/user.ts:1621-1645` trusts the Gatekeeper-returned resource metadata for policy checks and returns it without comparing it to the requested URL.

## Reproduction from the current source

For a connected Google account, request a Gatekeeper with either of these resource URLs:

```text
https://evil.example/resource
https://docs.google.com/document/not-a-document-id
```

`GatekeeperUserImpl.getGatekeeperClassFor()` falls through to the Gmail branch and returns `GmailGatekeeperImpl` plus `GMAIL_RESOURCE`, even though neither URL is a Gmail URL. A direct client, blueprint, or any caller that reaches `OverseerClientInterface.newGatekeeper()` can supply the URL; the core stores the mismatched original URL as the binding's resource URL.

## Impact

This is not a cross-user account escalation: the capability still comes from the caller's own connected Google account. It is a resource-URL validation and audit-integrity bug. A non-Gmail request silently becomes a Gmail mailbox capability, and the returned resource metadata no longer describes the URL the caller requested. That weakens the intended resource-pattern boundary and can make admin/resource policy and audit records misleading.

The agent request path normally pre-validates URLs using `resolveRequestedResource()`, but the capability boundary is also reached by the frontend and blueprint instantiation paths, so the Gatekeeper should reject unsupported URLs itself rather than rely on callers.

## Suggested direction

Reject unsupported Google hosts and paths before the Gmail fallback, or make each resource parser explicitly recognize its canonical host/pattern and return an error otherwise. Add a regression test that calls `getGatekeeperClassFor()` with a non-Google URL and an unsupported Google path and asserts rejection.

I am filing this as an issue rather than a PR because the repository's `CONTRIBUTING.md` asks external contributors to report bugs and avoid design-level patches.

Contributor guide

Open the contributing guide

Research direction

Start in packages/gatekeeper-google/src/google.ts:832-955, then read the resource flow in packages/workshop-backend/src/overseer.ts:7447-7458 and packages/workshop-backend/src/user.ts:1621-1645. Add regression coverage for a non-Google URL and an unsupported Google path passed to getGatekeeperClassFor(); done means both are rejected instead of receiving GmailGatekeeperImpl or GMAIL_RESOURCE.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.