# How God's Eye View Protects Sensitive API Keys Using Vite Middleware: A Defense-in-Depth Guide

> Learn how God's Eye View protects API keys with Vite middleware. Discover server-side credential management and secure browser key exposure for robust defense-in-depth.

- Repository: [Bilawal Sidhu/gods-eye-view](https://github.com/bilawalsidhu/gods-eye-view)
- Tags: how-to-guide
- Published: 2026-09-11

---

**God's Eye View stores all external-service credentials in a server-side environment snapshot created at boot time, exposes only two intentionally public keys to the browser via Vite's `define` injection, and proxies all private API requests through Node.js middleware that attaches credentials on the server side.**

God's Eye View is an open-source geospatial visualization project that aggregates data from OpenSky Network, Overpass API, and other providers. Because these integrations require paid API credentials, the application must prevent secret leakage to the client bundle while still enabling rich frontend functionality. According to the bilawalsidhu/gods-eye-view source code, the project achieves this through a layered security model combining Vite's `configureServer` hook, a strict key-registry policy, and hardened environment-file management.

## Boot-Time Environment Isolation

At startup, Vite loads environment variables via `loadEnv` before any middleware executes. The configuration in [`vite.config.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/vite.config.js) immediately snapshots these values into a constant called `PROVIDER_ENV_AT_BOOT` (lines 98–101). This snapshot serves as the single source of truth for all server-side credential retrieval throughout the application lifecycle.

By capturing the environment at boot time, the application decouples runtime credential access from `process.env`, preventing leakage through accidental logging or subprocess inheritance. All subsequent proxy middleware references this immutable snapshot rather than the mutable global environment.

## The Key Registry and Client-Exposure Policy

The `src/keySetupCore.mjs` file maintains a centralized registry of every supported API key (lines 30–80). Each entry includes metadata such as the required environment variable names, provider URLs, and a critical `clientExposed` boolean flag.

Only two keys carry `clientExposed: true`: the Google Maps API key and the Cesium Ion token. These are public-facing identifiers intended for client-side map rendering, not secrets. All other credentials—such as those for OpenSky, Overpass, and radio APIs—strictly remain server-side.

```javascript
export const KEY_SETUP_KEYS = Object.freeze([
  {
    id: 'google-maps',
    title: 'GOOGLE MAPS',
    unlocks: 'The photorealistic 3D planet + place search',
    getUrl: 'https://developers.google.com/maps/documentation/tile/get-api-key',
    envVars: Object.freeze(['GOOGLE_MAPS_API_KEY']),
    tier: 'metered',
    clientExposed: true, // Only these keys reach the browser
  },
  // Sensitive keys lack clientExposed or set it to false
]);

```

## Request Validation and CSRF Protection

Before any proxy middleware handles a request, it must pass the `admitKeySetupRequest` gate implemented in `src/keySetupCore.mjs` (lines 89–155). This function enforces three strict validation rules:

- **Loopback enforcement**: The request must originate from `127.0.0.1` or `::1`.
- **Origin validation**: The `Origin` header must exactly match the local development URL.
- **Proxy header rejection**: Any request carrying `Forwarded`, `X-Forwarded-*`, or similar headers is immediately rejected.

This prevents external attackers from exploiting the proxy endpoints via CSRF or header-based routing attacks. If validation fails, the middleware returns a 403 status before touching any credentials.

## Server-Side Proxy Middleware Architecture

Vite's `configureServer` hook registers multiple Connect middlewares in [`vite.config.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/vite.config.js) (lines 340–460) to handle sensitive API routes such as `/api/opensky`, `/api/overpass`, and `/api/radio`. Instead of exposing raw keys to the browser, the browser calls these local endpoints, and the server attaches the credential to the outbound request.

```javascript
server: {
  middlewareMode: true,
  configureServer(server) {
    server.middlewares.use('/api/opensky', async (req, res, next) => {
      // 1. Verify request origin using hardened gate
      const gate = admitKeySetupRequest({ 
        method: req.method, 
        remoteAddress: req.socket.remoteAddress, 
        hostHeader: req.headers.host, 
        protocol: `${req.protocol}:`, 
        origin: req.headers.origin, 
        contentType: req.headers['content-type'], 
        proxyHeaders: req.headers, 
        env: process.env 
      });
      
      if (!gate.ok) {
        return res.writeHead(gate.status, { 'Content-Type': 'application/json' })
          .end(JSON.stringify({ error: gate.error }));
      }

      // 2. Retrieve credential from boot-time snapshot
      const token = PROVIDER_ENV_AT_BOOT.OPENSKY_CLIENT_ID;
      const upstream = `https://opensky-network.org/api/...`;
      
      // 3. Attach credential on the server side
      const response = await fetch(upstream, { 
        headers: { Authorization: `Bearer ${token}` } 
      });

      // 4. Stream sanitized response to client
      const body = await readResponseJsonCapped(response, 2 * 1024 * 1024);
      res.setHeader('Content-Type', 'application/json');
      res.end(JSON.stringify(body));
    });
  },
}

