[{"data":1,"prerenderedAt":235},["ShallowReactive",2],{"seo-verification":3,"blog-php-version-inventory-for-client-sites-an-agency-method-en":6},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-php-version-inventory-for-client-sites-an-agency-method-en",{"id":9,"slug":10,"slugs":11,"title":15,"excerpt":16,"readTime":17,"views":18,"isPinned":19,"publishedAt":20,"updatedAt":21,"category":22,"categories":28,"featuredImage":30,"bgImage":31,"posterImage":32,"relatedSolution":30,"intro":33,"sections":34,"ctaTitle":173,"ctaBody":174,"ctaButton":175,"ctaUrl":176,"relatedPosts":177},508,"php-version-inventory-for-client-sites-an-agency-method",{"fr":12,"en":10,"ar":13,"es":14},"inventaire-versions-php-parc-sites-clients-agence","جرد-إصدارات-php-لمواقع-العملاء-منهج-للوكالات","inventario-de-versiones-php-de-sitios-cliente-metodo-de-agencia","PHP version inventory for client sites: an agency method","Build a register of the PHP version served by every client site across several hosts: access tiers, batch scripts, priority batches, client message, dated proof.",11,0,false,"2026-10-27T00:00:00+00:00","2026-10-27T23:58:39+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},8,"Security & Monitoring","securite-monitoring","bg-rose-500\u002F10 text-rose-400","security",[29],{"id":23,"name":24,"slug":25,"color":26,"icon":27},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Finventaire-versions-php-parc-sites-clients-agence-poster.svg","When a critical PHP flaw lands, the client's question is simple: is my site affected? For an agency, answering site by site, across five hosts with uneven access, takes days if nothing is prepared. This method fits in half a day for 20 to 200 sites: measurement in tiers according to the access you have, a register that separates presumed from confirmed, priority batches, a template message and dated proof of the fix. The same register is replayed for every CVE and every branch end of life.",[35,39,43,75,97,100,103,115,118,145,148,157,160,163],{"type":36,"title":37,"body":38},"h2","What a portfolio audit must produce","A portfolio audit is not a command you run once. It is a register: one row per site, with the PHP version read, how it was read, the date and the degree of certainty. Without these three pieces of information a number is worthless, because a version read last month says nothing about today.\n\nThe usual objection is fair: you do not control the client's host, you cannot run SSH commands everywhere, and you must not drop a diagnostic file on a production site. The answer is one idea: measure with what you have, and record honestly what each measurement proves. A site read from outside is presumed; a site read from the server is confirmed. The register keeps both and shows where work remains.",{"type":40,"title":41,"body":42},"tip","Dated context: PHP2Shell","On 21 October 2026 the PHP project released versions 8.5.12, 8.4.27, 8.3.36 and 8.2.35, which fix CVE-2026-109618 and CVE-2026-109619 (unauthenticated remote code execution). PHP 8.1 and older branches no longer receive updates from the project; minimal source backports were published for 7.4, 8.0 and 8.1. The addition to the CISA catalog of known exploited vulnerabilities dates from 26 October 2026, with a federal deadline of 29 October 2026. The flaws and the update of a single server are covered in the dedicated article; here we deal with the portfolio.",{"type":44,"title":45,"headers":46,"rows":50},"comparison","The four measurement tiers",[47,48,49],"Tier and access","What it proves","What it does not prove",[51,55,59,63,67,71],[52,53,54],"1. External observation, no access","An X-Powered-By or Server header, when present, suggests a stack and a version","Nothing certain: the header is often hidden, stripped or false. It is a presumption",[56,57,58],"2. wp-cli or SSH","The version of the PHP command-line binary, read on the machine","The version served on the web: the CLI binary can differ from PHP-FPM or Apache",[60,61,62],"3. cPanel, WHM or Plesk panel","The version assigned to each domain, with its handler","The fix actually applied: the same number can be patched or not depending on the package",[64,65,66],"4. Docker","The version in the image and in the running container","That the deployed image is the right one: compare the image with the live container",[68,69,70],"Reading the package changelog","That the fix is present despite an unchanged number (backport)","That the site was not compromised before the update",[72,73,74],"No tier possible","Nothing: the site goes to batch 4, to be asked of the client or the host","Never classify it as fixed by default",{"type":76,"title":77,"steps":78},"steps","Measure tier by tier",[79,82,85,88,91,94],{"title":80,"body":81},"Tier 1: read headers with no access","Prepare `sites.txt`, one URL per line, then run `while read -r u; do printf '%s,%s\\n' \"$u\" \"$(curl -sI --max-time 10 \"$u\" | tr -d '\\r' | grep -iE '^(server|x-powered-by):' | tr '\\n' ' ')\"; done \u003C sites.txt > externe.csv`. Each line gives the URL and the two headers found. An empty line is information: the header is hidden. Classify these sites as presumed and move to the next tier as soon as you can.",{"title":83,"body":84},"Tier 2: query WordPress with wp-cli","On a WordPress site where wp-cli is installed, `wp cli info` prints, among others, a `PHP binary` line and a `PHP version` line. To extract the second: `wp cli info | grep 'PHP version'`. Note that this value describes the binary used on the command line. The web server may run another version, especially when the host offers several versions per domain. For a reliable check, compare with tier 3.",{"title":86,"body":87},"Tier 2 bis: a batch SSH script","With `hotes.txt` (one SSH alias per line): `while read -r h; do printf '%s,%s\\n' \"$h\" \"$(timeout 20 ssh -n -o BatchMode=yes -o ConnectTimeout=8 \"$h\" \"php -r 'echo PHP_VERSION;'\" 2>\u002Fdev\u002Fnull || echo inconnue)\"; done \u003C hotes.txt > ssh.csv`. The `-n` stops ssh from swallowing the list, `BatchMode` prevents a host from asking for a password and blocking the loop, `timeout` bounds each attempt. Hosts that fail show up as \"inconnue\" instead of vanishing: tested with a failing host and a host that does not answer, both appear in the CSV.",{"title":89,"body":90},"Tier 3: read the panels","In cPanel, MultiPHP Manager lists each domain with its PHP version, or the Inherited label when it follows the system value. In WHM, the same tool gives the per-account view. In Plesk, the version and handler are set per domain under Websites & Domains, in the PHP settings section, depending on the Plesk version. Record the displayed version, then go to the next step to find out whether the fix is present.",{"title":92,"body":93},"Backports: read the changelog, not just the number","Distributions and hosts running CloudLinux often fix without changing the upstream number. AlmaLinux says so explicitly in its advisory: do not rely on `php -v`, compare the installed package with the published fixed version, for example with `rpm -q php-common`. To look for a CVE in the package history: `rpm -q --changelog php-common | grep CVE-2026-109618` on the RHEL family, and `apt changelog` followed by the package name on Debian and Ubuntu. If the CVE is absent from the history, it is not fixed in that package.",{"title":95,"body":96},"Tier 4: containers","A recent image does not prove that the running container is recent too. Compare the version in the image with that of the running container, then rebuild if needed. The full procedure is in the article on rebuilding PHP images, which we point to rather than copy.",{"type":36,"title":98,"body":99},"Why not phpinfo, and never in public","The reflex is to drop a `phpinfo()` file on the site. It shows everything, but it also exposes paths, modules and server configuration to anyone who knows the address, and a forgotten file becomes a reconnaissance entry point. On a client's site there is a second problem: changing that site without written authority is a fault, even just to read a version.\n\nBy default, rule it out. If a situation forces it, a temporary file must meet four conditions: the client's written agreement, an unpredictable name, immediate deletion after reading, and a record of the operation in the register. In almost every case a tier 2 or 3 measurement makes the file unnecessary.",{"type":36,"title":101,"body":102},"The register: one row per site","A shared spreadsheet is enough, provided everyone keeps the same columns. The goal is that a colleague can resume the audit without asking you anything, and that the client can receive their row as it stands.",{"type":104,"title":105,"items":106},"ul","The register columns",[107,108,109,110,111,112,113,114],"**Site, client, host** — the identity of the row, with the canonical URL and the technical contact.","**Access type** — none, wp-cli, SSH, panel or Docker: what determines the reachable tier.","**Measurement method** — the command or screen used, so that the measurement can be replayed identically.","**Version read and SAPI** — the number and the execution mode (FPM, Apache module, CLI), since the risk differs by mode.","**Measurement date** — a version without a date is an opinion.","**Confidence level** — presumed (tier 1) or confirmed (tiers 2 to 4), plus a backported mention if the changelog confirms it.","**Priority batch and status** — from 1 to 4, then to do, notified, in progress, fixed, or declined by the client.","**Fix date and proof** — the capture, the command output and the operator's name.",{"type":36,"title":116,"body":117},"Sort into batches, not a shopping list","Once the register is filled, the question is no longer \"is everything up to date?\" but \"where do we start?\". Four batches answer it. Batch 1 groups exposed sites on a branch that no longer receives fixes from the PHP project (8.1 and older), unless a vendor fix is confirmed by the changelog. Batch 2: branch still supported but a version older than the fix. Batch 3: fixed branch, to be confirmed by a tier 2 or 3 measurement. Batch 4: unreachable site or unknown version.\n\nThree criteria move a site up a batch: a public form, a shop, personal data, or a plugin that accepts uploaded files. A static showcase site in batch 2 comes after a shop in batch 3.",{"type":44,"title":119,"headers":120,"rows":124},"Priority grid",[121,122,123],"Batch","Criterion","Action",[125,129,133,137,141],[126,127,128],"Batch 1","Exposed, branch with no fix from the project (8.1 and older)","Migrate or demand a vendor-fixed package, notify the client the same day",[130,131,132],"Batch 2","Supported branch, version older than the fix","Update to the fixed version of the branch, within the week",[134,135,136],"Batch 3","Fixed branch, measurement to confirm","Tier 2 or 3 measurement, then set confidence to confirmed",[138,139,140],"Batch 4","Unreachable, access refused or version unknown","Ask the client for access or the version, follow up and date each request",[142,143,144],"Aggravating factor","Form, shop, personal data, upload","Moves the site up one batch in the order of treatment",{"type":36,"title":146,"body":147},"Warn clients without alarming them","A client does not need the detail of the two CVEs. They need to know whether their site is affected, what you are doing and what it changes for them. Two short messages are enough, to adapt. Keep the same factual tone: the version read, the date, what comes next. Do not write that the site is protected or secured: a version read is not proof of the absence of compromise.",{"type":76,"title":149,"steps":150},"Two template messages",[151,154],{"title":152,"body":153},"Client informed of the state of their site","\"Hello, we read the PHP version of your site on [date]. It was [version], older than the fix published by the PHP project for two critical flaws. We are updating it on [date], with no downtime planned. We will then send you dated proof of the version in service. No action is needed on your side. If you have questions, reply to this message.\"",{"title":155,"body":156},"Client whose site cannot be migrated right away","\"Hello, your site runs on a PHP version that no longer receives fixes from the project. The migration requires [work], which we propose for [date]. In the meantime we are [measure: vendor-fixed package, removal of the file upload form, filtering]. These measures reduce the risk without removing it. Please confirm the chosen date before [date].\"",{"type":36,"title":158,"body":159},"Prove the fix, then replay the audit","Proof of a fix is one record per site: the measurement before, the intervention, the same measurement after, the capture or command output, the version number, the date and the operator's name. Replaying the same measurement with the same method is what makes the proof comparable. Keep the log with the register.\n\nKeep the limit in mind: a version read proves the version served at the moment of measurement, not the absence of intrusion before the update. If a site stayed exposed after 21 October 2026, hunting for traces of exploitation is a second job, described in the PHP2Shell article.",{"type":36,"title":161,"body":162},"The cadence: one audit per quarter, and at every trigger","Replay the audit every quarter, plus at every new critical CVE and every branch end of life. Compare the two measurements: drift is a site whose version went down or whose confidence level went back to presumed. Record in the register the end-of-life dates that matter. For PHP 8.2 the project gives 31 December 2026; the migration checklist to 8.3 or 8.4 is in the dedicated article. The first batch of the next audit is already known: everything still on 8.2 on 1 January.",{"type":104,"title":164,"items":165},"Official documentation",[166,167,168,169,170,171,172],"**PHP notice of 21 October 2026** — https:\u002F\u002Fwww.php.net\u002Farchive\u002F2026.php#2026-10-21-5","**Supported PHP versions** — https:\u002F\u002Fwww.php.net\u002Fsupported-versions.php","**CISA alert of 26 October 2026** — https:\u002F\u002Fwww.cisa.gov\u002Fnews-events\u002Falerts\u002F2026\u002F10\u002F26\u002Fcisa-adds-two-known-exploited-vulnerabilities-catalog","**NCSC-NL php2shell repository** — https:\u002F\u002Fgithub.com\u002FNCSC-NL\u002Fphp2shell","**AlmaLinux advisory on fixed packages** — https:\u002F\u002Falmalinux.org\u002Fblog\u002F2026-10-21-php2shell-cve-2026-109618-cve-2026-109619\u002F","**MultiPHP Manager (cPanel)** — https:\u002F\u002Fdocs.cpanel.net\u002Fcpanel\u002Fsoftware\u002Fmultiphp-manager-for-cpanel\u002F","**wp cli info** — https:\u002F\u002Fdeveloper.wordpress.org\u002Fcli\u002Fcommands\u002Fcli\u002Finfo\u002F","One place to read and enforce the PHP version of every account","When client sites are spread across several hosts, every audit starts from zero: access to collect, mixed versions, scattered renewals. A Agency S reseller hosting plan (WHM, white label) or a fleet of VPS brings accounts together: one interface to read each account's PHP version, enforce it and keep the proof. Agency plans include daily backups.","See solutions for agencies","\u002Fsolutions\u002Fagences",[178,195,216],{"id":179,"slug":180,"slugs":181,"title":185,"excerpt":186,"readTime":187,"views":188,"isPinned":19,"publishedAt":189,"updatedAt":190,"category":191,"categories":192,"featuredImage":30,"bgImage":31,"posterImage":194,"relatedSolution":30},489,"php2shell-cve-2026-109618-109619-patch-php",{"fr":182,"en":180,"ar":183,"es":184},"php2shell-cve-2026-109618-109619-mettre-a-jour-php","php2shell-cve-2026-109618-109619-تحديث-php","php2shell-cve-2026-109618-109619-actualizar-php","PHP2Shell: patch CVE-2026-109618 and CVE-2026-109619","PHP2Shell: two critical PHP flaws exploitable without an account. Patched versions, update commands per system and temporary mitigations.",16,1,"2026-10-22T00:00:00+00:00","2026-10-27T23:58:43+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},[193],{"id":23,"name":24,"slug":25,"color":26,"icon":27},"\u002Fblog\u002Fcovers\u002Fphp2shell-cve-2026-109618-109619-mettre-a-jour-php-poster.svg",{"id":196,"slug":197,"slugs":198,"title":202,"excerpt":203,"readTime":17,"views":204,"isPinned":19,"publishedAt":205,"updatedAt":206,"category":207,"categories":213,"featuredImage":30,"bgImage":31,"posterImage":215,"relatedSolution":30},206,"php-82-end-of-life-planning-your-migration",{"fr":199,"en":197,"ar":200,"es":201},"php-82-fin-de-vie-checklist-migration","نهاية-دعم-php-82-دليل-الترحيل","php-82-fin-de-vida-planificar-la-migracion","PHP 8.2 end of life: your migration checklist","PHP 8.2 reaches EOL on December 31, 2026. Inventory your stack, compare PHP versions, and follow a step-by-step migration checklist to PHP 8.3 or 8.4.",7,"2026-08-01T00:00:00+00:00","2026-09-07T11:26:10+00:00",{"id":208,"name":209,"slug":210,"color":211,"icon":212},4,"Development","developpement","bg-warning\u002F10 text-warning","dev",[214],{"id":208,"name":209,"slug":210,"color":211,"icon":212},"\u002Fblog\u002Fcovers\u002Fphp-82-fin-de-vie-checklist-migration-poster.svg",{"id":217,"slug":218,"slugs":219,"title":223,"excerpt":224,"readTime":225,"views":18,"isPinned":19,"publishedAt":226,"updatedAt":227,"category":228,"categories":229,"featuredImage":30,"bgImage":31,"posterImage":231,"relatedSolution":232},501,"php2shell-docker-rebuild-php-wordpress-images",{"fr":220,"en":218,"ar":221,"es":222},"php2shell-docker-wordpress-reconstruire-images-php","php2shell-docker-إعادة-بناء-صور-php-ووردبريس","php2shell-docker-reconstruir-imagenes-php-wordpress","PHP2Shell and Docker: rebuild your PHP and WordPress images","An updated WordPress or Laravel does not change the PHP in your Docker image. Prove the served version, spot which tags moved and rebuild without traps.",12,"2026-10-23T00:00:00+00:00","2026-10-23T23:43:01+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},[230],{"id":23,"name":24,"slug":25,"color":26,"icon":27},"\u002Fblog\u002Fcovers\u002Fphp2shell-docker-wordpress-reconstruire-images-php-poster.svg",{"categorySlug":233,"appSlug":234},"cms-websites","wordpress",1793146022988]