Server-Side Supabase Service Role Key Security in Awesome-GPT-Image-2 Repository

The Awesome-GPT-Image-2 repository protects the SUPABASE_SERVICE_ROLE_KEY by restricting it strictly to server-side environments and never exposing it to client-side code.

This open-source web gallery project uses the GPT-Image-2 API for AI image generation while implementing defense-in-depth security for its Supabase backend credentials. The service role key—a credential with elevated database privileges—follows a rigorous server-only deployment pattern that prevents credential leakage and unauthorized access.

What Is the Service Role Key and Why It Needs Protection

The service role key is a Supabase JWT that bypasses Row Level Security (RLS) policies, granting full database access. Unlike the anonymous or authenticated client keys, this credential can read, write, and delete any data in the Supabase project.

In the Awesome-GPT-Image-2 architecture, this key enables privileged operations such as:

  • Credit balance adjustments per user
  • Membership billing state mutations
  • Administrative data corrections

Exposing this key to browsers or mobile clients would allow any user to escalate privileges and compromise the entire database.

Server-Side Only Implementation Pattern

The repository enforces a strict separation between client and server code. All files that reference SUPABASE_SERVICE_ROLE_KEY live in server-only paths that build tools never bundle for the browser.

Supabase Helper Module

The centralized database client in api/_lib/supabase.js reads the key exclusively from process.env:

// api/_lib/supabase.js
import { createClient } from '@supabase/supabase-js'

// Line 7: Server-only environment variable access
const serviceRoleKey = process.env.SUPABASE_SERVICE_ROLE_KEY

export const supabase = createClient(
  process.env.VITE_SUPABASE_URL,
  serviceRoleKey
)

This module is imported only by server routes—never by React components or browser code. The build system treats api/_lib/ as a server-only boundary.

Vite Proxy Validation

The local development server at scripts/vite-local-api.mjs adds a runtime guard that fails fast if the key is missing:

// scripts/vite-local-api.mjs
// Line 27: Environment validation before server starts
if (!process.env.SUPABASE_SERVICE_ROLE_KEY) {
  throw new Error('Missing SUPABASE_SERVICE_ROLE_KEY')
}

// Subsequent proxy setup uses the key for authenticated GPT-Image-2 API calls

This validation ensures developers cannot accidentally start the server without proper credentials configured.

Environment Variable Security Architecture

The project follows platform-native secret management rather than file-based configuration in production.

Vercel Deployment Pattern

As documented in README.md (lines 318-344), production deployments use Vercel's encrypted environment variable system:

  1. Dashboard configuration — Secrets are entered through Vercel's UI, not committed to git
  2. Runtime injection — Values populate process.env only on the server compute instances
  3. Zero client exposure — Build logs and edge functions never receive the raw key

Local Development Safeguards

The .env.example file (line 6) includes an empty placeholder:

SUPABASE_SERVICE_ROLE_KEY=

This pattern reminds developers to:

  • Copy the file to .env.local (gitignored by default)
  • Populate secrets manually from Supabase dashboard
  • Never hardcode values or commit the local file

Client-Side Isolation Guarantees

The repository's build architecture provides multiple enforcement layers:

Layer Mechanism File
Import constraints Server-only modules tree-shaken from browser bundle api/_lib/supabase.js
Runtime guards Explicit process.env checks fail in browser context scripts/vite-local-api.mjs
Build tooling Vite server-proxy separation prevents client bundling vite.config.ts patterns
CI/CD validation .env.example linting ensures no defaults checked in GitHub Actions workflows

The style-library skill demonstrates this separation clearly. The client-side agent tool at agents/skills/gpt-image-2-style-library/SKILL.md operates entirely on public JSON data from data/style-library.json—no Supabase credentials required:


# Client-only installation - zero database access

npm install -g gpt-image-2-style-library
gpt-image-2-style-library install all

Threat Mitigation Summary

The repository's SUPABASE_SERVICE_ROLE_KEY handling mitigates these specific attack vectors:

  • Source control leakage — No production values in repository; placeholder-only .env.example
  • Client bundle extraction — Server-only code paths excluded from browser builds
  • Build-time exposure — Vercel injects at runtime, not during static generation
  • Developer error — Runtime validation throws before server accepts traffic

Summary

  • Server-only scope: All SUPABASE_SERVICE_ROLE_KEY references exist in api/ and scripts/ directories that never reach the browser
  • Environment isolation: Production uses platform secret management (Vercel) rather than file-based configuration
  • Fail-fast validation: Missing credentials trigger immediate errors at server startup
  • Clear documentation: README.md and .env.example establish security expectations for contributors
  • Functional separation: Client features like the style-library skill operate without privileged database access

Frequently Asked Questions

What happens if SUPABASE_SERVICE_ROLE_KEY leaks to the client?

A leaked service role key grants full database access bypassing all RLS policies. Attackers could read any user's data, modify credit balances, or delete entire tables. The Awesome-GPT-Image-2 repository prevents this through server-only module boundaries and build-time tree shaking that excludes api/_lib/supabase.js from client bundles.

How does the repository validate the key is server-side only?

The scripts/vite-local-api.mjs file contains an explicit check at line 27 that throws if process.env.SUPABASE_SERVICE_ROLE_KEY is undefined. Since browser environments lack process.env entirely, any accidental client import would fail immediately. Additionally, Vite's architecture treats api/ routes as server-only endpoints.

Can I use the style-library skill without Supabase credentials?

Yes. The gpt-image-2-style-library command-line tool reads exclusively from data/style-library.json, a public JSON file. No database connection or authentication is required for style installation and local usage. Supabase credentials are only needed for the web gallery's credit and membership features.

Where should I store SUPABASE_SERVICE_ROLE_KEY in production?

Store it in your hosting platform's encrypted environment variable system. For Vercel deployments, use Settings → Environment Variables in the dashboard, marking it for Production/Preview/Development scopes as needed. Never commit the value to .env.production or any file tracked by git.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →