Are you Mythos ready?

Read our latest report on validating and fixing vulnerabilities at machine speed.

Read the report
Read the report
Book a demo
Book a demo
For more information about how ZEST processes personal data, check out our Privacy Policy.
No items found.

php2shell: mitigate PHP now, patch the moment it ships

Dvir Sasson
Dvir Sasson
VP, Al & Security Research

This is a developing story. PHP released fixes on October 21, and we will keep updating this post as Linux distributions ship packages and attack details emerge. Last updated October 21, 2026, 15:35 UTC.

TL;DR

  • PHP has released fixes for two critical vulnerabilities, CVE-2026-109618 and CVE-2026-109619, each CVSS v4.0 9.2. Both allow unauthenticated remote code execution. Update to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or to your distribution's patched package, and restart every PHP worker.
  • Every PHP installation serving web requests is at risk: PHP-FPM, Apache mod_php, php-cgi, FrankenPHP and LiteSpeed. PHP rates the risk highest for mod_php.
  • PHP 8.1 and older get no official release. PHP published minimal source backports for 7.4, 8.0 and 8.1; otherwise use an LTS vendor or upgrade.
  • Exploit code is public and hosting providers report active attacks. Where you cannot patch today, the layers below reduce exposure, but PHP says no configuration change makes an installation safe.

On October 20, PHP's security team pre-announced an emergency release: two critical vulnerabilities, each rated 9.2 under CVSS v4.0, with fixes due Wednesday, October 21 at 14:00 UTC. Affected versions and technical details would ship with the fix.

The embargo did not hold. Within hours, CVE identifiers, a "php2shell" label and claims of unauthenticated remote code execution back to PHP 5 were circulating. By the next morning, defenders were reporting php2shell scanner traffic, exploit code claiming working remote code execution was public, and hosting providers were reporting active attacks.

PHP shipped the fixes on October 21, ahead of its 14:00 UTC schedule. This post covers how to patch, and what to do, layer by layer, for every server you cannot patch today.

Five layers of defense to deploy now: find every PHP, take it off the open internet, block at the edge, harden PHP, detect. Then patch.

What PHP confirmed

PHP's security advisory, published with the releases, confirms:

  • CVE-2026-109618, remote code execution through out-of-memory corruption, and CVE-2026-109619, remote code execution through stale global state, both CVSS v4.0 9.2
  • fixed releases 8.5.12, 8.4.27, 8.3.36 and 8.2.35, with patches shared with Linux distributions and LTS vendors in advance
  • every PHP installation serving web requests is at risk: PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed
  • no release for PHP 8.1 and older, with minimal source backports published for 7.4, 8.0 and 8.1
  • a demonstrated exploit against mod_php, where an unauthenticated request triggers the attack before any application code runs

Activity:

  • at least one defender reported scanner traffic with php2shell user agents in their logs by 04:35 UTC on October 21
  • from 07:34 UTC, several hosting providers reported active exploitation to Patchstack
  • at 07:43 UTC, Cloudflare's CTO said the company is seeing early attacks and has deployed WAF rules for the known exploit vectors to all plans, including Free
  • at 08:31 UTC, a proof of concept was published on GitHub that claims working code execution against PHP 8.4.4 and 8.2.34, adapting to each build's memory layout
  • Aikido reports exploitation in the wild and says configuration changes alone do not protect

Exploit code is circulating publicly, and attacks are under way. Our researchers confirmed the vulnerability in our lab, and watchTowr reports reproducing one of the two bugs. PHP rates both bugs 9.2, while the leaked post and watchTowr say 10.0. Either number means remote and critical.

The researcher who claims the find has published a write-up naming both CVEs.

Screenshot of the researcher's write-up naming CVE-2026-109618 and CVE-2026-109619. Handles blurred and exploit details cropped out.

The vulnerability

PHP's advisory describes two separate bugs, both in how PHP sets up and cleans up a request, before your application code runs.

CVE-2026-109618 (GHSA-w8hw-w9fx-j79w): if PHP runs out of memory while it is still filling in internal request data, the failure interrupts it halfway. Request cleanup then treats the partly initialized data as valid. The advisory's mitigations point at request size and structure as the way to drive PHP into that failure.

CVE-2026-109619 (GHSA-6wmf-4rv5-p3rp): some internal state that belongs to one request survives after the memory behind it has been freed, and the next request handled by the same worker can use it before PHP resets it. Session upload progress, the feature behind file upload progress bars, which is on by default, is one confirmed way in. On PHP 8.5, fatal error backtraces are another. Per-request PHP settings that emit a warning before the request starts are a third: php_value or php_flag in .htaccess or Apache directory configuration on mod_php, and PHP_VALUE or PHP_ADMIN_VALUE passed to FPM by the web server.