```

Because the `fetch` call executes within the Node.js process, the raw `token` never traverses the client-side network. The browser receives only the API response payload, not the authentication header.

## Safe Client-Side Key Injection via Vite Define

For the two keys marked `clientExposed`, Vite injects values directly into the client bundle at build time using the `define` configuration option (lines 720–740 in [`vite.config.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/vite.config.js)). This occurs after `loadEnv` parses the `.env` file, ensuring the values are compiled into the bundle rather than served dynamically.

```javascript
export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd());
  return {
    define: {
      'import.meta.env.GOOGLE_MAPS_API_KEY': JSON.stringify(env.GOOGLE_MAPS_API_KEY || ''),
      'import.meta.env.CESIUM_ION_TOKEN': JSON.stringify(env.CESIUM_ION_TOKEN || ''),
    },
  };
});

```

This approach prevents the client from re-reading environment variables at runtime and ensures that only the intended public keys are embedded in the `import.meta.env` object accessible to the frontend code.

## Hardened .env File Management

When users add or update keys through the UI, the `upsertDotenvValues` function in `src/keySetupCore.mjs` (lines 83–118) safely modifies the `.env` file without exposing credentials to logs or executing shell metacharacters. The function specifically rejects values containing `#`, `$`, `"`, `'`, or backtick characters to prevent injection attacks against the shell or `dotenv` parser.

The function preserves existing file structure, comments out removed keys rather than deleting them, and appends new entries under a standardized header. This ensures the `.env` file remains parseable and does not accumulate dangerous characters that could alter how Node.js interprets the environment on subsequent boots.

## Summary

God's Eye View implements a comprehensive security strategy for API key management:

- **Boot-time snapshots** isolate credentials in `PROVIDER_ENV_AT_BOOT`, preventing runtime environment manipulation.
- **Registry-based exposure control** via `clientExposed` flags ensures only public map tiles and terrain tokens reach the browser.
- **Strict request validation** through `admitKeySetupRequest` blocks CSRF, proxy header attacks, and remote access attempts.
- **Server-side proxy middleware** attaches sensitive credentials to outbound requests within the Node.js process, keeping secrets off the client network.
- **Build-time injection** via Vite's `define` option securely embeds the two public keys into the bundle.
- **Sanitized file writes** through `upsertDotenvValues` prevent shell injection and maintain `.env` integrity.

## Frequently Asked Questions

### How does the application prevent external attackers from accessing the proxy endpoints?

The `admitKeySetupRequest` function in `src/keySetupCore.mjs` enforces loopback-only access and rejects any request containing proxy-related headers like `X-Forwarded-For`. It also validates that the `Origin` header matches the exact local development URL. These checks ensure that only the local browser instance can reach the proxy middleware, effectively blocking remote CSRF attempts.

### Which API keys are exposed to the browser and why?

Only the **Google Maps API key** and the **Cesium Ion token** are exposed to the browser. These are explicitly marked with `clientExposed: true` in the key registry because they are public-facing identifiers required for client-side map rendering and 3D terrain visualization. All other credentials—including those for OpenSky, Overpass, and radio APIs—remain strictly server-side and are accessed only through the proxy middleware.

### Can I safely add new API keys through the application's UI?

Yes. The `upsertDotenvValues` function safely edits the `.env` file without logging sensitive values or executing shell metacharacters. It sanitizes input by rejecting characters such as `#`, `$`, quotes, and backticks that could be interpreted by the shell or modify the `dotenv` parsing logic. The function also preserves the existing file structure and comments out removed keys rather than deleting them, maintaining a clean audit trail.

### What prevents the proxy middleware from leaking credentials in server logs?

The proxy middleware retrieves credentials exclusively from the `PROVIDER_ENV_AT_BOOT` snapshot created during initialization. By design, the code never logs these values or assigns them to variables that could be captured in stack traces. Additionally, the middleware attaches credentials directly to the outbound `fetch` request headers within the Node.js process, ensuring the raw values never appear in client-side network logs, browser DevTools, or server access logs that might record URL parameters or request bodies.