How God's Eye View Protects Sensitive API Keys Using Vite Middleware: A Defense-in-Depth Guide
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 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.
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.1or::1. - Origin validation: The
Originheader 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 (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.
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). This occurs after loadEnv parses the .env file, ensuring the values are compiled into the bundle rather than served dynamically.
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
clientExposedflags ensures only public map tiles and terrain tokens reach the browser. - Strict request validation through
admitKeySetupRequestblocks 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
defineoption securely embeds the two public keys into the bundle. - Sanitized file writes through
upsertDotenvValuesprevent shell injection and maintain.envintegrity.
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.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →