<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Norminal Solutions</title>
    <description>The latest articles on DEV Community by Norminal Solutions (@norminal).</description>
    <link>https://dev.to/norminal</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4201321%2Fba52da2e-3e19-4fc2-ae25-5e14a7b776b2.png</url>
      <title>DEV Community: Norminal Solutions</title>
      <link>https://dev.to/norminal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/norminal"/>
    <language>en</language>
    <item>
      <title>Why your scanner or AI agent can call a fixed PHP server vulnerable</title>
      <dc:creator>Norminal Solutions</dc:creator>
      <pubDate>Fri, 23 Oct 2026 22:48:02 +0000</pubDate>
      <link>https://dev.to/norminal/why-your-scanner-or-ai-agent-can-call-a-fixed-php-server-vulnerable-2767</link>
      <guid>https://dev.to/norminal/why-your-scanner-or-ai-agent-can-call-a-fixed-php-server-vulnerable-2767</guid>
      <description>&lt;p&gt;After the PHP2Shell release (CVE-2026-109618 and CVE-2026-109619, &lt;a href="https://www.php.net/archive/2026.php#2026-10-21-5" rel="noopener noreferrer"&gt;php.net advisory of 21 October 2026&lt;/a&gt;), many people ran a scanner or asked an AI agent whether their servers are fixed. On some systems, the answer comes back wrong in both directions.&lt;/p&gt;

&lt;p&gt;Disclosure: we run &lt;a href="https://php2shell.fyi/?ref=devto" rel="noopener noreferrer"&gt;php2shell.fyi&lt;/a&gt;, a passive checker for PHP2Shell.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrong answer 1: a fixed server shows as vulnerable
&lt;/h2&gt;

&lt;p&gt;The PHP project fixed the flaws in PHP 8.2.35, 8.3.36, 8.4.27 and 8.5.12. Some distributions put the fix into the version they already ship and keep the old upstream number:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;System&lt;/th&gt;
&lt;th&gt;Fixed build&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;php -v&lt;/code&gt; shows&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ubuntu 24.04&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;php8.3&lt;/code&gt; &lt;code&gt;8.3.6-0ubuntu0.24.04.13&lt;/code&gt; (&lt;a href="https://ubuntu.com/security/notices/USN-8948-1" rel="noopener noreferrer"&gt;USN-8948-1&lt;/a&gt;)&lt;/td&gt;
&lt;td&gt;8.3.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ubuntu 22.04&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;php8.1&lt;/code&gt; &lt;code&gt;8.1.2-1ubuntu2.28&lt;/code&gt; (USN-8948-1)&lt;/td&gt;
&lt;td&gt;8.1.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RHEL 9&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;php-8.0.30-8.el9_8.1&lt;/code&gt; (&lt;a href="https://access.redhat.com/errata/RHSA-2026:87151" rel="noopener noreferrer"&gt;RHSA-2026:87151&lt;/a&gt;)&lt;/td&gt;
&lt;td&gt;8.0.30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chainguard&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;php-8.4&lt;/code&gt; &lt;code&gt;8.4.26-r4&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;8.4.26&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A tool that reads only &lt;code&gt;8.3.6&lt;/code&gt; and compares it with &lt;code&gt;8.3.36&lt;/code&gt; says "vulnerable". The ProjectDiscovery Nuclei template for CVE-2026-109618 does this in its version fallback, and so does the Assetnote scanner when it sees no crash signal. Some community agent skills do the same with &lt;code&gt;sort -V&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Not every distribution does this. Debian, Alpine, the RHEL modules and RHEL 10 ship the new upstream numbers, for example Debian 13 &lt;code&gt;8.4.27-1~deb13u1&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrong answer 2: an old branch shows as not affected
&lt;/h2&gt;

&lt;p&gt;The CVE record for CVE-2026-109618 lists only the 8.2, 8.3, 8.4 and 8.5 branches as affected, and marks every other version as unaffected (&lt;a href="https://www.cve.org/CVERecord?id=CVE-2026-109618" rel="noopener noreferrer"&gt;cve.org&lt;/a&gt;, checked 23 October 2026). A scanner that reads the record literally can call PHP 8.1 and older "not affected".&lt;/p&gt;