Both bugs run before any application logic, so no login, no file write access and no application flaw are needed. PHP rates the risk highest for Apache with mod_php, where it validated unauthenticated remote code execution with default input and memory limits, regardless of the application. PHP-FPM ends a worker when request startup fails, so there the out-of-memory bug depends on the application. PHP considers FrankenPHP likely to behave like mod_php.

The leaked write-up, and early analyses including ours, focused on session upload progress. It turned out to be one path to one of the two bugs. We checked one precondition of that path in our lab on PHP 8.3 with default settings: PHP tracked upload progress only when the request carried a session ID, either in the PHPSESSID cookie or as a field in the multipart body. It ignored a session ID in the query string, and it tracked progress for a script that never starts a session, so an application that does not use PHP sessions is still exposed.

Patch now

Update to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35. PHP shared the patches with Linux distributions and LTS vendors in advance, and their packages often keep the old upstream version number, so check your vendor's advisory for the package release, not the version string. PHP also warns that the volunteer-run rpms.remirepo.net repository will not have updates on October 21, so switch to distribution packages or build from source.

Then:

  • restart every PHP worker: a php-fpm master or Apache process started before the update still runs the old code
  • rebuild container images on the fixed base and redeploy, because production runs the old image until you do
  • verify through the web server, with check 1 from the curl section below or the check page from layer 4

Patch internet-facing servers first, then internal web servers, then images, then hosts that only have the PHP command line.

Distribution status as of 15:30 UTC on October 21: NVD has published both records, but most scanners have not yet added checks. Amazon Linux lists its PHP packages as Pending Fix, and Amazon Linux 2023's php8.1 as No Fix Planned. Gentoo has released GLSA 202610-02. Check your distribution's tracker before you assume a package is fixed.

Five layers for what you cannot patch yet

No single control covers this. Gina Peter Banyard, a PHP core developer, put it plainly: "the only mitigation is patching / upgrading PHP." The layers below cut the odds and the damage until you can.

Each layer covers a gap in the one before it. A WAF can miss a request that it and PHP parse differently. A configuration switch closes one confirmed path at most. And for PHP 8.1 and older, and for appliances and images you do not control, a patch may be days away or may never come.

Every snippet marked tested below was run in containers against nginx 1.27, Apache 2.4, ModSecurity with the OWASP Core Rule Set, and PHP 8.3 under both Apache and php-fpm.

Layer 1: find every PHP that answers HTTP

Start with PHP that serves web traffic: php-fpm, Apache's mod_php, php-cgi and LiteSpeed's lsphp. A host that only has the PHP command line, used for Composer or cron jobs, is outside the web request path and can wait.

shell
# PHP processes serving web traffic
ps -eo user,args | grep -E "[p]hp-fpm|[h]ttpd|[a]pache2|[l]sphp"

# installed PHP packages
dpkg -l | grep -E "php|libapache2-mod-php"   # Debian, Ubuntu
rpm -qa | grep -i php                        # RHEL, Amazon Linux
apk info -v | grep -i php                    # Alpine

# PHP container images on a host
docker images --format '{{.Repository}}:{{.Tag}}' | grep -i php

Then check the places PHP hides: images built on php:*-fpm or php:*-apache, appliances and hosting panels that bundle their own PHP, and Windows servers with a PHP binary in a tools folder. Version banners show how much of this is exposed. On October 21, a Shodan search on the X-Powered-By header found:

  • about 349,000 servers on PHP 5 and 329,000 on PHP 7
  • 78,000 on PHP 8.0 and 110,000 on PHP 8.1
  • 23,000 to 50,000 each on the releases that were current until October 21, 8.5.11, 8.4.26, 8.3.35 and 8.2.34, all affected

That is about 866,000 servers on branches that get no official release, and the counts include only servers that advertise their version. To see your own footprint, search for "X-Powered-By: PHP/" scoped to your networks with net: or org: (search filters need a Shodan account).

Shodan search for "X-Powered-By: PHP/8.1" on October 21, 2026: 109,708 servers advertising PHP 8.1, tagged eol-product, with banners showing PHP 8.1.34 and 8.1.8. Host identifiers blurred.

Layer 2: take PHP off the open internet

