PHP Support
If a PHP interpreter is installed, envGo will execute .php files server-side
instead of serving them as static text, and will pass every .env variable into
the PHP process. This lets existing PHP pages use the same secret management as
your HTML and JavaScript.
PHP support is optional. If PHP is not installed, envGo still runs — but
.php files are then served as static downloads. See
the important caveat below.
How it works
- A request resolves to a file ending in
.php - envGo looks for a PHP interpreter on
PATH - It runs
php <path>with every.envvariable added to the process environment - It also adds
REQUEST_METHOD,QUERY_STRING, andREQUEST_URI - The script’s output is returned to the browser
- The source is scanned for typos and for patterns that expose secrets
Browser → /index.php → envGo → php <path> → response │ └─ every .env variable injected into the process envRequirements
envGo looks for an interpreter in this order, using the first one found:
phpphp8php8.2php8.1php7
Install PHP if none of these resolve:
# Debian / Ubuntusudo apt install -y php
# macOS (Homebrew)brew install php
# Fedora / RHEL familysudo dnf install -y phpBasic usage
<?php// Example: check the key exists without revealing it$secret = getenv("MY_SECRET");
if (!$secret) { echo "<h1>Error: MY_SECRET not configured</h1>";} else { echo "<h1>Secret validated (value hidden)</h1>";}?>MY_SECRET=your-secret-valueenvgo run devThen open http://127.0.0.1:8080/index.php.
Directories also work: with no path, envGo tries index.html, then index.php,
then index.htm.
Accessing variables
All three styles work, because envGo places every .env variable in the process
environment:
<?php// 1. getenv()$secret = getenv("MY_SECRET");
// 2. $_ENV superglobal$secret = $_ENV["MY_SECRET"];
// 3. $_SERVER superglobal$secret = $_SERVER["MY_SECRET"];?>envGo also sets the following, so request-aware scripts work:
| Variable | Contents |
|---|---|
REQUEST_METHOD | The HTTP method, e.g. GET |
QUERY_STRING | The raw query string, e.g. foo=bar |
REQUEST_URI | The request path plus query string |
Every variable in .env is injected — there is no per-file allowlist. Any PHP
file in the served directory can read any .env variable, so treat your web root
as trusted code.
Typo detection
envGo scans the PHP source for getenv("…"), $_ENV["…"], and $_SERVER["…"]
and checks each name against .env. An unknown name triggers a red banner:
<?php $secret = getenv("MY_SECRETS"); // typo ?>envGo — PHP env typo: undefined variable MY_SECRETS not found in .env.Did you mean 'MY_SECRET'?The suggestion is the closest key by Levenshtein distance, up to a threshold of 3. The banner is injected into the response, so it only appears for the request that triggered it.
Security warning
envGo also scans for lines that both access a secret and print it to the browser.
Matching is line-based, looking for echo, print, var_dump, or print_r on
the same line as getenv, $_ENV, or $_SERVER.
<?phpecho getenv("MY_SECRET"); // DANGEROUS — triggers the bannerprint getenv("API_KEY"); // DANGEROUSvar_dump(getenv("SECRET")); // DANGEROUS?>envGo — SECURITY WARNING: getenv echoed to browser. Secrets exposed!Remove echo/print of getenv/$_ENV/$_SERVER.Safe patterns
<?php// SAFE: report only whether the value is present$secret = getenv("MY_SECRET");if ($secret) { echo "<p>Secret configured ✓</p>";} else { echo "<p>Error: Secret not configured</p>";}
// SAFE: use the value server-side, never print it$apiKey = getenv("OPENAI_API_KEY");if ($apiKey) { // make the outbound call here}
// SAFE: conditional display without the value$secret = getenv("MY_SECRET");echo "<p>Variable exists: " . ($secret ? "Yes" : "No") . "</p>";?>These checks are heuristic source scans, not a security boundary. Because matching is line-based, a secret printed across two lines, or passed through a variable, will not be flagged. Treat the banners as helpful hints, not as guarantees.
Timeout
Each PHP request has a 30-second limit, enforced with a context-aware command:
<?phpsleep(60); // killed at 30 seconds?>The fall-through caveat
You can confirm which side of the fall-through you are on by requesting the file and checking whether the browser renders HTML or offers a download.
Complete example
This is a full, working page. The variable names are illustrative — swap them for your own.
<?php$secret = getenv("MY_SECRET");$apiKey = getenv("OPENAI_API_KEY");
$errors = [];if (!$secret) $errors[] = "MY_SECRET";if (!$apiKey) $errors[] = "OPENAI_API_KEY";?><!DOCTYPE html><html><head> <title>envGo PHP Demo</title> <style> body { font-family: system-ui, sans-serif; max-width: 600px; margin: 50px auto; } .status { padding: 10px; margin: 10px 0; border-radius: 8px; } .ok { background: #d1fae5; color: #065f46; } .error { background: #fee2e2; color: #991b1b; } </style></head><body> <h1>envGo PHP Demo</h1>
<?php if (empty($errors)): ?> <div class="status ok">All environment variables configured ✓</div> <?php else: ?> <div class="status error"> Missing variables: <?php echo implode(", ", $errors); ?> </div> <?php endif; ?>
<h2>Variable Status</h2> <ul> <li>MY_SECRET: <?php echo $secret ? "✓ Set" : "✗ Missing"; ?></li> <li>OPENAI_API_KEY: <?php echo $apiKey ? "✓ Set" : "✗ Missing"; ?></li> </ul>
<p><em>Note: actual values are never displayed.</em></p></body></html>MY_SECRET=your-secret-valueOPENAI_API_KEY=sk-your-real-keyenvgo run devCustom response headers
If a script’s output begins with HTTP-style headers followed by a blank line, envGo forwards them:
<?phpheader("Content-Type: application/json");echo json_encode(["ok" => true]);?>Without a header block, the response is served as text/html; charset=utf-8.
Limitations
Be aware of all of the following:
- One process per request — each request spawns a fresh
phpprocess, so there is no in-process state carried between requests - 30-second timeout — long-running scripts are terminated
- A failed execution serves the source — see the caveat above
- All variables are injected — there is no per-file allowlist
- Requests are not recorded in the dashboard — only
/proxyand/api/<name>calls appear in history, so PHP traffic is invisible there - Heuristic scanning only — the typo and exposure checks are line-based source scans, not taint tracking
There is no restriction on PHP extensions. envGo simply runs the interpreter
found on PATH, so every extension that installation provides is available.
Common issues
| Symptom | Cause | Fix |
|---|---|---|
Browser downloads the .php file | No interpreter found, or the script failed | Install PHP and check php -v |
| Page hangs for 30 seconds then downloads | Script exceeded the timeout | Reduce work per request |
| Red typo banner | A key in the script is not in .env | Fix the name or add the key |
| Red security banner | A secret is printed to the browser | Stop echoing the value |
| Variable is empty | Key missing from .env, or .env not loaded | Check the startup log for the variable count |
Best practices
- Validate, never print — report presence, not value
- Confirm PHP is installed in every environment where
.phpfiles are served - Keep the web root free of secrets — remember the fall-through
- Watch the startup log — it tells you how many variables loaded
- Prefer
/proxyor/api/<name>for new integrations; PHP support exists mainly to modernise existing pages
Next steps
- Security Model — the PHP containment layer
- Environment Variables — the
.envformat - Threat Model — known limitations