Back to Blog
Technical Security

Cloudflare Workers and Pages Have No Per-Resource Access Control — And There Is No Real Workaround

ALAisha Lalli
Mar 11, 20269 min read

Cloudflare Workers and Pages RBAC gap

Cloudflare Workers and Pages are powerful, genuinely impressive products. But while working on enforcing least-privilege access controls for a production account running multiple Workers and Pages projects, I ran into a hard wall: there is no way in Cloudflare to scope a member role or an API token to a single Worker or a single Pages project. Not through domain scoping. Not through token permissions. Not through any combination of settings in the dashboard. It simply does not exist.

This post documents the gap precisely, as I encountered it — what I tried, what the community is doing to work around it, why those workarounds don't fully solve the problem, and what Cloudflare would need to build to fix it. I'm writing this as a developer who hit this in production, not as a security researcher constructing a theoretical scenario.

This is not a niche edge case. Any team running more than one Worker or Pages project — with more than one developer or one CI/CD pipeline — is affected by this gap.

The Problem: Everything Is Account-Wide

In Cloudflare's permission model, both Workers and Pages are account-level resources. When you grant any role or token access to Workers or Pages, that access applies to every Worker and every Pages project in the account — there is no resource filter at the individual Worker or project level.

Member Roles

When you add a team member and assign them the "Cloudflare Workers Admin" role, they can read, write, and delete every Worker in your account. The same applies to Pages — a member with access to Pages has access to all Pages projects, with no way to restrict them to a single project. There is no mechanism to say "this developer can only access worker-payments" or "this developer can only deploy to the marketing Pages project." Both roles apply account-wide, and that is the only option.

Cloudflare has a feature called Domain Scoped Roles, which allows you to restrict a member's access to specific zones. This sounds relevant — but it is not. Domain Scoped Roles apply exclusively to zone-level resources: DNS, SSL, firewall rules, page rules. Workers and Pages are account-level resources and fall entirely outside the domain scoping system. Assigning a domain-scoped role gives zero restriction over Workers or Pages. A member with Workers Admin scoped to only your production zone still has Workers Admin — and Pages access — across your entire account.

Domain Scoped Roles do not apply to Workers or Pages. They offer no relief for this problem — none.

API Tokens

API tokens are how CI/CD pipelines authenticate to deploy Workers via Wrangler and Pages via the Cloudflare API or wrangler pages deploy. When you create a token with the "Workers Scripts: Edit" permission, it can read, write, and delete any Worker in your account. When you create a token with "Cloudflare Pages: Edit" permission, it can read, write, and delete any Pages project in your account. Neither permission accepts a resource filter at the individual Worker or project level.

Cloudflare's own documentation on CI/CD deployments acknowledges this directly, advising developers to "scope your token" and restrict it to a specific account — but the best granularity offered is account-level. You can restrict a token to one account out of multiple accounts you own, but you cannot restrict it to one Worker or one Pages project within that account.

Cloudflare's permissions blog (September 2023) confirms this directly: as of that writing, resource scoping beyond zones is limited — R2 tokens can be scoped to specific buckets, but Workers and Pages have no equivalent. This is confirmed again in the Workers Builds documentation, which auto-generates a deployment token covering Workers Scripts (edit), Workers KV Storage (edit), Workers R2 Storage (edit), and Workers Routes (edit) — account-wide, with no option to narrow to a single script name. Pages deployments via CI/CD face the same issue: the Cloudflare Pages: Edit permission covers every Pages project on the account.

Time-Bound Tokens Don't Help

A common suggestion is to use time-bound tokens — tokens that expire after a short window — to limit exposure. This is worth doing as a general hygiene measure, but it does not address the scope problem at all. A token that expires in one hour still has full account-wide access to every Worker and every Pages project during that hour. Expiry automates revocation timing — it does not restrict what the token can touch while it is active.

Least privilege is about scope, not duration. Time-bound tokens limit the window of exposure. They do not restrict which Workers or Pages projects a token can access. These are different problems.

What This Breaks

