Security 10 min read

Your Laravel APP_KEY Is Probably on GitHub. Here Is Why That Means RCE.

GitGuardian found 260,000 exposed Laravel APP_KEYs on GitHub. With the right key, attackers can achieve remote code execution on your server in seconds. Here is how the attack works and how to protect yourself.

Matt King
Matt King
March 19, 2026
Last updated: March 19, 2026
Your Laravel APP_KEY Is Probably on GitHub. Here Is Why That Means RCE.

In a joint research effort, GitGuardian and Synacktiv analyzed publicly exposed Laravel APP_KEY values on GitHub and found the results alarming: 260,000 exposed keys, 400 validated as functional, and confirmed remote code execution on production Laravel applications.

Your APP_KEY is the single most dangerous secret in your Laravel application. Unlike a database password (which requires network access to the database), a leaked APP_KEY can be exploited remotely by anyone who can send an HTTP request to your application.

What is the APP_KEY and why does it matter?

The APP_KEY is a 32-byte symmetric encryption key defined in your .env file:

APP_KEY=base64:wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY=

Laravel uses it to encrypt:

  • Session data — including authentication tokens
  • Cookies — including the session cookie itself
  • Cache values — anything stored via the Cache facade
  • Any data processed by Crypt::encrypt()

If an attacker has your APP_KEY, they can decrypt all of the above. But the real danger is worse than decryption.

How APP_KEY leads to remote code execution

Laravel's decrypt() function does two things:

  1. Decrypts the data using the APP_KEY
  2. Automatically deserializes the decrypted data via PHP's unserialize()

Step 2 is the problem. PHP deserialization is a well-known attack vector. If an attacker can control the input to unserialize(), they can trigger "gadget chains" — sequences of existing PHP class methods that execute during deserialization and ultimately run arbitrary commands.

The attack in practice

  1. Attacker finds your APP_KEY (from GitHub, exposed .env, or other leaks)
  2. Attacker uses phpggc to generate a malicious PHP object serialization payload — phpggc catalogs 22+ RCE gadget chains across Laravel versions 5.1 through 12
  3. Attacker encrypts the payload using your APP_KEY
  4. Attacker sends the encrypted payload to your application (via a cookie, for example)
  5. Laravel decrypts the payload and calls unserialize()
  6. The gadget chain executes, giving the attacker shell access to your server

The entire attack can be automated and executed in seconds.

# Example using phpggc (for security research only)
phpggc Laravel/RCE10 system "id" -b | \
  php -r '$key = "YOUR_APP_KEY"; echo encrypt(file_get_contents("php://stdin"), $key);'

Known CVEs

This attack vector has been documented in multiple CVEs:

  • CVE-2018-15133 — the original Laravel RCE via APP_KEY
  • CVE-2024-55555 — additional deserialization vectors
  • CVE-2024-55556 — further gadget chain exploits

The scale of the problem

GitGuardian's research paints a clear picture:

Metric Number
APP_KEYs exposed on GitHub since 2018 260,000
Unique keys identified 10,000+
APP_KEY + APP_URL pairs exposed 28,000
Keys validated as still functional 400
Applications confirmed vulnerable to trivial RCE 120
Production RCE confirmed and reported 4

63% of exposures came from committed .env files. The remaining 35%+ came from configuration files, documentation, scripts, and other sources.

Perhaps most concerning: 50 keys that developers had deleted from their repositories were still valid in production. Deleting a file from a git repository does not remove it from the history. The key is still accessible to anyone who clones the repo.

Co-leaked secrets

When an APP_KEY is exposed, it rarely travels alone. GitGuardian found that 35% of exposures included other critical secrets:

  • Database credentials
  • AWS/cloud provider tokens
  • Payment gateway keys (Stripe, PayPal)
  • AI service API keys
  • SMTP credentials

A single committed .env file can compromise your entire infrastructure.

How to check if your APP_KEY is exposed

1. Search your git history

# Check if .env was ever committed
git log --all --diff-filter=A -- .env

# Search for APP_KEY in any committed file
git log --all -p -S "APP_KEY=base64:" --source

# Check if .env is in .gitignore
grep -n ".env" .gitignore

2. Check your live application

# Is your .env file publicly accessible?
curl -s -o /dev/null -w "%{http_code}" https://yourdomain.com/.env

# A 200 response means your .env (and APP_KEY) is exposed
# You want 403 or 404

