<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
<title>Hongdam Studio notes</title>
<subtitle>We measure AI models, find security holes and publish the fixes with their code and links to sources.</subtitle>
<link rel="alternate" type="text/html" href="https://hongdam.net/studio/notes/"/>
<link rel="self" href="https://hongdam.net/studio/feed.xml"/>
<id>https://hongdam.net/studio/notes/</id>
<updated>2026-10-24T06:00:00+07:00</updated>
<icon>https://hongdam.net/assets/favicon.svg</icon>
<author><name>Hongdam Studio</name><uri>https://hongdam.net/studio/</uri></author>
<entry>
<title>16,326 Supabase databases let anyone read their tables: check yours in two minutes</title>
<link rel="alternate" type="text/html" href="https://hongdam.net/studio/notes/supabase-public-key-open-tables/"/>
<id>tag:hongdam.net,2026-10-24:studio/supabase-public-key-open-tables</id>
<published>2026-10-24T06:00:00+07:00</published>
<updated>2026-10-24T06:00:00+07:00</updated>
<category term="last-mile" label="Last mile"/>
<summary>UpGuard counted 16,326 Supabase databases where anyone with the public key can read the tables. This note shows a two-minute check for your project, the SQL that closes the hole, and what Supabase changes on 30 October 2026.</summary>
<content type="html">&lt;p&gt;UpGuard counted 16,326 Supabase databases where anyone who holds the app&#x27;s public key can read the tables &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s1&quot; aria-label=&quot;source 1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. The study, published 24 September 2026 and updated 14 October, started from about 300,000 domains that appeared to use Supabase and found signs of personal data in more than half of the 16,326. UpGuard links the problem to how tables are made: Supabase turns on row-level security (RLS, explained next) for tables created in its Table Editor, but not for tables created through the API, which is how coding agents work &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s1&quot; aria-label=&quot;source 1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Row-level security (RLS) is the rule set inside Postgres, the database Supabase runs on, that decides which rows each caller may read or change. A Supabase app includes a public key in its browser code, called the publishable key (older name: the &lt;code&gt;anon&lt;/code&gt; key). Supabase describes it as safe to publish because it can only access what RLS allows &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s2&quot; aria-label=&quot;source 2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. With RLS off, that key can access every row. A second key, the secret key (older name: the &lt;code&gt;service_role&lt;/code&gt; key), bypasses RLS entirely and belongs on a server &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s2&quot; aria-label=&quot;source 2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id=&quot;four-scans-since-march-2025-all-found-open-table&quot;&gt;Four scans since March 2025 all found open tables&lt;/h2&gt;
&lt;p&gt;Matt Palmer&#x27;s scan of Lovable projects came first: he found the flaw on 20 March 2025, completed a scan of 1,645 projects on 21 March and published on 29 May 2025 &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s3&quot; aria-label=&quot;source 3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. NVD, the US vulnerability database, lists it as CVE-2025-48757 (insufficient RLS in Lovable through 15 April 2025): published 30 May 2025, severity 9.3 of 10 as scored by MITRE, the CVE&#x27;s issuer. The record is marked disputed, because the supplier holds each customer responsible for protecting its own app&#x27;s data &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s4&quot; aria-label=&quot;source 4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;div class=&quot;tbl&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th scope=&quot;col&quot;&gt;Scan&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;Published&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;Sample&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;Open tables found&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;Palmer, Lovable projects &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s3&quot; aria-label=&quot;source 3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/th&gt;&lt;td data-h=&quot;Published&quot;&gt;29 May 2025&lt;/td&gt;&lt;td data-h=&quot;Sample&quot;&gt;1,645 projects, home pages only&lt;/td&gt;&lt;td data-h=&quot;Open tables found&quot;&gt;170 projects (about 10.3%), 303 endpoints&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;Modern Pentest, Y Combinator startups &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s5&quot; aria-label=&quot;source 5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/th&gt;&lt;td data-h=&quot;Published&quot;&gt;26 January 2026&lt;/td&gt;&lt;td data-h=&quot;Sample&quot;&gt;71 startups with reachable Supabase databases&lt;/td&gt;&lt;td data-h=&quot;Open tables found&quot;&gt;20 exposed personal data (28%); 43 had some exposure (61%)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;Symbiotic Security &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s6&quot; aria-label=&quot;source 6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;&lt;/th&gt;&lt;td data-h=&quot;Published&quot;&gt;2 June 2026&lt;/td&gt;&lt;td data-h=&quot;Sample&quot;&gt;1,072 Supabase sites from Lovable, v0, Bolt.new, Replit and Windsurf&lt;/td&gt;&lt;td data-h=&quot;Open tables found&quot;&gt;39 with tables readable by the public key; 34 more with sensitive columns exposed&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;UpGuard &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s1&quot; aria-label=&quot;source 1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/th&gt;&lt;td data-h=&quot;Published&quot;&gt;24 September 2026&lt;/td&gt;&lt;td data-h=&quot;Sample&quot;&gt;about 300,000 domains showing signs of Supabase&lt;/td&gt;&lt;td data-h=&quot;Open tables found&quot;&gt;16,326 databases with readable tables&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;The samples differ, so the percentages cannot be compared across rows. Wiz found the same problem in Moltbook, a social network for AI agents, and reported it on 31 January 2026: the project URL and public key were in the production JavaScript, RLS was not configured, and queries returned 1.5 million API tokens and 35,000 email addresses. One PATCH request (an HTTP call that edits a record) changed an existing post, so writes were open too. The maintainer closed the tables in several steps within hours &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s7&quot; aria-label=&quot;source 7&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id=&quot;two-checks-show-whether-anyone-can-read-your-app&quot;&gt;Two checks show whether anyone can read your app&#x27;s data&lt;/h2&gt;
&lt;p&gt;The Connect dialog in the Supabase dashboard shows the project URL and the publishable key &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s2&quot; aria-label=&quot;source 2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. This request asks for one table that the app uses, with the placeholders replaced:&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;&lt;pre data-lang=&quot;bash&quot;&gt;&lt;code&gt;curl -s &amp;quot;https://YOUR-REF.supabase.co/rest/v1/orders?select=*&amp;amp;limit=3&amp;quot; \
  -H &amp;quot;apikey: YOUR_PUBLISHABLE_KEY&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Rows in the reply mean every visitor to the site can read that table. &lt;code&gt;[]&lt;/code&gt; means the key can access no rows (RLS on with no policy, or an empty table). A &lt;code&gt;42501&lt;/code&gt; permission error means the table is not exposed to the key at all &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s8&quot; aria-label=&quot;source 8&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;The SQL Editor in the same dashboard checks every table at once:&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;&lt;pre data-lang=&quot;sql&quot;&gt;&lt;code&gt;select c.relname as table_name,
       c.relrowsecurity as rls_on,
       has_table_privilege(&amp;#x27;anon&amp;#x27;, c.oid, &amp;#x27;select&amp;#x27;) as anon_can_read
from pg_class c
join pg_namespace n on n.oid = c.relnamespace
where n.nspname = &amp;#x27;public&amp;#x27; and c.relkind in (&amp;#x27;r&amp;#x27;,&amp;#x27;p&amp;#x27;)
order by rls_on, table_name;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A row with &lt;code&gt;rls_on&lt;/code&gt; false and &lt;code&gt;anon_can_read&lt;/code&gt; true is a table the public key reads. Both checks run against your own project.&lt;/p&gt;
&lt;h2 id=&quot;the-fix-turn-on-rls-take-away-the-public-role-s-&quot;&gt;The fix: turn on RLS, take away the public role&#x27;s access, and add one policy per action&lt;/h2&gt;
&lt;div class=&quot;code&quot;&gt;&lt;pre data-lang=&quot;sql&quot;&gt;&lt;code&gt;alter table public.orders enable row level security;
revoke all on public.orders from anon;

create policy &amp;quot;owner reads own orders&amp;quot; on public.orders
  for select to authenticated
  using ((select auth.uid()) = user_id);

create policy &amp;quot;owner adds own orders&amp;quot; on public.orders
  for insert to authenticated
  with check ((select auth.uid()) = user_id);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;auth.uid()&lt;/code&gt; returns the signed-in user&#x27;s id; wrapping it in &lt;code&gt;select&lt;/code&gt; lets Postgres evaluate it once per statement instead of once per row &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s9&quot; aria-label=&quot;source 9&quot;&gt;9&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;We ran these statements on 24 October 2026 on Postgres on our own computer (PGlite 0.5.11, Postgres 18.6) with test versions of the &lt;code&gt;anon&lt;/code&gt; and &lt;code&gt;authenticated&lt;/code&gt; roles, not on a hosted Supabase project. Before, the public role read every order. After, the public role got &lt;code&gt;permission denied&lt;/code&gt;, user 1 read only user 1&#x27;s rows, and an insert naming user 2 failed with a row-level security violation.&lt;/p&gt;
&lt;h2 id=&quot;a-policy-that-says-true-opens-the-table-again&quot;&gt;A policy that says &lt;code&gt;true&lt;/code&gt; opens the table again&lt;/h2&gt;
&lt;p&gt;A policy of &lt;code&gt;using (true)&lt;/code&gt; matches every row for every caller. Palmer reports that the scanner Lovable released in April 2025 checked that a policy exists, not what it says &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s3&quot; aria-label=&quot;source 3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. Lovable&#x27;s documentation lists rules that let everyone through among its quick scan&#x27;s database checks, and says the scans find common issues, not all of them &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s10&quot; aria-label=&quot;source 10&quot;&gt;10&lt;/a&gt;&lt;/sup&gt;. On the same test Postgres, a table with a &lt;code&gt;using (true)&lt;/code&gt; policy returned its row to the &lt;code&gt;anon&lt;/code&gt; role. One query lists the policies that match:&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;&lt;pre data-lang=&quot;sql&quot;&gt;&lt;code&gt;select tablename, policyname, cmd
from pg_policies
where schemaname = &amp;#x27;public&amp;#x27; and (qual = &amp;#x27;true&amp;#x27; or with_check = &amp;#x27;true&amp;#x27;);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;on-30-october-2026-supabase-changes-the-default-&quot;&gt;On 30 October 2026 Supabase changes the default for new tables; existing tables keep their settings&lt;/h2&gt;
&lt;p&gt;A Supabase changelog entry of 28 April 2026 says new tables in the &lt;code&gt;public&lt;/code&gt; schema are no longer reachable through the Data API (the generated REST layer that &lt;code&gt;supabase-js&lt;/code&gt; calls) until a &lt;code&gt;grant&lt;/code&gt; allows it. New projects get the new default from 30 May 2026, in a rollout over a few weeks; the entry sets 30 October 2026 for existing projects, six days after this note. Existing tables keep their grants and stay reachable, and RLS works as before. The entry gives the reason: agents, CLI scripts and AI platforms create tables without a human reviewing the change &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s8&quot; aria-label=&quot;source 8&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;. The new default does not close tables that are already open; the check above shows which ones are.&lt;/p&gt;
&lt;p&gt;An existing project can adopt the new default before 30 October with two statements from the same entry &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s8&quot; aria-label=&quot;source 8&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;. On our test Postgres, a table made afterwards returned &lt;code&gt;permission denied&lt;/code&gt; to &lt;code&gt;anon&lt;/code&gt;, the older table stayed readable, and an explicit &lt;code&gt;grant select&lt;/code&gt; made the new one readable again.&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;&lt;pre data-lang=&quot;sql&quot;&gt;&lt;code&gt;alter default privileges for role postgres in schema public
  revoke select, insert, update, delete on tables from anon, authenticated, service_role;
alter default privileges for role postgres in schema public
  revoke usage, select on sequences from anon, authenticated, service_role;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;An event trigger (a Postgres rule that runs when the database structure changes) can turn on RLS for each table created afterwards, whichever tool made it. Supabase publishes its own version &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s11&quot; aria-label=&quot;source 11&quot;&gt;11&lt;/a&gt;&lt;/sup&gt;; this shorter one ran in the same test and caught both &lt;code&gt;create table&lt;/code&gt; and &lt;code&gt;create table as&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;&lt;pre data-lang=&quot;sql&quot;&gt;&lt;code&gt;create function rls_on_new_tables() returns event_trigger
language plpgsql security definer set search_path = pg_catalog as $$
declare t record;
begin
  for t in select * from pg_event_trigger_ddl_commands()
           where command_tag in (&amp;#x27;CREATE TABLE&amp;#x27;, &amp;#x27;CREATE TABLE AS&amp;#x27;, &amp;#x27;SELECT INTO&amp;#x27;)
             and schema_name = &amp;#x27;public&amp;#x27;
  loop
    execute format(&amp;#x27;alter table %s enable row level security&amp;#x27;, t.object_identity);
  end loop;
end $$;

create event trigger rls_on_new_tables on ddl_command_end
  when tag in (&amp;#x27;CREATE TABLE&amp;#x27;, &amp;#x27;CREATE TABLE AS&amp;#x27;, &amp;#x27;SELECT INTO&amp;#x27;)
  execute function rls_on_new_tables();&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Tables created before the trigger need &lt;code&gt;alter table … enable row level security&lt;/code&gt; run on them manually &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s11&quot; aria-label=&quot;source 11&quot;&gt;11&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id=&quot;two-more-problems-columns-the-browser-can-write-&quot;&gt;Two more problems: columns the browser can write, and secret keys in the browser&lt;/h2&gt;
&lt;p&gt;On Linkable, a paid site built with Lovable, Palmer sent a POST request with no authorization header and inserted a record with &lt;code&gt;payment_status&lt;/code&gt; set to &quot;paid&quot;, bypassing Stripe &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s3&quot; aria-label=&quot;source 3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. A column the browser may write is a column a visitor may set. Column-level grants remove the write access: on our test Postgres, a signed-in user&#x27;s insert or update of &lt;code&gt;plan&lt;/code&gt; got &lt;code&gt;permission denied&lt;/code&gt;, while &lt;code&gt;display_name&lt;/code&gt; stayed writable.&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;&lt;pre data-lang=&quot;sql&quot;&gt;&lt;code&gt;revoke insert, update on public.profiles from authenticated;
grant insert (id, display_name), update (display_name) on public.profiles to authenticated;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The server that receives the payment provider&#x27;s event then writes &lt;code&gt;plan&lt;/code&gt; with the secret key, which bypasses RLS &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s2&quot; aria-label=&quot;source 2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. That key in a browser bundle defeats every policy above. Supabase answers a secret key sent from a browser with a 401 error, and says a leaked key still works from other tools &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s2&quot; aria-label=&quot;source 2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. In a framework such as Next.js, a &lt;code&gt;NEXT_PUBLIC_&lt;/code&gt; prefix on a variable name sends its value to the browser:&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;&lt;pre data-lang=&quot;bash&quot;&gt;&lt;code&gt;NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=sb_publishable_...   # sent to the browser
SUPABASE_SECRET_KEY=sb_secret_...                          # server only: no prefix&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;grep -r &amp;quot;sb_secret_&amp;quot; dist build .next/static&lt;/code&gt; over a build folder finds a new-format secret key left in it. You replace a leaked secret key in the dashboard under Settings, API Keys &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s2&quot; aria-label=&quot;source 2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. Supabase is deprecating the &lt;code&gt;anon&lt;/code&gt; and &lt;code&gt;service_role&lt;/code&gt; keys by the end of 2026 and replacing them with the publishable and secret keys &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s2&quot; aria-label=&quot;source 2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;</content>
</entry>
<entry>
<title>PHP2Shell: PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 fix two flaws that let attackers run code</title>
<link rel="alternate" type="text/html" href="https://hongdam.net/studio/notes/php2shell-fixed-releases-and-restart/"/>
<id>tag:hongdam.net,2026-10-24:studio/php2shell-fixed-releases-and-restart</id>
<published>2026-10-24T06:00:00+07:00</published>
<updated>2026-10-24T06:00:00+07:00</updated>
<category term="security" label="Security"/>
<summary>Two PHP flaws, CVE-2026-109618 and CVE-2026-109619, let an outsider run code on a web server without logging in. PHP released fixes on 21 October 2026. Attacks began on 17 October. Updated servers also need a restart.</summary>
<content type="html">&lt;p&gt;PHP, the language many websites run on, has two flaws in its core that let an outsider run commands on a web server without logging in. PHP released fixes on 21 October 2026 &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s1&quot; aria-label=&quot;source 1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, four days after Amazon recorded the first attack attempt &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s6&quot; aria-label=&quot;source 6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;. Sansec credits the exploit (attack code) that combines both flaws, called PHP2Shell, to the research firm Calif &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s15&quot; aria-label=&quot;source 15&quot;&gt;15&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;A CVE (Common Vulnerabilities and Exposures) number is the public ID of one flaw. A SAPI (server API) is the way PHP connects to a web server. php-fpm is a pool of PHP worker processes that nginx or Apache sends requests to; mod_php runs PHP inside Apache&#x27;s own processes.&lt;/p&gt;
&lt;h2 id=&quot;two-cves-both-rated-9-2-out-of-10-let-attackers-&quot;&gt;Two CVEs, both rated 9.2 out of 10, let attackers run code on the server&lt;/h2&gt;
&lt;p&gt;CVE-2026-109618: a request that exhausts &lt;code&gt;memory_limit&lt;/code&gt; makes PHP abort while it is starting up, and the cleanup that follows treats half-built data as valid &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s2&quot; aria-label=&quot;source 2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. CVE-2026-109619: state from one request keeps pointing at memory that request owned, and a later request on the same worker (the process that handles requests) uses the freed memory &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s3&quot; aria-label=&quot;source 3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. Both lead to remote code execution (RCE: an outsider runs commands on the server) with the web worker&#x27;s privileges &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s2&quot; aria-label=&quot;source 2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s3&quot; aria-label=&quot;source 3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;PHP scores each 9.2 on CVSS v4, a 0-to-10 severity scale, with attack complexity rated high &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s2&quot; aria-label=&quot;source 2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s3&quot; aria-label=&quot;source 3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. NVD adds a CVSS 3.1 score of 9.8 for CVE-2026-109618 &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s4&quot; aria-label=&quot;source 4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;. The PHP Foundation states that a score of 10.0 that circulated before the release was wrong &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s5&quot; aria-label=&quot;source 5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id=&quot;mod-php-is-the-most-exposed-setup-php-fpm-depend&quot;&gt;mod_php is the most exposed setup; php-fpm depends on the application&lt;/h2&gt;
&lt;p&gt;PHP&#x27;s advisory lists five affected setups: Apache mod_php, php-fpm, php-cgi, FrankenPHP and LiteSpeed. It rates mod_php highest, because an unauthenticated request reaches the first flaw before any application code runs &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s1&quot; aria-label=&quot;source 1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, and the advisory demonstrated it with default memory and input limits &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s2&quot; aria-label=&quot;source 2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;For php-fpm the sources differ:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;CVE-2026-109618: the advisory&#x27;s source analysis calls FPM susceptible but shows no full exploit; FPM exits the worker when startup fails &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s2&quot; aria-label=&quot;source 2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;&lt;li&gt;CVE-2026-109619: FPM is exposed through a frontend that passes &lt;code&gt;PHP_VALUE&lt;/code&gt; settings, or through session upload progress, which was validated &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s3&quot; aria-label=&quot;source 3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;&lt;li&gt;Calif demonstrated FPM behind nginx where the application decodes data after startup (&lt;code&gt;session_start()&lt;/code&gt;, &lt;code&gt;unserialize()&lt;/code&gt;) and lists pre-login code execution on WordPress 7.1.2, Drupal 11.4.3 and Joomla 6.1.4 &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s16&quot; aria-label=&quot;source 16&quot;&gt;16&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;&lt;li&gt;Red Hat: reliable exploitation needs precise heap manipulation, and FPM workers exit on early failure &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s12&quot; aria-label=&quot;source 12&quot;&gt;12&lt;/a&gt;&lt;/sup&gt;. Sansec: a researcher found public proofs of concept fail on default installs and mostly need a separate file-inclusion bug in the target &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s15&quot; aria-label=&quot;source 15&quot;&gt;15&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;The advisory does not cover servers without PHP or machines that run PHP only for command-line scripts; it covers PHP that serves web requests &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s1&quot; aria-label=&quot;source 1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. RHEL 7 is not affected by CVE-2026-109618, only by CVE-2026-109619 &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s12&quot; aria-label=&quot;source 12&quot;&gt;12&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id=&quot;attacks-began-on-17-october-four-days-before-the&quot;&gt;Attacks began on 17 October, four days before the fix&lt;/h2&gt;
&lt;p&gt;Amazon&#x27;s honeypot network (decoy servers that record attacks) logged the first attempt on 17 October from an anonymization network. On 21 October between 02:00 and 08:00 UTC more attempts arrived with varied payloads, which suggests several attackers; Amazon cannot say whether any would have worked on a real system &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s6&quot; aria-label=&quot;source 6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;. Cloudflare saw attack traffic against customers before the release and switched on managed WAF rules (web application firewall rules, which filter requests) for Free and paid plans at 03:02 UTC on 21 October &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s17&quot; aria-label=&quot;source 17&quot;&gt;17&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;The PHP team says the CVE ids leaked about 15:00 UTC on 20 October, a demonstration video followed that evening, and the release moved from 22 October to 21 October, 14:00 UTC. It found no working public exploit at release &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s5&quot; aria-label=&quot;source 5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;. The alert from CISA (the US government&#x27;s cybersecurity agency), published 21 October and revised 23 October, reports no successful exploitation observed &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s7&quot; aria-label=&quot;source 7&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;. The Known Exploited Vulnerabilities catalog, version 2026.10.23, lists neither CVE (read 24 October 2026) &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s8&quot; aria-label=&quot;source 8&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id=&quot;php-v-shows-the-command-line-php-the-web-server-&quot;&gt;&lt;code&gt;php -v&lt;/code&gt; shows the command-line PHP; the web server can run a different one&lt;/h2&gt;
&lt;p&gt;A small PHP file on the web server can print which PHP build serves web requests. &lt;code&gt;PHP_VERSION&lt;/code&gt; holds the version string and &lt;code&gt;PHP_SAPI&lt;/code&gt; the server API name &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s22&quot; aria-label=&quot;source 22&quot;&gt;22&lt;/a&gt;&lt;/sup&gt;; &lt;code&gt;fpm-fcgi&lt;/code&gt; is php-fpm, &lt;code&gt;apache2handler&lt;/code&gt; is the Apache module, &lt;code&gt;cgi-fcgi&lt;/code&gt; is FastCGI and &lt;code&gt;litespeed&lt;/code&gt; is LiteSpeed &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s23&quot; aria-label=&quot;source 23&quot;&gt;23&lt;/a&gt;&lt;/sup&gt;. Red Hat points to a temporary &lt;code&gt;phpinfo()&lt;/code&gt; page for web settings, because &lt;code&gt;php -i&lt;/code&gt; reports the command-line configuration &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s12&quot; aria-label=&quot;source 12&quot;&gt;12&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;&lt;pre data-lang=&quot;bash&quot;&gt;&lt;code&gt;php -v                                              # command-line build only
echo &amp;#x27;&amp;lt;?php echo PHP_VERSION, &amp;quot; &amp;quot;, PHP_SAPI, &amp;quot;\n&amp;quot;;&amp;#x27; | sudo tee /var/www/html/ver-check.php
curl -s https://example.com/ver-check.php           # e.g. 8.3.36 fpm-fcgi
sudo rm /var/www/html/ver-check.php&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;On the server itself:&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;&lt;pre data-lang=&quot;bash&quot;&gt;&lt;code&gt;ps -eo pid,lstart,user,args | grep -E &amp;#x27;php-fpm|apache2|httpd|lsphp|frankenphp|php-cgi&amp;#x27; | grep -v grep
sudo apachectl -M | grep php            # mod_php loaded into Apache
grep -rn fastcgi_pass /etc/nginx/       # which php-fpm socket nginx uses&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Distribution packages keep an older upstream number with a new suffix, so a printed version can read lower than the release table below while the package carries the fix; CloudLinux names alt-php85 8.5.11-5 and ea-php84 8.4.26-2.el8.cloudlinux.1 as fixed builds &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s14&quot; aria-label=&quot;source 14&quot;&gt;14&lt;/a&gt;&lt;/sup&gt;. Package versions decide.&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;&lt;pre data-lang=&quot;bash&quot;&gt;&lt;code&gt;apt list &amp;#x27;?installed ?name(^php[0-9.]+$)&amp;#x27;                                  # Debian, Ubuntu
zgrep CVE-2026-109618 /usr/share/doc/php8.3-common/changelog.Debian.gz    # Debian, Ubuntu
rpm -q --changelog php-common | grep CVE-2026-109618                       # RHEL family&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The changelog checks come from Sansec &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s15&quot; aria-label=&quot;source 15&quot;&gt;15&lt;/a&gt;&lt;/sup&gt;. CloudLinux notes its native PHP 8.2 and 8.3 changelogs omit the CVE ids; there &lt;code&gt;rpm -q php-cli&lt;/code&gt; reads 8.2.35 or 8.3.36 or later &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s14&quot; aria-label=&quot;source 14&quot;&gt;14&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id=&quot;four-php-versions-8-2-to-8-5-have-a-fixed-releas&quot;&gt;Four PHP versions (8.2 to 8.5) have a fixed release; 8.1 and older depend on the vendor&lt;/h2&gt;
&lt;div class=&quot;tbl&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th scope=&quot;col&quot;&gt;PHP branch&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;Fixed release (21 October 2026)&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;Upstream security support ends&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;8.5&lt;/th&gt;&lt;td data-h=&quot;Fixed release (21 October 2026)&quot;&gt;8.5.12&lt;/td&gt;&lt;td data-h=&quot;Upstream security support ends&quot;&gt;31 Dec 2029&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;8.4&lt;/th&gt;&lt;td data-h=&quot;Fixed release (21 October 2026)&quot;&gt;8.4.27&lt;/td&gt;&lt;td data-h=&quot;Upstream security support ends&quot;&gt;31 Dec 2028&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;8.3&lt;/th&gt;&lt;td data-h=&quot;Fixed release (21 October 2026)&quot;&gt;8.3.36&lt;/td&gt;&lt;td data-h=&quot;Upstream security support ends&quot;&gt;31 Dec 2027&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;8.2&lt;/th&gt;&lt;td data-h=&quot;Fixed release (21 October 2026)&quot;&gt;8.2.35&lt;/td&gt;&lt;td data-h=&quot;Upstream security support ends&quot;&gt;31 Dec 2026&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;8.1, 8.0, 7.4&lt;/th&gt;&lt;td data-h=&quot;Fixed release (21 October 2026)&quot;&gt;none; a source patch branch for each&lt;/td&gt;&lt;td data-h=&quot;Upstream security support ends&quot;&gt;ended&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;7.3 and older&lt;/th&gt;&lt;td data-h=&quot;Fixed release (21 October 2026)&quot;&gt;none listed&lt;/td&gt;&lt;td data-h=&quot;Upstream security support ends&quot;&gt;ended&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;8.6.0&lt;/th&gt;&lt;td data-h=&quot;Fixed release (21 October 2026)&quot;&gt;RC4 carries the fix; earlier 8.6.0 builds do not&lt;/td&gt;&lt;td data-h=&quot;Upstream security support ends&quot;&gt;not released&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Sources: &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s1&quot; aria-label=&quot;source 1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s2&quot; aria-label=&quot;source 2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s3&quot; aria-label=&quot;source 3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s24&quot; aria-label=&quot;source 24&quot;&gt;24&lt;/a&gt;&lt;/sup&gt;. The patch replaces the way PHP jumped out of the code on an out-of-memory error with a soft stop at the next safe point and a hard process exit at a higher limit &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s2&quot; aria-label=&quot;source 2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Linux distributions (Ubuntu, Debian, Red Hat) use their own version numbers for the fix:&lt;/p&gt;
&lt;div class=&quot;tbl&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th scope=&quot;col&quot;&gt;System&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;Package&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;Fixed version or erratum&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;Ubuntu 26.10&lt;/th&gt;&lt;td data-h=&quot;Package&quot;&gt;php8.5&lt;/td&gt;&lt;td data-h=&quot;Fixed version or erratum&quot;&gt;8.5.9-0ubuntu2.1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;Ubuntu 26.04&lt;/th&gt;&lt;td data-h=&quot;Package&quot;&gt;php8.5&lt;/td&gt;&lt;td data-h=&quot;Fixed version or erratum&quot;&gt;8.5.4-0ubuntu1.5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;Ubuntu 24.04&lt;/th&gt;&lt;td data-h=&quot;Package&quot;&gt;php8.3&lt;/td&gt;&lt;td data-h=&quot;Fixed version or erratum&quot;&gt;8.3.6-0ubuntu0.24.04.13&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;Ubuntu 22.04&lt;/th&gt;&lt;td data-h=&quot;Package&quot;&gt;php8.1&lt;/td&gt;&lt;td data-h=&quot;Fixed version or erratum&quot;&gt;8.1.2-1ubuntu2.28&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;Ubuntu 20.04, 18.04 (Ubuntu Pro)&lt;/th&gt;&lt;td data-h=&quot;Package&quot;&gt;php7.4, php7.2&lt;/td&gt;&lt;td data-h=&quot;Fixed version or erratum&quot;&gt;7.4.3-4ubuntu2.29+esm5, 7.2.24-0ubuntu0.18.04.17+esm14&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;Debian 13&lt;/th&gt;&lt;td data-h=&quot;Package&quot;&gt;php8.4&lt;/td&gt;&lt;td data-h=&quot;Fixed version or erratum&quot;&gt;8.4.27-1~deb13u1 (DSA-6574-1)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;Debian 12&lt;/th&gt;&lt;td data-h=&quot;Package&quot;&gt;php8.2&lt;/td&gt;&lt;td data-h=&quot;Fixed version or erratum&quot;&gt;8.2.35-1~deb12u1 (DLA-4848-1)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;RHEL 10&lt;/th&gt;&lt;td data-h=&quot;Package&quot;&gt;php, php8.4&lt;/td&gt;&lt;td data-h=&quot;Fixed version or erratum&quot;&gt;8.3.36-1.el10_2, 8.4.27-1.el10_2&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;RHEL 9&lt;/th&gt;&lt;td data-h=&quot;Package&quot;&gt;php:8.2, php:8.3, php 8.0&lt;/td&gt;&lt;td data-h=&quot;Fixed version or erratum&quot;&gt;RHSA-2026:87072, 87079, 87151&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;RHEL 8&lt;/th&gt;&lt;td data-h=&quot;Package&quot;&gt;php:8.2, php:7.4&lt;/td&gt;&lt;td data-h=&quot;Fixed version or erratum&quot;&gt;RHSA-2026:87073, 87080&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Sources: Ubuntu &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s9&quot; aria-label=&quot;source 9&quot;&gt;9&lt;/a&gt;&lt;/sup&gt;, Debian &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s11&quot; aria-label=&quot;source 11&quot;&gt;11&lt;/a&gt;&lt;/sup&gt;, Red Hat &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s13&quot; aria-label=&quot;source 13&quot;&gt;13&lt;/a&gt;&lt;/sup&gt;. Red Hat&#x27;s data, checked on 24 October 2026, lists the RHEL 9 php:8.4 stream as affected with no erratum &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s13&quot; aria-label=&quot;source 13&quot;&gt;13&lt;/a&gt;&lt;/sup&gt;. On cPanel hosts, ea-php82 to ea-php85 builds with the fix became stable on 21 October, and builds numbered 8.2.35-1, 8.3.36-1, 8.4.27-1 and 8.5.12-1 followed on 23 October &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s14&quot; aria-label=&quot;source 14&quot;&gt;14&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-update-is-the-fix-the-restart-is-what-makes-&quot;&gt;The update is the fix; the restart is what makes it apply&lt;/h2&gt;
&lt;p&gt;PHP&#x27;s advisory calls the update the only complete fix &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s1&quot; aria-label=&quot;source 1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;; a running worker keeps the code it started with. Ubuntu states that updating the packages is not enough on its own; unattended-upgrades (on by default since Ubuntu 16.04) applies security updates within about 24 hours, and applications still need a restart or the system a reboot afterward &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s10&quot; aria-label=&quot;source 10&quot;&gt;10&lt;/a&gt;&lt;/sup&gt;. Red Hat states a reload is not enough and a container is replaced, not restarted in place &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s12&quot; aria-label=&quot;source 12&quot;&gt;12&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;&lt;pre data-lang=&quot;bash&quot;&gt;&lt;code&gt;# Debian, Ubuntu
sudo apt update &amp;amp;&amp;amp; sudo apt install --only-upgrade &amp;#x27;?name(^php[0-9.]+$)&amp;#x27;
sudo systemctl restart php8.3-fpm       # php-fpm; unit name follows the branch
sudo systemctl restart apache2          # mod_php
# RHEL family
sudo dnf upgrade &amp;#x27;php*&amp;#x27;
sudo systemctl restart php-fpm          # php-fpm
sudo systemctl restart httpd            # mod_php&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The apt upgrade and the apache2 restart follow Ubuntu&#x27;s notice &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s10&quot; aria-label=&quot;source 10&quot;&gt;10&lt;/a&gt;&lt;/sup&gt;; the Red Hat unit names follow Red Hat&#x27;s bulletin &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s12&quot; aria-label=&quot;source 12&quot;&gt;12&lt;/a&gt;&lt;/sup&gt;. On cPanel hosts CloudLinux names &lt;code&gt;/scripts/restartsrv_httpd&lt;/code&gt; and &lt;code&gt;/scripts/restartsrv_apache_php_fpm&lt;/code&gt; &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s14&quot; aria-label=&quot;source 14&quot;&gt;14&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;If you cannot update yet, PHP lists partial measures, which it says do not make an install safe: &lt;code&gt;session.upload_progress.enabled=0&lt;/code&gt; and, on 8.5, &lt;code&gt;fatal_error_backtraces=0&lt;/code&gt;, set in php.ini or the pool config (not &lt;code&gt;ini_set()&lt;/code&gt; or &lt;code&gt;.user.ini&lt;/code&gt;) with a restart; &lt;code&gt;memory_limit=-1&lt;/code&gt; through &lt;code&gt;php_admin_value&lt;/code&gt;; a lower &lt;code&gt;post_max_size&lt;/code&gt; &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s1&quot; aria-label=&quot;source 1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id=&quot;checking-that-no-process-still-runs-the-old-code&quot;&gt;Checking that no process still runs the old code&lt;/h2&gt;
&lt;div class=&quot;code&quot;&gt;&lt;pre data-lang=&quot;bash&quot;&gt;&lt;code&gt;sudo needrestart -r l                   # Debian, Ubuntu: lists services on outdated code, changes nothing
sudo dnf needs-restarting -s            # RHEL family: services started before an updated package
for p in $(pgrep -f php-fpm); do sudo ls -l /proc/$p/exe; done
ps -o pid,lstart,args -C php-fpm8.3     # start times later than the upgrade&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;needrestart -r l&lt;/code&gt; reports services that need a restart and makes no change &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s19&quot; aria-label=&quot;source 19&quot;&gt;19&lt;/a&gt;&lt;/sup&gt;. &lt;code&gt;needs-restarting -s&lt;/code&gt; limits its report to systemd services whose process predates an updated package &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s20&quot; aria-label=&quot;source 20&quot;&gt;20&lt;/a&gt;&lt;/sup&gt;. A &lt;code&gt;/proc/PID/exe&lt;/code&gt; link ending in &lt;code&gt;(deleted)&lt;/code&gt; marks a process started from a binary that has since been replaced &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s21&quot; aria-label=&quot;source 21&quot;&gt;21&lt;/a&gt;&lt;/sup&gt;; php-fpm and php-cgi are their own binaries, while mod_php lives inside Apache, so the Apache service is the one that carries it.&lt;/p&gt;
&lt;h2 id=&quot;cve-2026-115560-affects-updated-builds-in-one-co&quot;&gt;CVE-2026-115560 affects updated builds in one configuration&lt;/h2&gt;
&lt;p&gt;PHP&#x27;s 23 October notice names a third CVE, in session upload progress, that Cloudflare states affects patched versions including 8.5.12 &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s17&quot; aria-label=&quot;source 17&quot;&gt;17&lt;/a&gt;&lt;/sup&gt;. It needs &lt;code&gt;session.serialize_handler&lt;/code&gt; set to &lt;code&gt;php_binary&lt;/code&gt; or &lt;code&gt;php_serialize&lt;/code&gt;, an application that switches it to &lt;code&gt;php&lt;/code&gt; with &lt;code&gt;ini_set()&lt;/code&gt; before &lt;code&gt;session_start()&lt;/code&gt;, and upload progress turned on. The temporary fix is &lt;code&gt;session.upload_progress.enabled=0&lt;/code&gt; until the next regular release, which carries the full advisory &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s1&quot; aria-label=&quot;source 1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;; Red Hat states the setting fully addresses it &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s12&quot; aria-label=&quot;source 12&quot;&gt;12&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id=&quot;signs-of-a-break-in-the-sources-list-few&quot;&gt;Signs of a break-in: the sources list few&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;PHP&#x27;s advisories list no indicators of compromise, and state that clean logs do not prove safety &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s3&quot; aria-label=&quot;source 3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;&lt;li&gt;CISA names PHP worker processes launching shells or downloading tools, and points to its SIGMA detection rule &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s7&quot; aria-label=&quot;source 7&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;&lt;li&gt;Amazon names the string &lt;code&gt;PHP_SESSION_UPLOAD_PROGRESS&lt;/code&gt; in multipart POST bodies and lists six source addresses on shared anonymization networks &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s6&quot; aria-label=&quot;source 6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;&lt;li&gt;The advisory&#x27;s log audit looks for repeated warnings before target scripts run, fatal errors, and &quot;Maximum execution time exceeded&quot; &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s3&quot; aria-label=&quot;source 3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;&lt;li&gt;Sansec reports a path that returns freed worker memory in a &lt;code&gt;PHPSESSID&lt;/code&gt; cookie; that memory can hold passwords, session tokens, API keys and TLS private keys &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s15&quot; aria-label=&quot;source 15&quot;&gt;15&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id=&quot;on-hosted-sites-the-hosting-company-applies-the-&quot;&gt;On hosted sites, the hosting company applies the fix&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;The version: WordPress lists the server setup under Tools, Site Health, Info, Server &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s18&quot; aria-label=&quot;source 18&quot;&gt;18&lt;/a&gt;&lt;/sup&gt;; the &lt;code&gt;ver-check.php&lt;/code&gt; file above works through a host&#x27;s file manager; a hosting control panel&#x27;s PHP setting shows the branch it serves.&lt;/li&gt;&lt;li&gt;The fix is the host&#x27;s build. CloudLinux&#x27;s builds for cPanel hosts keep old numbers while carrying the fix, so a panel reading 8.4.26 can be patched &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s14&quot; aria-label=&quot;source 14&quot;&gt;14&lt;/a&gt;&lt;/sup&gt;. Cloudflare states that patching means the vendor&#x27;s PHP update, not only site code or plugin updates, and that a host which manages PHP applies it &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s17&quot; aria-label=&quot;source 17&quot;&gt;17&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;&lt;li&gt;Versions: 8.2.35 is the oldest fixed upstream release, and 8.2 security support ends 31 December 2026 &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s1&quot; aria-label=&quot;source 1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s24&quot; aria-label=&quot;source 24&quot;&gt;24&lt;/a&gt;&lt;/sup&gt;. PHP 8.1 and older receive no upstream update; vendors backport the fix or the site moves to a newer version &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s1&quot; aria-label=&quot;source 1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. CISA lists taking a PHP system offline if it cannot be updated, or if it runs PHP 8.1 or earlier &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s7&quot; aria-label=&quot;source 7&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;&lt;li&gt;Cloudflare&#x27;s managed WAF rules for both CVEs run by default on Free and paid plans, as an added layer beside the update &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s17&quot; aria-label=&quot;source 17&quot;&gt;17&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;&lt;/ul&gt;</content>
</entry>
<entry>
<title>One workflow, 30,000 runs a month: Zapier US$1,149, Make US$116, Cloudflare Workers US$5</title>
<link rel="alternate" type="text/html" href="https://hongdam.net/studio/notes/automation-cost-per-run/"/>
<id>tag:hongdam.net,2026-10-24:studio/automation-cost-per-run</id>
<published>2026-10-24T06:00:00+07:00</published>
<updated>2026-10-24T06:00:00+07:00</updated>
<category term="automation" label="Automation"/>
<summary>Zapier charges per action, Make per module, n8n per run. One order workflow at 30,000 runs a month costs US$1,149 on Zapier, US$116.47 on Make, €144 on n8n and US$5 as code on Cloudflare Workers. Prices as of 24 October 2026.</summary>
<content type="html">&lt;p&gt;One order workflow costs US$5 a month on Cloudflare Workers and US$1,149 on Zapier at 30,000 runs. A workflow is a chain of automatic steps, and a run is one pass through it; Zapier, Make and n8n are tools for building workflows. The workflow is the same; each platform counts a run in a different unit, and the unit decides the price.&lt;/p&gt;
&lt;h2 id=&quot;the-example-run-is-one-trigger-and-four-actions-&quot;&gt;The example run is one trigger and four actions across three apps&lt;/h2&gt;
&lt;p&gt;In the example, a web form posts each order to a webhook, a web address that passes the order&#x27;s data to the workflow. The workflow finds the customer in a Google Sheet, writes the order as a row, emails a confirmation from Gmail and posts a message in Slack. Volumes are 300, 3,000 and 30,000 runs a month, or 10, 100 and 1,000 a day. Prices are list prices taken from each vendor&#x27;s pages on 24 October 2026, for the lowest plan or tier that covers the volume, not including the fees of Google, Slack or an email provider. Euro prices are converted to US dollars where compared, at the European Central Bank reference rate of 23 October 2026, EUR 1 = US$1.1193 &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s17&quot; aria-label=&quot;source 17&quot;&gt;17&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id=&quot;one-run-is-4-tasks-5-credits-1-execution-1-reque&quot;&gt;One run is 4 tasks, 5 credits, 1 execution, 1 request or 1 minute&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;Zapier counts a task for each successful action. The trigger and built-in steps (Filter, Formatter, Paths, Delay) count 0 &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s1&quot; aria-label=&quot;source 1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s2&quot; aria-label=&quot;source 2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. The run is &lt;strong&gt;4 tasks&lt;/strong&gt;.&lt;/li&gt;&lt;li&gt;Make counts a credit for each module action, and reading an incoming webhook is one of them. Router and error-handler modules count 0 &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s3&quot; aria-label=&quot;source 3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s4&quot; aria-label=&quot;source 4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;. The run is &lt;strong&gt;5 credits&lt;/strong&gt;. Make&#x27;s pricing page dates the switch to credits as its billing unit to 27 August; its help pages say operations.&lt;/li&gt;&lt;li&gt;n8n counts a run of the whole workflow at any number of steps: &quot;An execution is a single run of your entire workflow.&quot; &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s5&quot; aria-label=&quot;source 5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; The run is &lt;strong&gt;1 execution&lt;/strong&gt;.&lt;/li&gt;&lt;li&gt;Cloudflare Workers is code that Cloudflare runs for each incoming request, so you rent no server. It bills requests, and calls the code makes outward are free. The paid Standard plan also bills CPU time, the processor time the code uses; waiting on the network does not count &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s6&quot; aria-label=&quot;source 6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;&lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s7&quot; aria-label=&quot;source 7&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;. The run is &lt;strong&gt;1 request&lt;/strong&gt;.&lt;/li&gt;&lt;li&gt;GitHub Actions bills minutes on its runners, with each job rounded up to a whole minute &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s8&quot; aria-label=&quot;source 8&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;&lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s9&quot; aria-label=&quot;source 9&quot;&gt;9&lt;/a&gt;&lt;/sup&gt;. A job that ends in seconds is &lt;strong&gt;1 minute&lt;/strong&gt;.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Per-step counting grows with the workflow. One more action moves Zapier from 4 to 5 tasks (a quarter more) and Make from 5 to 6 credits (a fifth more). n8n stays at 1 execution, and a Worker adds milliseconds of CPU time, which fall within the 30 million included at these volumes &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s6&quot; aria-label=&quot;source 6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id=&quot;at-30-000-runs-zapier-costs-about-10-times-make-&quot;&gt;At 30,000 runs, Zapier costs about 10 times Make and 230 times Cloudflare Workers&lt;/h2&gt;
&lt;div class=&quot;tbl&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th scope=&quot;col&quot;&gt;Platform and plan&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;A run counts as&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;300 runs&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;3,000 runs&lt;/th&gt;&lt;th scope=&quot;col&quot;&gt;30,000 runs&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;Zapier, Professional &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s1&quot; aria-label=&quot;source 1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/th&gt;&lt;td data-h=&quot;A run counts as&quot;&gt;4 tasks&lt;/td&gt;&lt;td data-h=&quot;300 runs&quot;&gt;US$58.50 (1,500-task tier)&lt;/td&gt;&lt;td data-h=&quot;3,000 runs&quot;&gt;US$283.50 (20,000-task tier)&lt;/td&gt;&lt;td data-h=&quot;30,000 runs&quot;&gt;US$1,149 (200,000-task tier)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;Make, Core &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s3&quot; aria-label=&quot;source 3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/th&gt;&lt;td data-h=&quot;A run counts as&quot;&gt;5 credits&lt;/td&gt;&lt;td data-h=&quot;300 runs&quot;&gt;US$10.59 (10,000-credit tier)&lt;/td&gt;&lt;td data-h=&quot;3,000 runs&quot;&gt;US$18.82 (20,000-credit tier)&lt;/td&gt;&lt;td data-h=&quot;30,000 runs&quot;&gt;US$116.47 (150,000-credit tier)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;n8n Cloud, Starter then Pro &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s5&quot; aria-label=&quot;source 5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/th&gt;&lt;td data-h=&quot;A run counts as&quot;&gt;1 execution&lt;/td&gt;&lt;td data-h=&quot;300 runs&quot;&gt;€24 (Starter, 2,500 executions)&lt;/td&gt;&lt;td data-h=&quot;3,000 runs&quot;&gt;€60 (Pro, 10,000)&lt;/td&gt;&lt;td data-h=&quot;30,000 runs&quot;&gt;€144 (Pro, 50,000)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;n8n self-hosted, Community Edition &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s5&quot; aria-label=&quot;source 5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s10&quot; aria-label=&quot;source 10&quot;&gt;10&lt;/a&gt;&lt;/sup&gt;&lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s11&quot; aria-label=&quot;source 11&quot;&gt;11&lt;/a&gt;&lt;/sup&gt;&lt;/th&gt;&lt;td data-h=&quot;A run counts as&quot;&gt;1 execution&lt;/td&gt;&lt;td data-h=&quot;300 runs&quot;&gt;€5.99 to €26.99 server, plus update hours&lt;/td&gt;&lt;td data-h=&quot;3,000 runs&quot;&gt;€5.99 to €26.99 server, plus update hours&lt;/td&gt;&lt;td data-h=&quot;30,000 runs&quot;&gt;€5.99 to €26.99 server, plus update hours&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;Cloudflare Workers, Free or Standard &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s6&quot; aria-label=&quot;source 6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;&lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s7&quot; aria-label=&quot;source 7&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;&lt;/th&gt;&lt;td data-h=&quot;A run counts as&quot;&gt;1 request&lt;/td&gt;&lt;td data-h=&quot;300 runs&quot;&gt;US$0 on Free, US$5 on Standard&lt;/td&gt;&lt;td data-h=&quot;3,000 runs&quot;&gt;US$0 on Free, US$5 on Standard&lt;/td&gt;&lt;td data-h=&quot;30,000 runs&quot;&gt;US$0 on Free, US$5 on Standard&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;GitHub Actions, Linux 2-core, private repository &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s8&quot; aria-label=&quot;source 8&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;&lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s9&quot; aria-label=&quot;source 9&quot;&gt;9&lt;/a&gt;&lt;/sup&gt;&lt;/th&gt;&lt;td data-h=&quot;A run counts as&quot;&gt;1 job minute&lt;/td&gt;&lt;td data-h=&quot;300 runs&quot;&gt;US$0 (300 of 2,000 free minutes)&lt;/td&gt;&lt;td data-h=&quot;3,000 runs&quot;&gt;US$6.00 (1,000 minutes over)&lt;/td&gt;&lt;td data-h=&quot;30,000 runs&quot;&gt;US$168.00 (28,000 minutes over)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Annual billing lowers Zapier to US$39, US$189 and US$769, Make to US$9, US$16 and US$99, and n8n Cloud to €20, €50 and €120 &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s1&quot; aria-label=&quot;source 1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s3&quot; aria-label=&quot;source 3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s5&quot; aria-label=&quot;source 5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;. The Free plans do not cover the example run: Zapier&#x27;s Free plan allows two-step Zaps and 100 tasks, Make&#x27;s Free plan covers 200 runs in its 1,000 credits, and n8n Cloud starts with a trial limited to 1,000 executions &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s1&quot; aria-label=&quot;source 1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s3&quot; aria-label=&quot;source 3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s5&quot; aria-label=&quot;source 5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;. GitHub Actions starts a job from an event, which an outside form can send with a repository_dispatch call &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s18&quot; aria-label=&quot;source 18&quot;&gt;18&lt;/a&gt;&lt;/sup&gt;; standard runners in a public repository cost nothing &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s8&quot; aria-label=&quot;source 8&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Workers Free limits each request to 10 ms of CPU time. Cloudflare reports about 2.2 ms for the average Worker and 10 to 20 ms for heavier ones, such as authentication or large payloads &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s7&quot; aria-label=&quot;source 7&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;. The example run&#x27;s CPU time is not measured here, so the table shows both plans.&lt;/p&gt;
&lt;figure class=&quot;chart&quot;&gt;&lt;table&gt;&lt;caption&gt;Monthly cost of 30,000 runs, US dollars &lt;span class=&quot;lo&quot;&gt;· lower is better&lt;/span&gt;&lt;/caption&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;Zapier Professional&lt;/th&gt;&lt;td&gt;&lt;span class=&quot;bar&quot; style=&quot;--w:100.0%&quot;&gt;&lt;/span&gt;&lt;span class=&quot;v&quot;&gt;1,149 USD&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;GitHub Actions, 28,000 billed minutes&lt;/th&gt;&lt;td&gt;&lt;span class=&quot;bar&quot; style=&quot;--w:14.6%&quot;&gt;&lt;/span&gt;&lt;span class=&quot;v&quot;&gt;168 USD&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;n8n Cloud Pro, €144&lt;/th&gt;&lt;td&gt;&lt;span class=&quot;bar&quot; style=&quot;--w:14.0%&quot;&gt;&lt;/span&gt;&lt;span class=&quot;v&quot;&gt;161.18 USD&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;Make Core&lt;/th&gt;&lt;td&gt;&lt;span class=&quot;bar&quot; style=&quot;--w:10.1%&quot;&gt;&lt;/span&gt;&lt;span class=&quot;v&quot;&gt;116.47 USD&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;n8n self-hosted, 2 vCPU 4 GB server in Singapore, €26.99&lt;/th&gt;&lt;td&gt;&lt;span class=&quot;bar&quot; style=&quot;--w:2.6%&quot;&gt;&lt;/span&gt;&lt;span class=&quot;v&quot;&gt;30.21 USD&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;n8n self-hosted, 2 vCPU 4 GB server at NBG1 or HEL1, €5.99&lt;/th&gt;&lt;td&gt;&lt;span class=&quot;bar&quot; style=&quot;--w:0.6%&quot;&gt;&lt;/span&gt;&lt;span class=&quot;v&quot;&gt;6.7 USD&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th scope=&quot;row&quot;&gt;Cloudflare Workers Standard&lt;/th&gt;&lt;td&gt;&lt;span class=&quot;bar&quot; style=&quot;--w:0.4%&quot;&gt;&lt;/span&gt;&lt;span class=&quot;v&quot;&gt;5 USD&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;figcaption&gt;Monthly billing, list prices as of 24 October 2026, euro prices at EUR 1 = US$1.1193. The n8n self-hosted bars show the server cost only, without update hours.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&quot;n8n-self-hosted-a-5-99-to-26-99-server-plus-upda&quot;&gt;n8n self-hosted: a €5.99 to €26.99 server plus update hours&lt;/h2&gt;
&lt;p&gt;Self-hosting means running n8n&#x27;s free Community Edition on a server you rent and update yourself &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s5&quot; aria-label=&quot;source 5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;. Hetzner lists a 2 vCPU (virtual processor core), 4 GB server at €5.99 a month excluding VAT at its NBG1 and HEL1 locations (CX23), and a 2 vCPU, 4 GB AMD server at €19.99 at those locations and €26.99 at SIN1 in Singapore (CPX22) &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s10&quot; aria-label=&quot;source 10&quot;&gt;10&lt;/a&gt;&lt;/sup&gt;&lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s11&quot; aria-label=&quot;source 11&quot;&gt;11&lt;/a&gt;&lt;/sup&gt;. The order line on both pages read &quot;currently unavailable&quot; on 24 October 2026. n8n&#x27;s Hetzner guide asks for at least 4 GB and 2 vCPU once its Assistant feature is added &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s12&quot; aria-label=&quot;source 12&quot;&gt;12&lt;/a&gt;&lt;/sup&gt;. The load is small: n8n&#x27;s benchmark puts one instance at up to 220 executions a second, and 30,000 runs a month average 0.012 a second &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s13&quot; aria-label=&quot;source 13&quot;&gt;13&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;The server price is the smaller part. An update is three commands, &lt;code&gt;docker compose pull&lt;/code&gt;, &lt;code&gt;docker compose down&lt;/code&gt; and &lt;code&gt;docker compose up -d&lt;/code&gt; &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s14&quot; aria-label=&quot;source 14&quot;&gt;14&lt;/a&gt;&lt;/sup&gt;. Read from GitHub on 24 October 2026, n8n published 26 releases, on 17 different days, in the 30 days to that date, and 29 security advisories on two days: 14 on 30 September and 15 on 14 October, 15 medium and 14 high severity &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s15&quot; aria-label=&quot;source 15&quot;&gt;15&lt;/a&gt;&lt;/sup&gt;&lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s16&quot; aria-label=&quot;source 16&quot;&gt;16&lt;/a&gt;&lt;/sup&gt;. At one hour per update window (time to update and test the workflow), those two days come to 2 hours a month. The hour is an assumption, not a measurement; no source times it.&lt;/p&gt;
&lt;h2 id=&quot;with-more-steps-make-costs-more-than-n8n-cloud&quot;&gt;With more steps, Make costs more than n8n Cloud&lt;/h2&gt;
&lt;ul&gt;&lt;li&gt;A ten-credit run (a trigger and nine actions) at 30,000 runs needs 300,000 Make credits, US$214.31 a month on Core, while n8n Cloud Pro stays at €144 (US$161.18) &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s3&quot; aria-label=&quot;source 3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s5&quot; aria-label=&quot;source 5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;&lt;li&gt;Up to 200 runs a month, Make&#x27;s Free plan covers the example workflow at US$0. At 300 runs the lowest paid tiers are Make US$10.59, n8n Cloud €24 (US$26.86) and Zapier US$58.50.&lt;/li&gt;&lt;li&gt;A daily job such as a price check is 30 runs a month. Zapier&#x27;s lowest Professional tier (750 tasks, US$29.99), Make&#x27;s lowest Core tier (US$10.59) and n8n Starter (€24) each cover it &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s1&quot; aria-label=&quot;source 1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s3&quot; aria-label=&quot;source 3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s5&quot; aria-label=&quot;source 5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;&lt;li&gt;Code on Cloudflare Workers or GitHub Actions has no per-step unit; its cost is the time to build and maintain it. Hongdam&#x27;s price is ฿8,000 a workflow: one trigger, up to three apps, an alert when it stops and 30 days of fixes, in n8n, Make, Zapier or code, with the tool&#x27;s own fees charged at the price we pay &lt;sup class=&quot;ref&quot;&gt;&lt;a href=&quot;#s19&quot; aria-label=&quot;source 19&quot;&gt;19&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;&lt;/ul&gt;</content>
</entry>
</feed>
