🧠 Securing Git Repositories from Exposed .env Files using GitHub Apps + Render Hosting
🔍 Overview
Sensitive environment files (like .env, .env.production, .env.local) often contain credentials, API keys, or database passwords. Accidentally committing them to a public or shared repository can cause immediate credential leaks and security incidents.
To prevent this, we built EnvGuard, a custom GitHub App that automatically scans repositories for .env file exposure and blocks merges or pushes that contain sensitive files.
EnvGuard is deployed on Render.com as a Node.js service and uses the GitHub App API to perform automatic Check Runs and Issue creation when .env files are detected.
⚙️ System Architecture
┌────────────┐ ┌──────────────────────┐
│ GitHub │─────▶│ EnvGuard (Render) │
│ Repository │ push │ Node.js Webhook App │
└────────────┘ └──────────────────────┘
│ │
│ Webhook Event │ Check Run + Issue via GitHub API
▼ ▼
❌ PR Check Fails 🧾 Issue Created Automatically
Components
| Component | Purpose |
|---|---|
| GitHub App (EnvGuard) | Receives push and pull_request webhooks |
| Render Deployment | Hosts the webhook receiver securely |
| GitHub Checks API | Reports “Env Exposure Check” results |
| GitHub Issues API | Notifies maintainers of sensitive files |
| Branch Protection Rules | Blocks merges when the check fails |
🧩 Key Features
✅ Detects committed .env files in real-time
✅ Ignores .env.example and safe template files
✅ Automatically creates GitHub Issues alerting maintainers
✅ Fails Check Runs (“Env Exposure Check”) to block merges
✅ Integrates with GitHub Branch Protection Rules
✅ 100% self-hosted — no third-party dependency
☁️ Deployment Platform
Platform: Render.com
Runtime: Node.js v22
Type: Web Service
Framework: Express.js
Environment Variables:
| Key | Description |
|---|---|
GITHUB_APP_ID | GitHub App ID |
GITHUB_WEBHOOK_SECRET | Webhook secret configured in GitHub App |
GITHUB_PRIVATE_KEY | PEM content of GitHub App private key |
PORT | (optional) Render service port, defaults to 3000 |
🧱 Setup Guide
1️⃣ Create the GitHub App
- Go to GitHub Developer Settings → New GitHub App
- Fill in:
Field Example App Name Cloudmateria EnvGuard Homepage URL https://github-envguard.onrender.comCallback URL https://github-envguard.onrender.com/auth(required, dummy)Webhook URL https://github-envguard.onrender.com/github/webhookWebhook Secret (generate random strong string) - Under Permissions, set:
- ✅ Checks → Read & Write
- ✅ Issues → Read & Write
- ✅ Contents → Read-only
- ✅ Pull Requests → Read-only
- ✅ Metadata → Read-only
- Subscribe to events:
pushpull_request
- Click Create GitHub App and download the
.pemfile.
2️⃣ Deploy the App on Render
- Push your Node.js EnvGuard code to GitHub (without
.pemor.env) - On Render, click New → Web Service
- Connect your GitHub repo
- Set:
- Build Command:
npm install - Start Command:
node server.js
- Build Command:
- Add environment variables in Render Dashboard → Environment:env
GITHUB_APP_ID=123456 GITHUB_WEBHOOK_SECRET=your_secret GITHUB_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nMIIEv...\n-----END PRIVATE KEY-----" PORT=3000 - Click Deploy
Render will assign a public URL, e.g.https://github-envguard.onrender.com
3️⃣ Install the App on Your Repository
- Visit your GitHub App page → click Install App
- Choose:
- “Only select repositories”
- Select the repo(s) you want to protect
- Click Install
🧪 Testing the App
A. Push a .env File
echo "API_KEY=12345" > .env
git add .env
git commit -m "test: accidentally commit .env"
git push
🔍 Expected Result:
- The app detects
.envfiles. - ❌ “Env Exposure Check” fails in the Checks tab.
- 🧾 A GitHub Issue is created automatically.
B. Push .env.example
echo "API_KEY=demo" > .env.example
git add .env.example
git commit -m "add safe env example"
git push
✅ No issue or failure — .env.example is ignored.
🔒 Enforcing Protection via Branch Rules
To block merges that include .env files:
- Go to your repository → Settings → Branches
- Add rule for
main - Enable:
- ✅ “Require status checks to pass before merging”
- Select:
Env Exposure Check - Save changes
Now, merges to main will be blocked until .env files are removed.
⚙️ Troubleshooting
| Problem | Cause | Fix |
|---|---|---|
| Push rejected: “Required status check not found” | Branch rule references wrong check name | Edit branch protection → use Env Exposure Check |
| “Invalid signature” in logs | Webhook secret mismatch | Ensure Render’s GITHUB_WEBHOOK_SECRET matches the App settings |
| Issue not created | Missing Issues permission | Update App permissions → Issues → Read & Write |
| App not triggered | Not installed on that repo | Install App → “Only select repositories” |
| App deployed but inactive | Wrong Webhook URL | Ensure full /github/webhook endpoint in GitHub App settings |
🧾 Example Console Logs (Render)
✅ EnvGuard is running successfully on Render
🚨 Found exposed .env file(s): [ '.env' ]
📋 Issue created in docker-compose-collections
🧠 Security Practices
| Practice | Description |
|---|---|
| Do not commit .pem files | Always add github-app.pem to .gitignore |
| Use environment variables | Store all secrets in Render environment configuration |
| Rotate keys periodically | Regenerate GitHub App private key every 6–12 months |
| Restrict permissions | Only grant minimal permissions (Checks, Issues, Contents) |
| Monitor Render logs | Detect failed webhook deliveries early |
🧩 Example .gitignore
# Secrets and keys
.env
*.pem
# Dependencies
node_modules/
✅ Summary
| Stage | Action |
|---|---|
| 1 | Create GitHub App and configure permissions |
| 2 | Deploy Node.js webhook handler on Render |
| 3 | Add App to target repositories |
| 4 | Enable branch protection for Env Exposure Check |
| 5 | Test by committing .env and .env.example |
| 6 | Monitor Render logs and GitHub Issues for alerts |
📎 References
🏁 Conclusion
With EnvGuard, any accidental exposure of environment variables in your repositories is automatically caught before merging — keeping your infrastructure credentials secure without manual review.
This automation combines GitHub Apps, webhooks, and Render serverless hosting to provide a reliable, low-cost, and scalable secret-protection layer for any organization.