PHP2ShellCVE-2026-109618, CVE-2026-109619: critical RCE, exploited in the wild.Read the advisory
Crypto & Solana

If PHP touched your keys, assume they leaked.

PHP2Shell gives an unauthenticated attacker code execution as your web worker, and one of the two bugs can also read freed worker memory. For a Solana dApp, trading dashboard, NFT mint or exchange tool running PHP, every secret that process could reach is now in scope: hot-wallet keys, RPC provider keys, exchange API secrets, and any mnemonic in the environment.

Patch first, then treat keys as compromised.
Upgrading stops new break-ins. It does not un-leak a secret that was already readable by a vulnerable worker. If your PHP tier could read a signing key or API secret, rotate it.

Blast radius: why crypto teams are exposed

PHP2Shell is two critical (CVSS 9.2), unauthenticated remote-code-execution bugs in the PHP engine itself, fixed on 21 October 2026 and exploited in the wild before the patch shipped. They hit any web-facing PHP worker, whatever framework sits on top.

Remote code execution via out-of-memory state corruption

Confirmed impact: unauthenticated remote code execution as the web worker account.

CVE-2026-109618 · GHSA-w8hw-w9fx-j79w · CVSS 9.2

Remote code execution via stale request state (use-after-free)

Confirmed impact: unauthenticated memory disclosure and remote code execution as the web worker account.

CVE-2026-109619 · GHSA-6wmf-4rv5-p3rp · CVSS 9.2

Where the secret inventory comes from, not the advisory.

The advisories describe the impact as code execution and memory disclosure as the web worker. They do not publish a list of what secrets exist on your box; that inventory is yours. The rule of thumb below is ours: if the PHP process could read it, an attacker running as that process could read it too.

Hot-wallet signing keys
Any Solana keypair a PHP process loads to sign transfers, mints or trades.
Server-side agent / bot keys
Non-custodial automation that signs on its own: market makers, auto-claimers, mint crons.
RPC provider keys
Helius, QuickNode, Alchemy, Triton, Ankr and similar URLs with an embedded API key.
Exchange API secrets
CEX keys and secrets used by trading dashboards and treasury tooling.
Mnemonics / seed phrases in env
A BIP39 phrase in an .env or config recovers an entire wallet tree.
Session tokens & app secrets
Anything the worker reads to authenticate users or sign cookies.

Sources:php.net release archive and security advisory (2026)GHSA-w8hw-w9fx-j79wGHSA-6wmf-4rv5-p3rp

Incident response: what to do now, in order

Work top to bottom. Steps 1 and 2 stop the bleeding; step 3 assumes the keys already leaked; steps 4 and 5 confirm and contain. Tick items off as you go; the list is stored only in this browser.

  1. 1

    Patch PHP and confirm every SAPI is fixed

    Upgrade to the fixed release for your branch (8.5.12 / 8.4.27 / 8.3.36 / 8.2.35). PHP 8.1 and older get no official fix: move off them.

    Platform-by-platform fix playbooks

  2. 2

    Restart every worker

    An upgrade only protects processes started after it. Restart PHP-FPM, Apache mod_php, FrankenPHP, LiteSpeed lsphp and any long-running CLI workers so none still run the old build.

  3. 3

    Assume key compromise: rotate and move funds

    If a vulnerable worker could read a secret, treat it as leaked. Do this before you have proof of a breach, not after.

    • Move funds from any hot wallet whose key the server held to a freshly generated wallet, and retire the old keypair.
    • Check every wallet you keep for token delegates (approvals) you did not set up, and revoke them from the owner wallet.
    • Rotate RPC provider keys and every exchange API key and secret.
    • Invalidate active sessions and rotate app secrets (session keys, signing keys, webhook secrets).
    • Rotate any mnemonic that lived in an environment file or config.
  4. 4

    Scan the codebase for keys that never belonged there

    Find committed keypairs, seed phrases and provider keys so you know exactly what to rotate and where it leaked from.

    Use the exposed-key scanner below (local, nothing uploaded), or phpshield scan on the host

  5. 5

    Monitor on-chain

    Watch the wallets you believe were exposed for unexpected movement, and keep watching after you rotate.

    Turn on Watch below, list token delegations, or run phpshield wallet ADDRESS --watch --webhook URL on a server