The strongest control you have today is making sure an anonymous request never reaches PHP. The same core developer suggested that turning a server off for a day may be the most sensible move, for anyone who can afford it.

For the rest, put authentication or an allowlist in front of PHP: a VPN, an IP allowlist, an identity-aware proxy, or HTTP basic auth at the reverse proxy for admin panels and internal tools. In our test, an unauthenticated multipart POST got a 401 from nginx and php-fpm never saw the request.

nginx
# server {} block: nothing reaches PHP without credentials
auth_basic           "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;   # create with: htpasswd -c /etc/nginx/.htpasswd ops

This does not work for public sites. Those need layers 3 to 5 and the patch.

Layer 3: block the trigger at the edge

For the session path of CVE-2026-109619, the trigger is a multipart POST carrying the upload progress field, PHP_SESSION_UPLOAD_PROGRESS by default. Only applications that show upload progress bars send it. The field has to arrive before the file parts, but an attacker can still push it deep into the body by padding it with large ordinary fields first. Cloud WAFs inspect only the first few kilobytes of a body, so treat these rules as a filter for unmodified tooling and rely on the web server fence below for the rest.

ModSecurity or Coraza (tested). ModSecurity reads the whole body up to its configured limit, so in our test it still blocked the field behind a 20 KB padding field. The second rule targets one public proof of concept, which sends twenty file parts with filenames around 256 KB long. Real filenames stay far below 1 KB, even in non-Latin scripts:

modsecurity
SecRule ARGS_NAMES "@streq PHP_SESSION_UPLOAD_PROGRESS" \
    "id:1096180,phase:2,deny,status:403,log,msg:'php2shell: PHP_SESSION_UPLOAD_PROGRESS field'"
SecRule FILES "@rx ^.{1024}" \
    "id:1096181,phase:2,deny,status:403,log,msg:'php2shell: upload filename over 1023 bytes'"

Both rules need request body inspection on (SecRequestBodyAccess On). Keep strict multipart validation on as well. ModSecurity's recommended configuration ships it as rule 200003, which rejected our malformed test bodies with a 400. Attackers bypass WAFs by sending bodies the WAF and PHP read differently, and strict validation narrows that gap.

AWS WAF, as a rule in the web ACL's JSON editor. We validated it against the AWS WAF API model, not against live traffic. AWS WAF inspects the first 8 KB of the body on Application Load Balancers and the first 16 KB on CloudFront by default:

json
{
  "Name": "php2shell-upload-progress",
  "Priority": 0,
  "Action": { "Block": {} },
  "VisibilityConfig": {
    "SampledRequestsEnabled": true,
    "CloudWatchMetricsEnabled": true,
    "MetricName": "php2shell-upload-progress"
  },
  "Statement": {
    "ByteMatchStatement": {
      "FieldToMatch": { "Body": { "OversizeHandling": "CONTINUE" } },
      "PositionalConstraint": "CONTAINS",
      "SearchString": "PHP_SESSION_UPLOAD_PROGRESS",
      "TextTransformations": [ { "Priority": 0, "Type": "NONE" } ]
    }
  }
}

Azure Application Gateway WAF, as a custom rule. Use PostArgs, which covers multipart bodies. RequestBody only applies to URL-encoded forms on Application Gateway:

json
{
  "name": "php2shellUploadProgress",
  "priority": 5,
  "ruleType": "MatchRule",
  "action": "Block",
  "state": "Enabled",
  "matchConditions": [
    {
      "matchVariables": [ { "variableName": "PostArgs", "selector": "PHP_SESSION_UPLOAD_PROGRESS" } ],
      "operator": "Any",
      "negationCondition": false,
      "matchValues": []
    }
  ]
}

Google Cloud Armor, as a custom rule on your security policy:

shell
gcloud compute security-policies rules create 1000 \
    --security-policy=YOUR_POLICY \
    --expression="request.body.contains('PHP_SESSION_UPLOAD_PROGRESS')" \
    --action=deny-403

Cloudflare, as a custom rule expression. The multipart and raw body fields require an Enterprise plan:

cloudflare expression
any(http.request.body.multipart.names[*][0] == "PHP_SESSION_UPLOAD_PROGRESS")

On every Cloudflare plan, keep the managed ruleset on. Cloudflare shipped four new "Generic Rules - Anomalous Execution" rules in an emergency release on October 21, and its CTO says rules for the known exploit vectors are live for all customers, including Free, with more coming as new vectors appear. He also calls them a stopgap. Someone has claimed a WAF bypass for this exploit, and nobody has shown it publicly yet. Do not rely on any WAF alone.

