From 0db2b9e95c6f6ba90fdb7712c91d7608fb0afe76 Mon Sep 17 00:00:00 2001 From: Diego Imbert Date: Wed, 15 Jul 2026 13:45:47 +0200 Subject: [PATCH] fix: exclude service accounts from the free AI tier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Free-tier eligibility was keyed solely on authed.email. Workspace admins can create and impersonate arbitrary service accounts (synthetic *.sa.wm.dev identities), each of which would receive its own one-time grant — letting one tenant mint many grants and drain the instance-wide daily allowance. Skip the free-tier fallback for *.sa.wm.dev identities. Co-Authored-By: Claude Opus 4.8 (1M context) --- backend/windmill-api/src/ai.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/backend/windmill-api/src/ai.rs b/backend/windmill-api/src/ai.rs index 2cc61e1eb3..a92a9830f4 100644 --- a/backend/windmill-api/src/ai.rs +++ b/backend/windmill-api/src/ai.rs @@ -717,7 +717,14 @@ async fn proxy( // one-time grant and the instance's daily cap have room. // Errors once the grant is spent, the day is capped, or the // user already has a request in flight; None otherwise. - if let Some((free_credentials, lease)) = + // + // Service accounts (synthetic `*.sa.wm.dev` identities) are + // excluded: a workspace admin can create/impersonate them in + // bulk, and each distinct email would otherwise mint its own + // grant and let one tenant drain the instance-wide daily cap. + let free = if authed.email.ends_with(".sa.wm.dev") { + None + } else { crate::ai_free_tier_oss::resolve_free_tier_credentials( &provider, &db, @@ -725,7 +732,8 @@ async fn proxy( &authed.email, ) .await? - { + }; + if let Some((free_credentials, lease)) = free { free_lease = Some(lease); break 'cred free_credentials; }