Local scanner: find keys that should never have been on the server

Drop a .env, a keypair file, or a whole repo folder. PHPShield finds committed Solana keypairs, BIP39 seed phrases, and RPC / exchange API keys. Keypairs show the public address so you know which wallet to rotate; every secret itself stays masked.

Everything runs in your browser.
Files are read with the local File API and scanned on this page. Nothing you drop is uploaded, logged, or sent anywhere. Reload the page and it is gone.

Drop .env files, keypair JSON, or source files here, or click to choose

Read locally in this tab. Nothing is uploaded.

Scans for exposed private keys, Solana keypairs and BIP39 seed phrases. Secrets are masked before anything is shown; only the public wallet address is displayed, so you know which wallet to rotate. Everything runs in your browser; nothing is uploaded.

Masked findings appear here.

Read-only check: has a possibly-compromised wallet moved?

Enter a Solana address to list its most recent transactions straight from an RPC node, then turn on Watch to keep checking every 60 seconds while this tab is open. Each new transaction is marked when the wallet itself signed it; that needs the private key, so a signature you did not make means someone else has it. This is a read-only lookup (getSignaturesForAddress, getParsedTransactions). PHPShield never builds, signs or sends a transaction.

A notification is raised while watching when a new transaction appears.

The default is PublicNode's free endpoint, which answers browser requests but keeps only the last few days of history. For older activity, paste your own RPC URL or run phpshield wallet ADDRESS. api.mainnet-beta.solana.com refuses requests from browsers.

from a server or cron, with alerts
phpshield wallet <ADDRESS> --watch --interval 60s \
  --webhook "$SLACK_WEBHOOK_URL" --webhook-format slack
Recent transactions appear here, each explained: what moved, to whom and through which program. Only rows this wallet signed can mean a leaked key.

Read-only check: can someone else spend your tokens?

A token delegate (an approval) can move up to an approved amount out of a token account without the owner signing. Enter a wallet address to list every spl-token and Token-2022 account that still has one. This only reads (getTokenAccountsByOwner); revoking is done from your own wallet.

Why this needs your own RPC URL

The free public endpoints refuse this lookup from a browser: api.mainnet-beta.solana.com blocks every browser request, and PublicNode blocks getTokenAccountsByOwner. Use the RPC URL from your provider or your own node. No RPC URL? phpshield delegates ADDRESS runs the same check from a terminal against the public endpoint.

Every spl-token and Token-2022 account that still has a delegate appears here, with the revoke command.

Hardening: keep private keys off the web server

Once you have patched and rotated, change the architecture so the next RCE cannot reach a signing key at all.

Use a signer service, HSM or KMS

Keep the raw private key out of the application entirely. The web tier asks a dedicated signer (hardware token, KMS, or a separate signing service on its own host) to sign; an RCE in PHP then yields no key material.

Keep secrets out of the web root and VCS

Store env files and key material outside any web-served directory, and never commit them. Secrets under public/, wp-content/, dist/ or similar are both reachable and often publicly served.

Least privilege for the PHP worker

Run PHP as an unprivileged user that can read only what it must. Use open_basedir and disable_functions, and give the worker no standing access to keys it does not need for the current request.

Separate the signer from the web tier

Put signing behind a narrow, audited internal API with its own authn and rate limits, on a host that does not serve web requests. A compromised front end can then request a signature but cannot exfiltrate the key.

Server-side agent wallets are the sharpest edge.
A non-custodial bot that signs with a key held on the server (a market-making loop, an auto-claimer, a mint cron) keeps a live signing key within reach of the PHP worker. Those keys are the first thing to move behind a signer service, and the first to rotate after an incident.
Run the same checks on your host

The CLI scans your whole server for exposed keys and signs of compromise. phpshield wallet ADDRESS --watch watches a wallet from a server or cron job and can post to Slack or Discord, and phpshield delegates ADDRESS lists token approvals.

Advisory facts: CVE-2026-109618 and CVE-2026-109619, published 2026-10-21.