The Azure, Cloud Armor and Cloudflare rules follow each vendor's documented syntax. We did not test them against live traffic. Deploy in log or count mode first, confirm nothing legitimate matches, then switch to block.

No WAF in front of an AWS Application Load Balancer? A listener rule can refuse multipart requests on its own, as Azara shared on X. Give it a number lower than your forwarding rules, and add a rule with an even lower number that forwards your real upload paths first. We checked it against AWS documentation, not live traffic:

aws alb
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
  ListenerArn: <listener-arn>
  Priority: 10
  Conditions:
    - Field: http-header
      HttpHeaderConfig:
        HttpHeaderName: Content-Type
        Values:
          - "*multipart/form-data*"
  Actions:
    - Type: fixed-response
      FixedResponseConfig:
        StatusCode: "403"
        ContentType: "text/plain"
        MessageBody: "Temporarily unavailable"

Some widely shared mitigation lists, including one labeled as generated by an LLM, go further and block every request that carries the PHPSESSID cookie. That logs out every user of a session-based application. On its own it also misses the attack: in our lab, PHP accepted the session ID as a multipart form field too. Those lists only hold because they also block all multipart traffic.

Then fence multipart at the web server (tested). Most routes never take uploads. Replace /upload/ with your real upload paths.

nginx, in the http block and the server block:

nginx
# http {} block
map $http_content_type $php2shell_multipart {
    default                  0;
    "~*multipart/form-data"  1;
}
map "$php2shell_multipart:$uri" $php2shell_block {
    default                  0;
    "~^1:/(?!upload/)"       1;   # multipart allowed only under /upload/
}

# server {} block
if ($php2shell_block) { return 403; }

Apache 2.4, in the virtual host:

apache
<If "%{HTTP:Content-Type} =~ m#multipart/form-data#i && %{REQUEST_URI} !~ m#^/upload/#">
    Require all denied
</If>

In an Apache expression, %{CONTENT_TYPE} is the response content type, not the request's. Our first version used it, never matched, and kept passing the traffic it was meant to block. Use %{HTTP:Content-Type}.

Syhunt published a small Apache kit built on the same idea, a .htaccess rule that refuses multipart POSTs, with test pages that confirm the block is working. Delete the test pages afterward, as its README says.

The fence does not cover CVE-2026-109618, which is driven by memory exhaustion. For that bug, PHP recommends limits at the web server or proxy on decoded request size, input field count, multipart part count, header count and nesting depth, and the limits must also cover requests without a usable Content-Length.

Layer 4: harden PHP

PHP's advisory lists configuration changes that reduce exposure to specific attack paths. None of them makes an installation safe.

For CVE-2026-109619, switch off session upload progress and restart every worker. PHP says this blocks the confirmed session paths but not other variants. It costs nothing unless your application shows upload progress bars.

The setting is INI_PERDIR, so ini_set() cannot change it. Set it where your web SAPI reads configuration, then restart every php-fpm pool or the web server (tested for php.ini and the php-fpm pool):

ini
; php.ini, or a file in conf.d/
session.upload_progress.enabled = Off
ini
; php-fpm pool, for example /etc/php/8.3/fpm/pool.d/www.conf
php_admin_flag[session.upload_progress.enabled] = off
apache
# Apache virtual host with mod_php
php_admin_flag session.upload_progress.enabled off
dockerfile
# Dockerfile based on the official php image
RUN echo "session.upload_progress.enabled=0" \
    > "$PHP_INI_DIR/conf.d/zz-php2shell.ini"

Do not use a .user.ini file or ini_set() for this setting. PHP's advisory says it must be set where it applies before request parsing.

Then verify through the web server, because the PHP command line usually reads a different php.ini. In our php-fpm test container, the pool reported "0" while php -r in the same container still reported "1". Drop this file in the web root, request it, then delete it:

php
<?php
header('Content-Type: text/plain');
var_dump(ini_get('session.upload_progress.enabled'));   // want string(1) "0" or string(0) ""

Then apply the advisory's other measures where they fit. We have not tested these; set them in the php-fpm pool or server configuration so applications cannot override them:

ini
; php-fpm pool, for example /etc/php/8.4/fpm/pool.d/www.conf
php_admin_value[memory_limit] = -1             ; CVE-2026-109618, read the caveat below
php_admin_value[post_max_size] = 8M            ; 32M if the application takes uploads
php_admin_flag[fatal_error_backtraces] = off   ; PHP 8.5 only, CVE-2026-109619