&lt;p&gt;They are affected. The PHP security team published source fixes for 7.4, 8.0 and 8.1, and the researchers found affected releases back to PHP 5.4 (&lt;a href="https://php2shell.com/" rel="noopener noreferrer"&gt;php2shell.com&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  How to check the real build
&lt;/h2&gt;

&lt;p&gt;Read the package version of the PHP that serves the site, not only &lt;code&gt;php -v&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Debian and Ubuntu&lt;/span&gt;
dpkg &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="s1"&gt;'php*'&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'^ii'&lt;/span&gt;
&lt;span class="c"&gt;# RHEL, AlmaLinux, Rocky&lt;/span&gt;
rpm &lt;span class="nt"&gt;-qa&lt;/span&gt; &lt;span class="s1"&gt;'php*'&lt;/span&gt;
&lt;span class="c"&gt;# Alpine and Wolfi&lt;/span&gt;
apk info &lt;span class="nt"&gt;-v&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'^php'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compare the full version with the fixed build in your vendor's notice. On Debian and Ubuntu, &lt;code&gt;dpkg --compare-versions&lt;/code&gt; does this correctly; on RPM systems, compare within the same release and stream.&lt;/p&gt;

&lt;p&gt;Then check that PHP restarted. An installed package does not change PHP processes that are already running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ps &lt;span class="nt"&gt;-eo&lt;/span&gt; pid,lstart,cmd | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'[p]hp'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A PHP-FPM, Apache or LiteSpeed process that started before the update still runs the old code.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you use an AI agent
&lt;/h2&gt;

&lt;p&gt;Tell it which comparison to use. For example: "Compare the full package version with the vendor's fixed build. Do not compare &lt;code&gt;php -v&lt;/code&gt; with upstream numbers. If you cannot verify a version, report it as unknown." The agent skills from OpenAI (&lt;code&gt;phpcheck-server&lt;/code&gt;), Cognition (&lt;code&gt;fix-php-vuln&lt;/code&gt;) and Chainguard already work this way.&lt;/p&gt;

&lt;p&gt;The fixed builds for Ubuntu, Debian, RHEL and Alpine, with the vendor links, are on &lt;a href="https://php2shell.fyi/linux?ref=devto" rel="noopener noreferrer"&gt;php2shell.fyi/linux&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>php</category>
      <category>security</category>
      <category>linux</category>
      <category>ai</category>
    </item>
    <item>
      <title>AI agent skills for PHP2Shell: what each one checks</title>
      <dc:creator>Norminal Solutions</dc:creator>
      <pubDate>Fri, 23 Oct 2026 18:34:04 +0000</pubDate>
      <link>https://dev.to/norminal/ai-agent-skills-for-php2shell-what-each-one-checks-5bf0</link>
      <guid>https://dev.to/norminal/ai-agent-skills-for-php2shell-what-each-one-checks-5bf0</guid>
      <description>&lt;p&gt;PHP2Shell (CVE-2026-109618 and CVE-2026-109619) is a pair of flaws in PHP itself. The PHP project fixed them on 21 October 2026 in PHP 8.2.35, 8.3.36, 8.4.27 and 8.5.12 (&lt;a href="https://www.php.net/archive/2026.php#2026-10-21-5" rel="noopener noreferrer"&gt;php.net advisory&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Within two days, several teams published skills for coding and operations agents (Claude Code, Codex, Devin and others) that look for affected PHP and help update it. We read the skill files of the ones below. This post lists what each one inspects, how it decides whether a build has the fix, and whether it waits for your approval before it changes anything.&lt;/p&gt;

&lt;p&gt;Disclosure: we run &lt;a href="https://php2shell.fyi/?ref=devto" rel="noopener noreferrer"&gt;php2shell.fyi&lt;/a&gt;, a passive checker for PHP2Shell. None of the tools below is ours.&lt;/p&gt;

&lt;h2&gt;
  
  
  The question that matters most
&lt;/h2&gt;

&lt;p&gt;Some Linux distributions ship the fix under the old version number. Ubuntu 24.04 has the fix in &lt;code&gt;php8.3&lt;/code&gt; &lt;code&gt;8.3.6-0ubuntu0.24.04.13&lt;/code&gt; (&lt;a href="https://ubuntu.com/security/notices/USN-8948-1" rel="noopener noreferrer"&gt;USN-8948-1&lt;/a&gt;). RHEL 9 has it in &lt;code&gt;php-8.0.30-8.el9_8.1&lt;/code&gt; (&lt;a href="https://access.redhat.com/errata/RHSA-2026:87151" rel="noopener noreferrer"&gt;RHSA-2026:87151&lt;/a&gt;). Chainguard has it in &lt;code&gt;8.4.26-r4&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A tool that compares only the upstream number (8.3.6 is lower than 8.3.36) reports these fixed servers as vulnerable. An agent that trusts that answer may try to "fix" a server that is already fixed. So the first column we checked is: does the tool compare the full package version?&lt;/p&gt;

&lt;h2&gt;
  
  
  The skills
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Skill&lt;/th&gt;
&lt;th&gt;Publisher&lt;/th&gt;
&lt;th&gt;What it inspects&lt;/th&gt;
&lt;th&gt;Full package version?&lt;/th&gt;
&lt;th&gt;Changes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/openai/php2shell-checker" rel="noopener noreferrer"&gt;&lt;code&gt;phpcheck-server&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;OpenAI&lt;/td&gt;
&lt;td&gt;The PHP binary or Apache module that serves the site, its package, the OS, containers&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Check only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/openai/php2shell-checker" rel="noopener noreferrer"&gt;&lt;code&gt;phpcheck-url&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;OpenAI&lt;/td&gt;
&lt;td&gt;The &lt;code&gt;Server&lt;/code&gt; and &lt;code&gt;X-Powered-By&lt;/code&gt; headers of one URL&lt;/td&gt;
&lt;td&gt;No, and it says so&lt;/td&gt;
&lt;td&gt;Check only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/CognitionAI/devin-vuln-fixes" rel="noopener noreferrer"&gt;&lt;code&gt;fix-php-vuln&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Cognition&lt;/td&gt;
&lt;td&gt;Repositories: Dockerfiles, CI, Helm, Terraform, Ansible, Chef, Puppet&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Only after you pick the repos; then one pull request per repo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/chainguard-dev/cg-skills" rel="noopener noreferrer"&gt;&lt;code&gt;php2shell&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Chainguard&lt;/td&gt;
&lt;td&gt;Chainguard and Wolfi images, SBOMs, Kubernetes workloads&lt;/td&gt;
&lt;td&gt;Yes (apk revisions)&lt;/td&gt;
&lt;td&gt;Each change needs approval&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/rogulia/skills" rel="noopener noreferrer"&gt;&lt;code&gt;php2shell-response&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Iurii Rogulia (community)&lt;/td&gt;
&lt;td&gt;Hosts, images, hosting accounts, repositories&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Read-only unless you say otherwise&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;What the skill files say, in their own words:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OpenAI &lt;code&gt;phpcheck-server&lt;/code&gt;:&lt;/strong&gt; "Compare the full package revision against vendor guidance covering both CVEs. An older upstream version alone does not prove vulnerability." It also asks whether the web workers restarted after the update, and says: "Do not run exploit probes."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenAI &lt;code&gt;phpcheck-url&lt;/code&gt;:&lt;/strong&gt; "HTTP headers cannot tell whether the version contains a backported fix." Use it for a first look, not for a verdict.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cognition &lt;code&gt;fix-php-vuln&lt;/code&gt;:&lt;/strong&gt; "Never compare &lt;code&gt;php -v&lt;/code&gt; with upstream numbers to decide this." Discovery ends with: "Stop. Show the table and ask which repos to patch."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chainguard &lt;code&gt;php2shell&lt;/code&gt;:&lt;/strong&gt; "Every change needs the user's explicit approval first". It also warns: "Never compare version strings as text (&lt;code&gt;-r10&lt;/code&gt; is newer than &lt;code&gt;-r4&lt;/code&gt;)".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;php2shell-response&lt;/code&gt;:&lt;/strong&gt; "A distribution package may carry the fix under an older version number: check the vendor changelog or advisory, never compare version strings alone." Its mode: "Read-only unless the user says otherwise."&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tools that compare only the upstream number
&lt;/h2&gt;

&lt;p&gt;These are useful, but read their "vulnerable" answer as a question, not a verdict, on Ubuntu, RHEL and Chainguard:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The ProjectDiscovery &lt;a href="https://github.com/projectdiscovery/nuclei-templates/blob/main/http/cves/2026/CVE-2026-109618.yaml" rel="noopener noreferrer"&gt;Nuclei template&lt;/a&gt; for CVE-2026-109618. Its version fallback marks a patch number below the fixed one as vulnerable, so &lt;code&gt;8.3.6-0ubuntu0.24.04.13&lt;/code&gt; counts as vulnerable. It also marks every version below 8.2 as end of life.&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://github.com/assetnote/php2shell-scanner" rel="noopener noreferrer"&gt;Assetnote scanner&lt;/a&gt;. When it sees no crash signal, it falls back to the &lt;code&gt;X-Powered-By&lt;/code&gt; number with the same comparison.&lt;/li&gt;
&lt;li&gt;Some community skills compare versions with &lt;code&gt;sort -V&lt;/code&gt; on the upstream number only.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Before you let an agent change a server
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Give it read access first, and ask for a table: runtime, path, version, package, status.&lt;/li&gt;
&lt;li&gt;Check that it reads the PHP that serves the site (PHP-FPM, the Apache module, LiteSpeed), not only &lt;code&gt;php -v&lt;/code&gt; on the command line.&lt;/li&gt;
&lt;li&gt;Ask it to show the restart step. Old PHP processes keep the old code until they stop. &lt;code&gt;ps -eo pid,lstart,cmd | grep -i '[p]hp'&lt;/code&gt; shows when each one started.&lt;/li&gt;
&lt;li&gt;Do not let it fetch or run public proof-of-concept code. Most public PHP2Shell "PoC" repositories are attack tools, and their code is not reviewed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We keep a read-first prompt, our own &lt;code&gt;SKILL.md&lt;/code&gt; and this comparison up to date on &lt;a href="https://php2shell.fyi/ai-agents?ref=devto" rel="noopener noreferrer"&gt;php2shell.fyi/ai-agents&lt;/a&gt;. The fixed releases, the distribution builds and the mitigations are on &lt;a href="https://php2shell.fyi/fixed-versions?ref=devto" rel="noopener noreferrer"&gt;php2shell.fyi&lt;/a&gt;, with a source for each fact.&lt;/p&gt;

</description>
      <category>php</category>
      <category>security</category>
      <category>ai</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