These two gaps together break the two most foundational access control principles in production systems:

  • Least privilege: A CI/CD token for worker-payments should not have standing permission to modify worker-auth, worker-checkout, or any Pages project. A deployment pipeline for your marketing site should not be able to touch your payments Worker. Today, they can — and there is no platform mechanism to prevent it.
  • Separation of duties: A developer working on one Worker or Pages project should not be able to touch another team's resources in production. Today, if they have Workers or Pages access at all, they can.

The blast radius of a compromised token or phished developer account is the entire Workers and Pages surface of your account. In a production account with multiple teams and projects, that is a significant exposure.

What Developers Are Actually Doing: The Workarounds

Because the platform doesn't provide per-Worker or per-Pages-project access controls, teams have landed on a set of compensating patterns. Here is what is actually being used in the wild — and an honest account of the limitations of each.

The Separate Account Pattern — The Most Common Workaround

The most widely recommended workaround in the Cloudflare community is to isolate Workers and Pages projects into separate Cloudflare accounts — one account per project or team. Each account gets its own members and tokens, and because each account is a hard boundary, access is naturally isolated.

A Cloudflare Community thread from April 2025 — asking directly "Can members get access to just my Workers instead of the entire domain account?" — illustrates how common this question is. The answer from the community, consistent across multiple threads going back years, is the same: you need separate accounts. Another April 2025 thread asked about isolating management of different Worker, D1, and Pages apps between teams in a small company — the question names Pages explicitly — and again, the answer pointed toward account separation as the only real option.

This pattern does achieve the isolation goal. But calling it a workaround understates how operationally painful it actually is:

  • Account sprawl and billing fragmentation. Each account is a separate billing entity, a separate dashboard, a separate set of credentials to secure and rotate. Managing members, SSO, and audit logs across N accounts scales poorly.
  • Resources cannot cross account boundaries. Workers that need to share KV namespaces, D1 databases, R2 buckets, or Durable Objects cannot do so across accounts. Pages projects that use Workers as backend functions face the same constraint — service bindings are account-scoped.
  • There is no way to transfer a Worker or Pages project between accounts. If you develop in an isolated account and want to move it into your main production account, you must manually recreate the script or project, all bindings, environment variables, secrets, and routes from scratch. There is no transfer API and no migration path for either Workers or Pages.
  • Observability fragments. Logs, analytics, and metrics are per-account. You lose unified visibility across your Workers and Pages fleet and need external tooling to aggregate it.

Creating separate accounts to isolate Workers and Pages projects is a compensating control — not a designed security architecture. You are working around a missing authorization boundary, not building to one.

Short-Lived Tokens with Aggressive Rotation

Some teams mitigate risk by generating a fresh API token for each deployment run and revoking it immediately afterward. This applies equally to Workers deployments via Wrangler and Pages deployments via wrangler pages deploy or the Cloudflare API. This is a legitimate defence-in-depth step and worth doing — but it only limits exposure duration, not scope. The token still has full account-wide access to all Workers and Pages projects while it exists.

Implementing this properly also requires CI/CD infrastructure that supports dynamic token creation and revocation via the Cloudflare API, which most standard pipeline setups don't support out of the box.

# Illustrative: short-lived token via Cloudflare API
# Even with expiry set, Workers Scripts: Edit still covers ALL Workers.
# Cloudflare Pages: Edit still covers ALL Pages projects.
# There is no script_name or project_name resource filter in the permissions API.

POST /client/v4/user/tokens
{
  "name": "ci-deploy-worker-payments-2026-03-11",
  "policies": [{
    "effect": "allow",
    "resources": { "com.cloudflare.api.account.ACCOUNT_ID": "*" },
    "permission_groups": [{ "id": "<workers-scripts-edit-group-id>" }]
    // ^ No per-Worker or per-Pages-project resource filter exists. Account-wide only.
  }],
  "not_before": "2026-03-11T10:00:00Z",
  "expires_on":  "2026-03-11T11:00:00Z"
}

Locking Down API Access Per-User

Cloudflare's permissions system allows Super Administrators to restrict which account members are allowed to generate API tokens at all. This can centralize token creation into a single service account, reducing the number of people who can create tokens with broad permissions over both Workers and Pages.