An unlimited memory_limit removes the PHP memory limit an attacker can trip, but PHP notes that a real allocation failure can still reach the bug, and an unlimited worker can exhaust the host. PHP recommends a container or cgroup memory limit as the availability boundary, ideally one that kills only the affected worker, and warns against RLIMIT_AS and RLIMIT_DATA, which can cause the vulnerable failure. Keep upload_max_filesize below post_max_size.

The advisory adds three more measures:

  • lower max_input_nesting_level (64 by default), and cap input variables, multipart parts and uploads with max_input_vars, max_multipart_body_parts and max_file_uploads
  • remove per-request PHP settings that emit a warning before the request starts, such as obsolete php_value or php_flag lines in .htaccess on mod_php, or PHP_VALUE and PHP_ADMIN_VALUE passed from nginx or Apache to FPM, and prefer php.ini or the FPM pool
  • if performance allows, set pm.max_requests = 1 so each FPM worker handles a single request and no state carries over to the next

Also fix fatal errors and timeouts an attacker can trigger. Hiding diagnostics with error_reporting, display_errors or @ does not help.

Then limit what a successful request can do next:

ini
; php.ini: stop advertising the version to mass scanners
expose_php = Off

; php.ini: remove the usual command-execution functions
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,pcntl_exec

expose_php = Off removes the X-Powered-By: PHP/x.y.z header that internet-wide scanners read to pick targets. A determined attacker can still fingerprint the version, but you drop off the easiest target lists.

disable_functions breaks applications that shell out, so test it on staging first. Researchers have bypassed it before, and nobody has confirmed whether it blocks code execution through this bug. Treat it as a speed bump for the webshell that usually follows.

Outside PHP:

  • run each php-fpm pool as its own unprivileged user that cannot write to the web root
  • block outbound connections from the web tier, except the destinations the application needs
  • trim the IAM role or service account attached to PHP hosts to what the application needs, because a shell inherits it
  • keep secrets and data off PHP hosts where you can, and ship logs off the host so an attacker cannot erase them

Layer 5: detect attempts

These indicators come from public posts and one public proof of concept. They are trivial to change, so a clean result means only that nobody used the defaults:

  • user agents php2shell-109618 and php2shell-109619, reported in one defender's logs
  • multipart boundaries B7kQpoc618, B7kQpoc619 and BGCTXBOUNDARY, and the session cookie PHPSESSID=bgctxpoc
  • two POSTs in quick succession that both carry PHP_SESSION_UPLOAD_PROGRESS, the first with very long filenames
  • a pwned.txt file under wp-content/uploads/, written by the demonstrated chain on WordPress

None of these sources include attacker IP addresses yet.

shell
# scanner user agents in access logs (paths vary by distribution)
grep -hE "php2shell-10961[89]" /var/log/nginx/access.log* /var/log/apache2/access.log* /var/log/httpd/access_log* 2>/dev/null

# php-fpm workers that crashed (SIGSEGV, SIGABRT, SIGBUS)
grep -hE "exited on signal (6|7|11)" /var/log/php*fpm*.log

# PHP files created or changed in web roots since the leak, and the demo marker
find /var/www -type f \( -name "*.php" -o -name "pwned.txt" \) -newermt "2026-10-20"

Standard access logs do not record the multipart boundary or the form field names. To see those, log at the WAF or the reverse proxy.

Failed exploit attempts often crash the worker, so a burst of SIGSEGV lines on an internet-facing pool deserves a look. In your EDR, alert on php-fpm, httpd or apache2 spawning a shell, an interpreter, curl or wget. On Windows hosts, the Sigma rule for php.exe run with -r catches inline PHP execution, which is generic but cheap to enable.

Our researchers confirmed the vulnerability in our lab, and exploit code is now circulating publicly. Treat every exposed PHP server as reachable. A worker that does not crash is no proof you are safe: a successful exploit leaves the worker running. Do not run public exploits against production, and be careful what you download: pastes and repositories titled as "verified" exploits are a familiar lure for malware.

Check a server with curl

No safe request can prove a server is exploitable. These checks show whether the conditions for the attack are present and whether your layers hold, and none of them sends an exploit. Run them only against servers you own or are authorized to test, from outside your network:

shell
H=https://www.example.com   # any URL on the server that PHP answers

# 1. Does the server advertise PHP, and which version?
curl -sI "$H/" | grep -i '^x-powered-by'

# 2. Is session upload progress on? Needs the check page from layer 4.
curl -s "$H/php2shell-check.php"