3. Use automated scanning

  • GitHub Secret Scanning — enable in your repository settings (free for public repos)
  • GitGuardian — monitors for exposed secrets across GitHub
  • StackShield — checks for .env file exposure on every scan

Remediation

If your APP_KEY is exposed

Step 1: Generate a new key immediately

php artisan key:generate

Step 2: Deploy the new key to all environments

Update your .env file on every server. If you use environment variables via your hosting provider (Forge, Vapor, etc.), update it there.

Step 3: Understand the impact of rotation

Rotating your APP_KEY invalidates:

  • All active user sessions (users will be logged out)
  • All encrypted cookies
  • All data encrypted with Crypt::encrypt() using the old key
  • Cached values that were encrypted

If you store encrypted data at rest (e.g., encrypted database columns), you need to re-encrypt that data with the new key before rotating. Laravel does not handle this automatically.

Step 4: Remove the key from git history

Simply deleting .env from the repo is not enough. The key persists in git history.

# Using BFG Repo-Cleaner (recommended)
bfg --delete-files .env
git reflog expire --expire=now --all && git gc --prune=now --aggressive

# Force push to overwrite remote history
git push --force

Step 5: Rotate all co-leaked secrets

If your .env was committed, assume every secret in it is compromised. Rotate database passwords, API keys, SMTP credentials, and all third-party service tokens.

Preventing future exposure

1. Ensure .env is in .gitignore

Every Laravel project includes .env in .gitignore by default, but this can be accidentally removed or overridden:

# Verify .env is ignored
echo ".env" >> .gitignore
git rm --cached .env 2>/dev/null  # Remove if tracked

2. Use environment variables instead of .env files in production

Many hosting platforms (Forge, Vapor, Railway, Fly.io) let you set environment variables directly, so you never need a .env file on the server.

3. Enable GitHub secret scanning

Go to your repository Settings > Code security and analysis > Secret scanning and enable it. GitHub will alert you if secrets are pushed.

4. Add a pre-commit hook

# .git/hooks/pre-commit
#!/bin/sh
if git diff --cached --name-only | grep -q "\.env$"; then
    echo "ERROR: Attempting to commit .env file"
    exit 1
fi

5. Monitor your application externally

External monitoring catches .env exposure in production even when your git hygiene is perfect. Server misconfigurations, deployment errors, and web server changes can expose .env files that were never in your repository.

The lesson

Your APP_KEY is not just an encryption key. It is a remote code execution credential. Treat it with the same seriousness as your SSH private key or database root password. If it has ever been in a git repository — even briefly, even in a branch that was deleted — assume it is compromised and rotate it today.

Frequently Asked Questions

What is the Laravel APP_KEY used for?

The APP_KEY is a 32-byte symmetric encryption key that Laravel uses for encrypting cookies, session data, cache values, and any data processed by the Crypt facade. It is the single most sensitive value in your .env file. If an attacker obtains it, they can decrypt any data your application encrypted and, more critically, craft payloads that achieve remote code execution through PHP deserialization.

How does a leaked APP_KEY lead to remote code execution?

Laravel's decrypt() function automatically deserializes decrypted data. An attacker with your APP_KEY can encrypt a malicious PHP object (a "gadget chain") and send it to your application via a cookie or other encrypted input. When Laravel decrypts and deserializes the payload, the gadget chain executes arbitrary commands on your server. The phpggc tool catalogs 22+ RCE gadget chains across Laravel versions 5.1 through 12.

How do I check if my Laravel APP_KEY has been leaked?

Search GitHub for your APP_KEY value (or a portion of it). Check your git history for any commits that included your .env file: git log --all --diff-filter=A -- .env. Use GitGuardian, GitHub secret scanning, or similar tools to monitor for exposed secrets. Also check if your .env file is publicly accessible by visiting yourdomain.com/.env in a browser.

What should I do if my Laravel APP_KEY is exposed?

Immediately generate a new APP_KEY with php artisan key:generate. Deploy the new key to all environments. Invalidate all existing sessions by clearing the session store. Re-encrypt any data that was encrypted with the old key. Remove the exposed key from your git history using git filter-branch or BFG Repo-Cleaner. Do not just delete the .env file from the repository — the key remains in git history.

Does rotating my APP_KEY break anything?

Yes, rotating the APP_KEY invalidates all existing encrypted data: sessions, cookies, cached values, and any data stored using the Crypt facade. Users will be logged out, and any encrypted-at-rest data becomes unreadable. Plan for this by re-encrypting stored data before rotating, or accept the session invalidation as a necessary security measure.