Security Best Practices for God's Eye View: Protecting API Keys and Hardening Your Instance

The God's Eye View security model keeps all secret-bearing API keys server-side, exposes only intentionally client-side tokens with strict restrictions, and hardens the Vite dev proxy with request validation, size caps, and per-IP rate limiting.

God's Eye View (GEV) is a local-first web client that visualizes multiple public-data layers through third-party APIs. Because the application communicates with numerous external services—OpenAI, Google Maps, Cesium Ion, and OpenStreetMap data feeds—its security best practices focus on credential isolation, proxy hardening, and controlled network exposure. This guide walks through the safeguards implemented in the bilawalsidhu/gods-eye-view repository and how to apply them in your deployment.


Core Security Principle: Secrets Stay Server-Side

The foundational rule is documented in [SECURITY.md](https://github.com/bilawalsidhu/gods-eye-view/blob/main/SECURITY.md#L14-L31):

"The golden rule: secret-bearing API keys stay on the server side."

The GEV architecture enforces this through token tiering:

Token Type Examples Exposure Lifetime
Server-side secrets OPENAI_API_KEY, PINOKIO_ENV_FILE Never reaches browser Persistent (stored in .env or Keychain)
Short-lived session tokens OpenAI Realtime ephemeral tokens Returned via authenticated /api/realtime/token Minutes
Public client tokens GOOGLE_MAPS_API_KEY, CESIUM_ION_TOKEN Visible in import.meta.env Long-lived, but restricted by provider

Only two keys are deliberately client-side—Google Maps and Cesium Ion—and both must be restricted in their provider consoles through referrer allowlists and read-only asset scopes.


Secure Key Management with the POWER UP Panel

GEV provides a built-in UI for adding provider credentials without manual file editing. The POWER UP panel (implemented in src/keySetupCore.mjs) handles key persistence securely:

  1. User enters keys through the web interface
  2. Values are written to .env (git-ignored) or macOS Keychain
  3. The development server auto-restarts to load new credentials
// Example: Adding keys via the POWER UP flow
// In the running app, click the "POWER UP" chip → Provider Settings
// Paste your Cesium Ion token (public read-only) and save.
// The panel writes to .env and triggers a Vite restart.

Critical: Never commit .env files. The repository includes .env.example as a template without real values.


Hardening the Development Proxy

All external API traffic routes through Vite's dev server, defined in [vite.config.js](https://github.com/bilawalsidhu/gods-eye-view/blob/main/vite.config.js). The proxy implements multiple defense layers:

Request Validation and Size Limits

// vite.config.js – Overpass API protection (excerpt)
// Lines 15-30: Validates URLs, caps request/response sizes
const OVERPASS_MAX_BODY_BYTES = 1024 * 1024;      // 1 MB
const OVERPASS_MAX_RESPONSE_BYTES = 10 * 1024 * 1024; // 10 MB

The proxy rejects arbitrary URLs and enforces per-endpoint size limits to prevent abuse and memory exhaustion.

Secret-Only Proxy Logic

// vite.config.js – Lines 44-55
// Client keys are explicitly whitelisted; secrets remain server-bound
function clientKey(envName) {
  return (name) => name === envName ? process.env[envName] : undefined;
}

This ensures that even if the client attempts to access OPENAI_API_KEY, the proxy returns undefined—the key never enters the browser bundle.

Per-IP Rate Limiting for Cost-Bearing Endpoints

Lines 84-101 of [vite.config.js](https://github.com/bilawalsidhu/gods-eye-view/blob/main/vite.config.js#L84-L101) implement opt-in throttling for paid APIs:


# Enable per-IP rate limiting in .env

echo "GEV_RATELIMIT_OPENAI_PER_MIN=30" >> .env
echo "GEV_RATELIMIT_GOOGLE_PER_MIN=60" >> .env

When limits are exceeded, the proxy returns HTTP 429 without forwarding the request to the provider, protecting quota and budget.


Restricting Client-Side API Keys

Since Google Maps and Cesium Ion tokens are visible in browser DevTools, provider-side restrictions are mandatory:

Google Maps API Key


# Google Cloud Console → Credentials → API Key

# Application restrictions: HTTP referrers (e.g., https://localhost:4173/*)

# API restrictions: Maps JavaScript API, Places API, Tile API

echo "GOOGLE_MAPS_API_KEY=AIzaSy...restricted" >> .env

Cesium Ion Token

  • Create a public token with assets:read scope only
  • Apply URL restrictions in the Cesium dashboard
  • Never use your default (private) token for client applications

Network Exposure: Localhost by Default

By design, GEV binds to localhost (127.0.0.1). If you intentionally expose the server on a LAN:

HOST=0.0.0.0 npm run dev

Critical warning from README.md#L54-L63: Every device on your network can consume your API quotas. Always pair LAN exposure with:

  • Per-IP rate limits (GEV_RATELIMIT_* variables)
  • Firewall rules at the OS level
  • Regular quota monitoring in provider consoles

Redacted Logging and Audit Trails

Debug logs are persisted to .gev-logs/ with automatic redaction of sensitive data:

Redacted Field Reason
API keys Prevent credential leakage in log files
Bearer tokens Short-lived but still sensitive
Image data Privacy and size reduction

See SECURITY.md#L52-L53 for the redaction policy.


Data Provenance and Compliance

All visualization layers source from public, documented APIs with proper attribution. The [DATA_SOURCES.md](https://github.com/bilawalsidhu/gods-eye-view/blob/main/DATA_SOURCES.md) file maps each layer to its official documentation and terms of service. Respect these policies when scaling usage—GEV's internal throttles are not billing caps.


Verification: Confirming Secrets Stay Hidden

You can verify the client-side exposure model by inspecting import.meta.env in your browser console:

// In src/main.js or browser DevTools:
import.meta.env.GOOGLE_MAPS_API_KEY   // ✓ Defined (public, restricted)
import.meta.env.CESIUM_ION_TOKEN      // ✓ Defined (public, restricted)
import.meta.env.OPENAI_API_KEY         // ✗ Undefined (never exposed)

// OpenAI features work via ephemeral token from /api/realtime/token

If OPENAI_API_KEY appears anywhere in the client bundle, your configuration is compromised.


Summary

  • Keep secrets server-side—use .env or Keychain, never commit credentials
  • Restrict the two client-side keys (Google Maps, Cesium Ion) in provider consoles
  • Run behind the built-in proxy—it validates URLs, caps sizes, sanitizes errors, and rate-limits
  • Use POWER UP panel for secure key entry with automatic server restart
  • Limit network exposure—localhost default; LAN requires explicit rate limiting
  • Monitor quotas externally—GEV throttles protect against abuse, not billing

Frequently Asked Questions

How does God's Eye View protect my OpenAI API key?

Your OPENAI_API_KEY never reaches the browser. The server holds it in environment variables and exchanges it for short-lived, scoped session tokens via the /api/realtime/token endpoint. Clients receive only ephemeral tokens valid for minutes, not your permanent credential. This is enforced by the proxy logic in vite.config.js#L44-L55.

Can I safely share my God's Eye View instance with my team?

Only with precautions. Binding to 0.0.0.0 exposes your API quotas to all LAN devices. Before sharing, set per-IP rate limits (GEV_RATELIMIT_OPENAI_PER_MIN, GEV_RATELIMIT_GOOGLE_PER_MIN), monitor usage in provider dashboards, and consider running behind a reverse proxy with additional authentication. See [README.md](https://github.com/bilawalsidhu/gods-eye-view/blob/main/README.md#L54-L63) for the official guidance.

Why are Google Maps and Cesium Ion tokens visible in the client?

These services require browser-side initialization—Google Maps JavaScript loads directly from Google's servers, and Cesium renders 3D tiles in WebGL. The security model shifts to provider-side restrictions: referrer allowlists, URL restrictions, and minimal scopes (assets:read for Cesium). Treat these as capable but bounded credentials, not secrets.

What happens if I exceed the per-IP rate limit?

The Vite proxy returns HTTP 429 Too Many Requests immediately, without forwarding to the upstream API. This protects your quota but may interrupt functionality for that IP. Adjust limits in .env based on your expected usage pattern, or disable throttling entirely (not recommended for shared instances).

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 →