This is a useful administrative control — but it doesn't solve the scope problem. Tokens created by the service account still have account-wide Workers and Pages access. It reduces the number of surfaces through which an over-scoped token can be created or misused, but the tokens that do get created are still over-scoped by design.

What Cloudflare Needs to Build

The fix is not architecturally complex to describe. Cloudflare's 2022 blog post introducing Domain Scoped Roles described their Bach permission system as supporting resource scoping for "accounts, zones, worker environments, or DNS records." Worker environments are explicitly named as a resource type in that underlying system — and Pages projects should be treated the same way.

The gap is that this capability has not been exposed for Workers or Pages in the product. What needs to happen:

  • API tokens: The Workers Scripts permission group needs to accept a resource filter of individual Worker script names. The Cloudflare Pages permission group needs to accept a resource filter of individual Pages project names. A token scoped to Workers Scripts: Edit on resource worker-payments should be incapable of touching worker-auth. A token scoped to Cloudflare Pages: Edit on project marketing-site should be incapable of touching payments-portal.
  • Member roles: The Workers Admin and Pages roles (or new per-resource variants) should be scopeable to named Workers and named Pages projects — not just to zones the way Domain Scoped Roles work today, and not in a way that still grants account-wide access.
  • R2 is the proof of concept: Cloudflare already supports bucket-level scoping for R2 tokens. The same pattern applied to Worker script names and Pages project names would solve this. The capability exists in the permission model — it needs to be applied to Workers and Pages.

This would allow a CI/CD token to be incapable, by platform enforcement, of touching any Worker or Pages project other than the one it was issued for. A compromised developer account would be blast-radius limited to their assigned resources. Separation of duties between product teams would be enforced by the platform — not by organisational policy and trust.

What Teams Should Do Right Now

While this gap exists, here is how to get as close to least privilege as the platform currently allows. These are compensating controls — not solutions — and should be understood as such.

  • Isolate your most critical Workers and Pages projects into a dedicated account. If you have a small number of high-stakes resources — payment processing Workers, customer-facing Pages apps, authentication services — and can tolerate the operational overhead, putting them in their own account provides real isolation. Accept that resource sharing and observability will be harder as a trade-off.
  • Generate short-lived tokens per deployment and revoke them immediately. This applies to both Workers and Pages pipelines. Limit the window of exposure even if you cannot limit scope.
  • Restrict API token creation to a single service account. Use Cloudflare's per-user API access control to prevent team members from creating their own broad tokens independently.
  • Monitor the audit log. Use the Cloudflare Audit Log API to track Worker script uploads, Pages deployment events, and any changes to either. Alert on unexpected actors or unexpected resource names being modified.
  • Raise it with Cloudflare formally. If you are on an Enterprise plan, raise per-resource RBAC for both Workers and Pages with your CSM as a named product request. Post in the Community forum. The more teams that document this gap explicitly, the more pressure there is to close it.
# Audit log query: monitor for Worker and Pages changes
GET /client/v4/accounts/{account_id}/audit_logs
  ?action.type=Script+Upload
  &since=2026-01-01T00:00:00Z
  Authorization: Bearer {your_token}

# Run a separate query for Pages deployment events:
GET /client/v4/accounts/{account_id}/audit_logs
  ?action.type=Deployment
  &since=2026-01-01T00:00:00Z
  Authorization: Bearer {your_token}

# Review both for unexpected actors or unexpected resource names.

Closing

Cloudflare is a platform we use and recommend. This post is not a condemnation — it is a precise, documented account of a specific gap that matters for production security across both Workers and Pages. The infrastructure to fix it reportedly already exists in Bach. The ask is straightforward: expose per-resource scoping for tokens and roles across Workers and Pages, exactly as it already exists for R2 buckets.

At Evolving Cyber, we believe that good security is a design decision, not a retrofit. That principle applies to the platforms we build on, not just the software we build. When a platform makes least privilege operationally impossible — or achievable only through account sprawl and manual compensation — it shifts the security burden entirely onto the teams using it. That is not good design.

The ask: scope API tokens and member roles to individual Worker script names and Pages project names. R2 already does this for buckets. Workers and Pages need the same.

Sources & References