Skip to content

Commit db179b6

Browse files
schwaaampclaude
andcommitted
Security: Rename SUPABASE_SERVICE_ROLE_KEY to SERVICE_ROLE_KEY
- Rename environment variable across all Edge Functions - Supabase CLI blocks secrets starting with SUPABASE_ - Update shared supabaseClient.ts and 20+ Edge Functions - Allows proper secret rotation via: supabase secrets set SERVICE_ROLE_KEY=<key> Security Context: - GitGuardian detected exposed service_role JWT in repository - Legacy JWT cannot be regenerated, must migrate to Secret API keys - Removed exposed secrets from mobile/.env (not committed) Next Steps: 1. Create new Secret API key in Supabase dashboard 2. Set secret: supabase secrets set SERVICE_ROLE_KEY=<new_key> 3. Deploy all Edge Functions 4. Revoke exposed API keys (OpenAI, Claude, Gemini, USDA) 5. Rotate OAuth secrets (Fitbit, Whoop) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent a9a7bd3 commit db179b6

File tree

31 files changed

+71
-71
lines changed

31 files changed

+71
-71
lines changed

supabase/functions/_shared/config.test.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Deno.test({
2424
fn: () => {
2525
const requiredVars = [
2626
"SUPABASE_URL",
27-
"SUPABASE_SERVICE_ROLE_KEY",
27+
"SERVICE_ROLE_KEY",
2828
];
2929

3030
const missing: string[] = [];
@@ -194,9 +194,9 @@ Deno.test({
194194
});
195195

196196
Deno.test({
197-
name: "SUPABASE_SERVICE_ROLE_KEY is not empty and has sufficient length",
197+
name: "SERVICE_ROLE_KEY is not empty and has sufficient length",
198198
fn: () => {
199-
const key = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY");
199+
const key = Deno.env.get("SERVICE_ROLE_KEY");
200200

201201
if (!key) {
202202
return;
@@ -205,7 +205,7 @@ Deno.test({
205205
assertEquals(
206206
key.length > 50,
207207
true,
208-
"SUPABASE_SERVICE_ROLE_KEY appears too short"
208+
"SERVICE_ROLE_KEY appears too short"
209209
);
210210
},
211211
});
@@ -290,7 +290,7 @@ Deno.test({
290290
fn: () => {
291291
const criticalVars = [
292292
"SUPABASE_URL",
293-
"SUPABASE_SERVICE_ROLE_KEY",
293+
"SERVICE_ROLE_KEY",
294294
"WHOOP_CLIENT_ID",
295295
"WHOOP_CLIENT_SECRET",
296296
"FITBIT_CLIENT_ID",
@@ -343,7 +343,7 @@ Deno.test({
343343
Deno.test({
344344
name: "SECURITY: Service role key is not accidentally exposed as anon key",
345345
fn: () => {
346-
const serviceRoleKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY");
346+
const serviceRoleKey = Deno.env.get("SERVICE_ROLE_KEY");
347347

348348
if (!serviceRoleKey) {
349349
return;
@@ -354,14 +354,14 @@ Deno.test({
354354
assertEquals(
355355
serviceRoleKey.startsWith("eyJ"),
356356
true,
357-
"SUPABASE_SERVICE_ROLE_KEY should be a JWT"
357+
"SERVICE_ROLE_KEY should be a JWT"
358358
);
359359

360360
// Service role key should be significantly long (at least 100 chars)
361361
assertEquals(
362362
serviceRoleKey.length > 100,
363363
true,
364-
"SUPABASE_SERVICE_ROLE_KEY appears too short"
364+
"SERVICE_ROLE_KEY appears too short"
365365
);
366366
},
367367
});
@@ -376,7 +376,7 @@ Deno.test({
376376
const allRequiredVars = [
377377
// Supabase
378378
"SUPABASE_URL",
379-
"SUPABASE_SERVICE_ROLE_KEY",
379+
"SERVICE_ROLE_KEY",
380380
// WHOOP
381381
"WHOOP_CLIENT_ID",
382382
"WHOOP_CLIENT_SECRET",

supabase/functions/_shared/oura-client.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const mockEnv = new Map<string, string>([
1010
['OURA_CLIENT_SECRET', 'test-oura-client-secret'],
1111
['OURA_WEBHOOK_SECRET', 'test-webhook-secret'],
1212
['SUPABASE_URL', 'https://test-project.supabase.co'],
13-
['SUPABASE_SERVICE_ROLE_KEY', 'test-service-role-key'],
13+
['SERVICE_ROLE_KEY', 'test-service-role-key'],
1414
]);
1515

1616
// @ts-ignore - Mock Deno global

supabase/functions/_shared/supabaseClient.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ export function createClient(): SupabaseClient {
1919
}
2020

2121
const supabaseUrl = Deno.env.get('SUPABASE_URL');
22-
const supabaseServiceRoleKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY');
22+
const supabaseServiceRoleKey = Deno.env.get('SERVICE_ROLE_KEY');
2323

2424
if (!supabaseUrl || !supabaseServiceRoleKey) {
25-
throw new Error('Missing SUPABASE_URL or SUPABASE_SERVICE_ROLE_KEY environment variables');
25+
throw new Error('Missing SUPABASE_URL or SERVICE_ROLE_KEY environment variables');
2626
}
2727

2828
supabaseClient = createSupabaseClient(supabaseUrl, supabaseServiceRoleKey, {

supabase/functions/caller-test/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ Deno.serve(withLogging('caller-test', async (req: Request, logger: Logger) => {
2222
}
2323

2424
const supabaseUrl = Deno.env.get('SUPABASE_URL');
25-
const serviceRoleKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY');
25+
const serviceRoleKey = Deno.env.get('SERVICE_ROLE_KEY');
2626

2727
if (!supabaseUrl || !serviceRoleKey) {
2828
return new Response(
2929
JSON.stringify({
30-
error: 'Missing SUPABASE_URL or SUPABASE_SERVICE_ROLE_KEY',
30+
error: 'Missing SUPABASE_URL or SERVICE_ROLE_KEY',
3131
}),
3232
{ status: 500, headers: { 'Content-Type': 'application/json' } }
3333
);

supabase/functions/fitbit-auth-start/index.standalone.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const corsHeaders = {
1515

1616
function createClient() {
1717
const supabaseUrl = Deno.env.get('SUPABASE_URL')!;
18-
const supabaseServiceRoleKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!;
18+
const supabaseServiceRoleKey = Deno.env.get('SERVICE_ROLE_KEY')!;
1919
return createSupabaseClient(supabaseUrl, supabaseServiceRoleKey, {
2020
auth: { autoRefreshToken: false, persistSession: false },
2121
});

supabase/functions/fitbit-callback/index.standalone.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { createClient as createSupabaseClient } from 'https://esm.sh/@supabase/s
88

99
function createClient() {
1010
const supabaseUrl = Deno.env.get('SUPABASE_URL')!;
11-
const supabaseServiceRoleKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!;
11+
const supabaseServiceRoleKey = Deno.env.get('SERVICE_ROLE_KEY')!;
1212
return createSupabaseClient(supabaseUrl, supabaseServiceRoleKey, {
1313
auth: { autoRefreshToken: false, persistSession: false },
1414
});
@@ -230,7 +230,7 @@ Deno.serve(async (req: Request) => {
230230

231231
// Trigger initial backfill (fire-and-forget)
232232
const supabaseUrl = Deno.env.get('SUPABASE_URL');
233-
const serviceRoleKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY');
233+
const serviceRoleKey = Deno.env.get('SERVICE_ROLE_KEY');
234234
if (supabaseUrl && serviceRoleKey) {
235235
fetch(`${supabaseUrl}/functions/v1/sync-fitbit`, {
236236
method: 'POST',

supabase/functions/fitbit-callback/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ Deno.serve(async (req: Request) => {
282282
async function triggerInitialBackfill(userId: string, deviceId: string) {
283283
try {
284284
const supabaseUrl = Deno.env.get('SUPABASE_URL');
285-
const serviceRoleKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY');
285+
const serviceRoleKey = Deno.env.get('SERVICE_ROLE_KEY');
286286

287287
if (!supabaseUrl || !serviceRoleKey) {
288288
console.error('Missing Supabase configuration for backfill trigger');

supabase/functions/fitbit-webhook/index.standalone.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { createClient as createSupabaseClient } from 'https://esm.sh/@supabase/s
88

99
function createClient() {
1010
const supabaseUrl = Deno.env.get('SUPABASE_URL')!;
11-
const supabaseServiceRoleKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!;
11+
const supabaseServiceRoleKey = Deno.env.get('SERVICE_ROLE_KEY')!;
1212
return createSupabaseClient(supabaseUrl, supabaseServiceRoleKey, {
1313
auth: { autoRefreshToken: false, persistSession: false },
1414
});
@@ -120,7 +120,7 @@ Deno.serve(async (req: Request) => {
120120

121121
// Trigger sync (fire-and-forget)
122122
const supabaseUrl = Deno.env.get('SUPABASE_URL');
123-
const serviceRoleKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY');
123+
const serviceRoleKey = Deno.env.get('SERVICE_ROLE_KEY');
124124

125125
if (supabaseUrl && serviceRoleKey) {
126126
fetch(`${supabaseUrl}/functions/v1/sync-fitbit`, {

supabase/functions/fitbit-webhook/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ async function triggerSync(
212212
): Promise<void> {
213213
try {
214214
const supabaseUrl = Deno.env.get('SUPABASE_URL');
215-
const serviceRoleKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY');
215+
const serviceRoleKey = Deno.env.get('SERVICE_ROLE_KEY');
216216

217217
if (!supabaseUrl || !serviceRoleKey) {
218218
console.error('Missing Supabase configuration for sync trigger');

supabase/functions/function-to-function-auth.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ Deno.test({
2222
name: 'BUG: Edge Function calling another Edge Function gets 401',
2323
async fn() {
2424
const supabaseUrl = Deno.env.get('SUPABASE_URL');
25-
const serviceRoleKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY');
25+
const serviceRoleKey = Deno.env.get('SERVICE_ROLE_KEY');
2626

2727
assertExists(supabaseUrl, 'SUPABASE_URL must be set');
28-
assertExists(serviceRoleKey, 'SUPABASE_SERVICE_ROLE_KEY must be set');
28+
assertExists(serviceRoleKey, 'SERVICE_ROLE_KEY must be set');
2929

3030
console.log('\n🧪 Testing function-to-function authentication...\n');
3131

@@ -92,10 +92,10 @@ Deno.test({
9292
name: 'CONTROL: Direct call to echo-test works (baseline)',
9393
async fn() {
9494
const supabaseUrl = Deno.env.get('SUPABASE_URL');
95-
const serviceRoleKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY');
95+
const serviceRoleKey = Deno.env.get('SERVICE_ROLE_KEY');
9696

9797
assertExists(supabaseUrl, 'SUPABASE_URL must be set');
98-
assertExists(serviceRoleKey, 'SUPABASE_SERVICE_ROLE_KEY must be set');
98+
assertExists(serviceRoleKey, 'SERVICE_ROLE_KEY must be set');
9999

100100
const echoUrl = `${supabaseUrl}/functions/v1/echo-test`;
101101
const response = await fetch(echoUrl, {

0 commit comments

Comments
 (0)