# 3. Does your edge block the trigger field? Want 403.
curl -s -o /dev/null -w '%{http_code}\n' "$H/" -F 'PHP_SESSION_UPLOAD_PROGRESS=zest-check' -F 'note=harmless'

# 4. Does the multipart fence hold outside your upload paths? Want 403.
curl -s -o /dev/null -w '%{http_code}\n' "$H/" -F 'note=harmless'

# 5. Repeat check 3 against the origin IP, around your CDN. Want 403 or no answer.
curl -s -o /dev/null -w '%{http_code}\n' --resolve www.example.com:443:203.0.113.10 https://www.example.com/ -F 'PHP_SESSION_UPLOAD_PROGRESS=zest-check' -F 'note=harmless'

How to read the results:

  • check 1: X-Powered-By: PHP/8.5.11 means the server runs 8.5.11, which is affected: anything below 8.5.12, 8.4.27, 8.3.36 or 8.2.35 is. Distribution builds add a suffix such as -1ubuntu and backport fixes, so check the package version on the host. No header does not mean no PHP: expose_php may be off, or a proxy may strip it
  • check 2: string(1) "1" means the confirmed session path to CVE-2026-109619 is open; "0" or "" means layer 4 is in place
  • check 3: a 200 means the trigger field reached your application. The request carries no session ID, so PHP does not track it even then. In our lab it created no session, while the same request with a PHPSESSID cookie did
  • check 5: a WAF on the CDN does nothing for a request that reaches the origin directly. Replace the IP with your origin's address, and lock the origin down to the CDN's ranges if it answers

We ran these against PHP 8.5.11 in our lab. Checks 3 and 5 returned 403 behind ModSecurity with the layer 3 rules, and check 4 returned 403 behind the Apache fence and 200 on an upload path.

PHP 8.1 and older: the mitigation is the plan

PHP 8.1 and older get no official release. That leaves:

  • PHP's minimal source backports for 7.4, 8.0 and 8.1, if you build PHP yourself
  • vendor extended support: if a distribution or LTS vendor shipped your PHP, ask for its backport and a date
  • layer 2 permanently, so nothing anonymous reaches it, plus layers 3 to 5
  • migration to 8.2 or later; 8.2 itself leaves security support on December 31, 2026, so 8.3 is the better target

Appliances that bundle their own PHP are in scope too. Scanners have started flagging F5 BIG-IP's bundled PHP 5.4.45 for both CVEs. F5 has not published an advisory yet, and you can't patch that PHP yourself; the fix has to come from F5. Until then, keep the BIG-IP management interface off the internet and watch F5's advisories.

A server you cannot patch is acceptable only behind controls you can show are in place.

How ZEST approaches this

ZEST is a Continuous Threat Exposure Management (CTEM) platform. When a vulnerability leaks before its patch, there is nothing to scan for yet, so ZEST starts from inventory.

It finds PHP in what your connected tools already report: package inventories on hosts, container image contents and the external attack surface. It ties each runtime to its asset and owner and validates which ones are reachable from the internet, so you know which hosts need layer 2 first.

During the window, a compensating control ZEST can verify, such as a WAF rule in block mode in front of the asset, is recorded as evidence against the specific vulnerability. The vulnerability stays visible and returns to the queue if the control disappears. After the release, automated remediation tracks each patch through to verification by rescan, including the images that need a rebuild and a redeploy.

To see where PHP runs across your cloud and on-prem estate, which of those hosts still run an affected version and which are reachable from the internet, book a demo with ZEST.

Sources

About The Author

Dvir Sasson

Dvir Shimon Sasson is the VP of AI & Security Research at ZEST Security, where he drives innovation at the nexus of AI, autonomous agents, and cybersecurity. With over a decade of hands-on expertise across offensive and defensive security, his specializations include red team operations on AI systems and agents, incident response, threat intelligence, cloud security, and pioneering research into agentic security automation and emerging risks like Shadow AI. Certified CISSP and OSCP, Dvir is passionate about problem-solving, developing intelligent automation scripts in Python and PowerShell, and dissecting the mechanics of breaking things to build more resilient, AI-native defenses.

More Resources

View more
View more
BOOK a demo

Ready to see
ZEST in action?

"With ZEST, we can proactively resolve attack paths and quickly address cloud vulnerabilities"
Alexander Scheer Head of Cybersecurity @ Odyssey Therapeutics
Alexander Scheer
Head of Cybersecurity
@ Odyssey Therapeutics