---
title: "PHP2Shell: Critical PHP Flaw Lets Attackers Hijack Web Servers Unauthenticated"
url: https://radicalnotion.ai/blog/php2shell-critical-php-flaw-lets-attackers-hijack-web-servers-unauthenticated-20261021164259
type: article
description: "A critical PHP use-after-free (CVE-2026-109619, CVSS 9.2) lets unauthenticated attackers turn one failed request into code execution on the next. Researchers demonstrated it against default WordPress, Drupal and Joomla installs. Patches are out now."
updated: 2026-10-26
source: RadicalNotion.AI
license: CC BY-NC 4.0 (https://creativecommons.org/licenses/by-nc/4.0/)
---

# PHP2Shell: Critical PHP Flaw Lets Attackers Hijack Web Servers Unauthenticated

By Radical Notion Team, 2026-10-21

*A critical PHP use-after-free (CVE-2026-109619, CVSS 9.2) lets unauthenticated attackers turn one failed request into code execution on the next. Researchers demonstrated it against default WordPress, Drupal and Joomla installs. Patches are out now.*

PHP runs a large share of the world's websites, and the PHP project has just patched a flaw that could let an anonymous attacker take control of the servers behind them. The bug, tracked as **CVE-2026-109619** and nicknamed **PHP2Shell** by the Wiz researchers who helped find it, carries a **CVSS 4.0 score of 9.2 (Critical)**. It requires no login, no user interaction and no particular plugin. According to Wiz, researchers demonstrated it against **default deployments of WordPress, Drupal, and Joomla**. Fixed releases (PHP **8.2.35, 8.3.36, 8.4.27, and 8.5.12**) shipped on **October 21, 2026**, and anyone running PHP on an internet-facing server should treat this as a patch-today event.

---

## What Happened

On October 21, 2026, the PHP Group published GitHub Security Advisory **GHSA-6wmf-4rv5-p3rp** and the corresponding CVE record. The advisory describes a class of memory-safety bugs titled simply **RCE via stale global state**. The official description reads:

*PHP has various global state that temporarily points into request memory. In some scenarios, global state may not be correctly reset, or may be repopulated after being reset. The global state may then refer to request memory even after it has been freed. Subsequent requests may read or branch on this stale state before it is fully initialized. Multiple strategies can trigger this condition and produce remote code execution (RCE).*

The CVE record credits three reporting parties: **Wiz**, **Ryan at Calif.io**, and **OpenAI**. It credits PHP core developers **Arnaud Le Blanc, Ilija Tovilo, Jakub Zelenka, and Nora Dossche** with developing the fix. A same-day post to the **oss-security mailing list** on Openwall confirmed that the flaw enables unauthenticated remote code execution against **Apache mod****\_****php and PHP-FPM**, the two most common ways PHP is deployed in production. That post also stated that **no complete generic configuration workaround exists**.

The timeline in the Wiz Research write-up is fast. Wiz says it **discovered the vulnerability on August 19, 2026** and **demonstrated a working private exploit, called** `php2shell`**, on August 21, 2026**, two days later, against WordPress, Drupal and Joomla. Wiz **notified the PHP project on August 24, 2026**, and the vendor **acknowledged the report on September 21, 2026**. The CVE identifier was reserved on **October 12, 2026**, and the CVE record, vendor advisory and patches went public on **October 21, 2026**. Wiz states the bug was discovered and weaponized "in a matter of days with the aid of frontier AI models." That detail matters for everyone who defends web servers, and I come back to it at the end of this piece.

The U.S. Cybersecurity and Infrastructure Security Agency (CISA) added its own SSVC triage to the CVE record on publication day. It lists **Exploitation: none**, **Automatable: no**, and **Technical Impact: total**. In plain English: nobody is known to be exploiting this yet, it is not trivially wormable, but if someone succeeds they own the affected process completely.

---

## Understanding the Vulnerability

### A quick primer: why PHP workers remember things

Most production PHP does not start a fresh program for every web page. Under **PHP-FPM** (FastCGI Process Manager) or **Apache mod****\_****php**, a pool of long-lived worker processes handles request after request. Each request gets its own scratch area of memory, the **request heap**, which PHP wipes when the request finishes. The worker process itself, and certain **global variables** inside the PHP engine, persist from one request to the next.

The design assumes that any global variable pointing into the request heap gets cleared before that heap is freed. Think of a hotel housekeeper who must collect every room key before the guest's room is reassigned. CVE-2026-109619 covers cases where housekeeping gets interrupted. A key to a room that no longer belongs to anyone stays on the hook, and the next guest picks it up.

In memory-safety terms, this is a **use-after-free (UAF)**: code reads or writes memory that has already been released and may now contain something else. If an attacker can control what fills that freed memory, a UAF can often be turned into full control of the program.

The CVE record maps the flaw to five weakness categories:

| CWE | Name | How it applies |
| --- | --- | --- |
| CWE-416 | Use After Free | Global state dereferences freed request memory |
| CWE-755 | Improper Handling of Exceptional Conditions | Fatal errors, OOM, timeouts skip the cleanup path |
| CWE-824 | Access of Uninitialized Pointer | Next request reads state before it is initialized |
| CWE-1325 | Improperly Controlled Sequential Memory Allocation | Allocation failures mid-operation leave inconsistent state (OPcache) |
| CWE-1419 | Incorrect Initialization of Resource | Request startup does not reset state early enough |

The CVE record also tags the attack pattern as **CAPEC-234: Hijacking a privileged process**.

### The producer and the consumer

The PHP advisory frames exploitation as two separate HTTP requests that must be handled, one after the other, by **the exact same worker process**.

- **The producer request** makes PHP store a pointer to request-owned data in a globally accessible place. Then something interrupts execution before PHP clears that pointer. The advisory lists these interruptions:
- **The consumer request** arrives at the same worker and runs an operation early, before normal request initialization has replaced the stale pointer. That operation reads, frees, or branches on the stale pointer. The advisory names two such early operations: **pre-initialization INI diagnostics** (warnings PHP emits while processing per-request configuration) and **session upload progress handling**.

The consumer runs before the script's own error-handling settings take effect. As a result, the advisory notes that **application-level error suppression is ineffective**: turning off `display_errors` inside your code does not help, because the dangerous read happens before your code runs.

### The two primitives Wiz documented

Wiz Research describes two specific bugs, which it calls primitives, and chains them together in its private `php2shell` exploit.

**Primitive 1: fatal-error backtrace use-after-free.** PHP keeps the backtrace of the most recent fatal error in an executor-global value named `EG(last_fatal_error_backtrace)`. A backtrace is the list of function calls that led to the error. According to Wiz, an out-of-memory error can destroy the request heap **without clearing that executor-global value**. The result is a dangling pointer into freed memory, which PHP later accesses while emitting a diagnostic early in a subsequent request. The PHP advisory confirms the **fatal error backtrace producer** is specific to PHP 8.5. That is why one of the vendor's interim mitigations is the PHP 8.5 setting `fatal_error_backtraces=0`.

**Primitive 2: OPcache type confusion.** OPcache is PHP's built-in bytecode cache, enabled on most production servers. It stores compiled scripts in **shared memory** that all workers use. Wiz explains that during `zend_accel_script_persist()`, the routine that writes a compiled script into shared memory, PHP advances a process-local counter, `CG(map_ptr_last)`, *before* it publishes the matching shared counter that other workers see. If an allocation failure happens between those two steps, the two counters disagree. This worker believes certain slots are in use, while shared state still marks them available. Another worker can then reuse a slot and find stale shared metadata that **resolves to the wrong type**. That is a **type confusion**: the program treats a piece of memory as one kind of object when it is actually another. Unlike Primitive 1, this one crosses **from one worker process to another**.

Wiz says chaining these primitives yields **pre-authentication remote code execution independent of the application running on top of PHP**. It also reports **process memory disclosure**: the ability to read data left over from other users' requests.

### Illustrating the bug class

The following is **not PHP source code** and **not an exploit**. It is a simplified sketch of the general pattern described in the advisory, meant to show why an interrupted cleanup is dangerous:

```plaintext
/* Simplified illustration of the stale-global-state bug class.
 * NOT actual php-src code. */

static backtrace_t *last_fatal_bt;   /* process-global: survives across requests */

void on_fatal_error(request_t *req) {
    /* Producer: global now points INTO the request heap */
    last_fatal_bt = build_backtrace(req->heap);
    /* ...an OOM / fatal bailout jumps out here, skipping the reset... */
}

void request_shutdown(request_t *req) {
    free_request_heap(req->heap);    /* memory released... */
    /* ...but last_fatal_bt still points into it (dangling pointer) */
}

void next_request_startup(request_t *next) {
    emit_early_ini_diagnostic();     /* Consumer: touches last_fatal_bt -> use-after-free */
    last_fatal_bt = NULL;            /* the reset happens too late */
}
```

The vendor's fix, which the advisory describes as a "complete state reset patch," makes sure this kind of global state is cleared on every exit path, including the exceptional ones, and before anything in the next request can touch it.

### The attack chain, step by step

The sequence below combines the PHP advisory, the Openwall post and the Wiz write-up. The sources deliberately do not describe the heap-manipulation technique needed for reliable code execution, and neither does this article.

1. **Producer request.** The attacker sends a request that reaches a PHP operation storing request-owned state in a global location. Wiz flags **unusual multipart requests** (the format used for file uploads) as part of the observed pattern.
2. **Interruption.** The request is cut short before the state is reset. Causes include an out-of-memory fatal error, a parse or compile failure, an uncaught exception, a `require` failure, or Maximum execution time exceeded. Alternatively, a late-shutdown diagnostic repopulates the state after it was cleared.
3. **Heap freed, pointer kept.** PHP frees the request heap, but the persistent worker keeps the global pointer referring to it.
4. **Same-worker targeting.** The attacker sends a second request that must land on **the same worker process**. This is a large part of why CVSS rates attack complexity as High.
5. **Consumer request.** Early in the second request, a pre-initialization INI diagnostic or session upload progress handling reads, frees or branches on the stale pointer before initialization clears it. For the backtrace primitive, Wiz describes this as an early diagnostic touching `EG(last_fatal_error_backtrace)`, which now references freed, attacker-influenced memory.
6. **OPcache path (Wiz).** Separately, the attacker induces an allocation failure inside `zend_accel_script_persist()` between the local `CG(map_ptr_last)` advance and the shared-frontier publication. Another worker then reuses an affected slot, producing **cross-worker type confusion**.
7. **Code execution.** With a strategically arranged heap layout, the resulting memory corruption or type confusion is chained into **arbitrary code execution** with the privileges of the PHP worker process.

### Reading the CVSS 4.0 vector

The vector is `CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N`:

| Metric | Value | What it means |
| --- | --- | --- |
| Attack Vector (AV) | Network | Exploitable remotely over the internet |
| Attack Complexity (AC) | High | Requires heap shaping and precise sequencing |
| Attack Requirements (AT) | Present | Depends on deployment conditions such as persistent workers and same-worker reuse |
| Privileges Required (PR) | None | No account or login needed |
| User Interaction (UI) | None | No victim needs to click anything |
| Vulnerable System Confidentiality / Integrity / Availability | High / High / High | Full compromise of the PHP process |
| Subsequent System C/I/A | None / None / None | Score does not assume spread to other systems, though attackers can still pivot in practice |

The result is a **9.2 Critical** base score. No CVSS v3.1 score was provided by the CNA.

---

## Who Is Affected

| Vendor | Product | Affected Versions | Fixed Versions |
| --- | --- | --- | --- |
| PHP Group | PHP (php-src) | 8.2.\* before 8.2.35 | 8.2.35 |
| PHP Group | PHP (php-src) | 8.3.\* before 8.3.36 | 8.3.36 |
| PHP Group | PHP (php-src) | 8.4.\* before 8.4.27 | 8.4.27 |
| PHP Group | PHP (php-src) | 8.5.\* before 8.5.12 | 8.5.12 |

According to the PHP advisory and the Openwall post, the deployments most at risk are those using **persistent PHP workers**, chiefly **PHP-FPM** and **Apache mod****\_****php**. That covers most WordPress, Drupal, Joomla, Laravel, Magento, and custom PHP sites, along with shared hosting providers and SaaS platforms built on PHP. Wiz says it achieved RCE against **default** installs of WordPress, Drupal and Joomla, and stresses that the bug lives in PHP itself rather than in any CMS. Keeping your plugins up to date will not protect you.

The sources disagree on one important point. **Wiz states that PHP 5.4 and later releases are affected.** The PHP Group's CVE record lists only the supported 8.2 through 8.5 branches. For patching, the vendor's list is authoritative, since those are the branches that have fixes. Organizations still running end-of-life PHP (5.x, 7.x, 8.0, 8.1) should assume they are vulnerable **with no official patch coming**, and should treat this as an urgent reason to upgrade.

The intelligence picture also has gaps. The sources do not fully enumerate which SAPIs (server interfaces) beyond mod\_php and PHP-FPM are exploitable, or exactly which OPcache settings are sufficient. The advisory also mentions a related report, **GHSA-w8hw-w9fx-j79w**, but none of the analyzed sources explain how it relates to this CVE.

---

## Real-World Risk

**No confirmed exploitation in the wild, for now.** None of the three references report in-the-wild attacks, threat-actor activity, or campaigns. CISA's SSVC rating of Exploitation: none agrees, and the CVE does not appear in CISA's Known Exploited Vulnerabilities catalog as of publication. There is also **no public proof-of-concept code**; Wiz has not released `php2shell`.

That should not reassure anyone for long. Wiz's own assessment is that the public disclosure, PHP's enormous install base, and a demonstrated pre-auth RCE **make rapid exploitation likely**. Patches tell skilled attackers where to look: comparing patched and unpatched source code is standard practice. And if one research team, aided by AI models, went from discovery to working exploit in two days, defenders should not count on weeks of grace.

**What an attacker gets.** Successful exploitation runs code with the privileges of the web worker (often `www-data`, `apache`, or `nginx`). From there, according to the advisories, an attacker could reach:

- Application source code and configuration files
- Database credentials, API keys and other application secrets
- User credentials, session identifiers and cookies
- Personally identifiable information (PII) and application data
- Any files readable by the web worker
- Cloud service credentials reachable from the PHP worker
- Internal network resources, enabling **lateral movement** and **persistence**

Wiz also highlights the **memory disclosure** angle: reading leftover data from other users' requests, potentially including **passwords, authentication tokens, API keys, session identifiers, and TLS certificates** belonging to other requests or the server itself. That is reminiscent of Heartbleed-style leaks. An attacker might not even need code execution to cause damage.

**Worst case.** On **shared hosting**, many customers' sites often run on the same PHP infrastructure. A single compromised worker, or the cross-worker OPcache type confusion, could expose other tenants on the same host. Large-scale opportunistic exploitation against WordPress sites would also hand criminals a ready-made botnet for SEO spam, credit card skimming, malware hosting and phishing.

**Why it is not a 10.** Exploitation is rated **difficult**. The attacker has to steer two requests to the same worker, trigger an interruption at exactly the right moment, and shape the heap. CISA rates the flaw **not automatable**. Those hurdles slow down mass exploitation; they do not stop a determined attacker.

---

## What You Should Do

### 1. Patch now, and restart every worker

The PHP advisory and the Openwall post agree that **upgrading is the only fully reliable mitigation.** Openwall states plainly that no complete generic configuration workaround exists.

- PHP 8.2 → **8.2.35**
- PHP 8.3 → **8.3.36**
- PHP 8.4 → **8.4.27**
- PHP 8.5 → **8.5.12**

First, check what you are running. Note that the command-line PHP and the web server's PHP can differ:

```bash
# CLI version
php -v

# PHP-FPM version (binary name varies by distro)
php-fpm -v 2>/dev/null || php-fpm8.3 -v

# List PHP packages on Debian/Ubuntu
dpkg -l | grep -E '^ii\s+php[0-9.]*-(fpm|cli|common)'

# List PHP packages on RHEL/Alma/Rocky/Fedora
rpm -qa | grep -E '^php'
```

If you use distribution packages (Debian, Ubuntu, Red Hat and others), the vendor may **backport** the fix without bumping to the upstream version number. Check your distribution's security tracker rather than relying on the version string alone.

After upgrading, **fully restart all PHP workers**. A worker still running old code stays vulnerable:

```bash
# PHP-FPM (adjust service name to your version)
sudo systemctl restart php8.3-fpm

# Apache with mod_php
sudo systemctl restart apache2     # Debian/Ubuntu
sudo systemctl restart httpd       # RHEL-family

# Containers: rebuild images on the patched base and redeploy
docker pull php:8.3-fpm && docker compose up -d --build
```

### 2. Prioritize

Wiz recommends starting with internet-facing PHP applications, **especially WordPress, Drupal and Joomla**, and anything running **PHP-FPM with OPcache**. Next, audit the whole environment, including containers, CI images and forgotten staging boxes, so that no affected version or OPcache configuration remains. End-of-life PHP versions deserve particular attention because no patch is coming for them.

### 3. Interim mitigations if you truly cannot patch today

The PHP advisory lists several **partial** mitigations. None is a substitute for patching. Each must be set **administratively**, meaning in the main `php.ini` or pool configuration rather than per-request, and each requires **restarting all workers**.

**a) PHP 8.5 only: disable fatal error backtraces.** This removes the confirmed fatal backtrace producer. The trade-off is less diagnostic detail when fatal errors occur.

```plaintext
; php.ini (PHP 8.5)
fatal_error_backtraces = 0
```

**b) Disable session upload progress** to block the early session producer/consumer path. The trade-off is losing upload progress bars that rely on this feature.

```plaintext
; php.ini
session.upload_progress.enabled = 0
```

**c) Recycle PHP-FPM workers after every request.** If a worker never handles a second request, stale state has nothing to carry over into. Expect **significant performance degradation** from constant process creation.

```plaintext
; /etc/php/8.3/fpm/pool.d/www.conf
pm.max_requests = 1
```

This setting addresses the same-worker reuse that the fatal-error-backtrace and session attacks depend on.

**d) Eliminate early INI diagnostics.** Prefer static `php.ini` or pool startup configuration over per-request overrides via `.htaccess` (`php_value` / `php_flag`), `PHP_VALUE`, or `PHP_ADMIN_VALUE`, and remove deprecated or invalid directives. The advisory specifically calls out directives that trigger early deprecation notices, such as `auto_detect_line_endings=1`, `filter.default`, and legacy assert and session settings. The trade-off is less per-request configuration flexibility.

```bash
# Hunt for per-request PHP overrides
grep -rniE 'php_(value|flag|admin_value|admin_flag)' /var/www --include=.htaccess
grep -rniE 'PHP_(ADMIN_)?VALUE' /etc/nginx /etc/apache2 /etc/httpd 2>/dev/null

# Look for deprecated directives the advisory calls out
php -i | grep -Ei 'auto_detect_line_endings|filter.default|assert\.'
```

**e) Eliminate attacker-reachable fatal errors and timeouts.** Harden application paths so users cannot easily trigger fatal errors, memory exhaustion, or Maximum execution time exceeded conditions. This may require application code changes.

**f) Eliminate warnings during cleanup.** Fix warnings and diagnostics emitted during extension post-deactivation and server cleanup, which can repopulate stale state during late shutdown. This may require configuration changes and hardening of extension cleanup paths.

**g) Edge and WAF protections.** Wiz reports that out-of-the-box mitigations and WAF guidance were prepared in coordination with **Automattic, Akamai, AWS, Cloudflare, Fastly, Google, Imperva, Microsoft, and Vercel**. If your site sits behind one of these providers, confirm that the relevant rules are enabled. These rules may need tuning and **may not block every exploitation strategy**. The Openwall post likewise frames WAFs and network segmentation as defense-in-depth, not a fix.

**h) Runtime protection.** Wiz recommends eBPF-based runtime sensors that can detect and kill anomalous PHP worker behavior, and notes that **Wiz Sensor version 1.0.12768** includes such termination rules. These can interrupt workers and affect availability if they produce false positives.

### 4. Detection: what to look for in your logs

No Sigma, YARA, or formal detection signatures have been published. The PHP advisory and Wiz do describe behavioral signals. First, turn on comprehensive logging in **startup configuration**, ideally during an isolated audit:

```plaintext
; php.ini - audit logging
log_errors = On
error_reporting = E_ALL
error_log = /var/log/php/php_errors.log
```

Then review Apache, PHP-FPM, reverse proxy and service logs for:

- **Unusual multipart requests followed by memory-limit errors** or **repeated HTTP 500 responses** (Wiz)
- **Fatal out-of-memory errors followed by diagnostics in subsequent requests** on the same worker (Wiz)
- Fatal errors, parse errors, uncaught exceptions, or **Maximum execution time exceeded** entries immediately before later abnormal behavior in the same worker process (PHP advisory)
- **Repeated warnings, deprecations and core errors that occur before the target script executes** (PHP advisory)
- Warnings or diagnostics emitted during **extension or server cleanup** phases
- **Early INI deprecation notices** triggered by directives such as `auto_detect_line_endings=1`, `filter.default`, or legacy assert/session settings, especially when they come from `.htaccess`, `PHP_VALUE` or `PHP_ADMIN_VALUE` overrides
- **Session upload progress activity when your application never calls** `session_start()`, a sign of possible producer/consumer probing
- **Unexpectedly large or malformed** `PHPSESSID` **response cookies** (Wiz), which may indicate memory disclosure
- **Unexplained PHP worker churn, crashes, or abnormal recycling** in PHP-FPM logs (Wiz)

Some quick starting points:

```bash
# OOM and timeout fatals
grep -E 'Allowed memory size of [0-9]+ bytes exhausted|Maximum execution time of [0-9]+ second' /var/log/php/*.log

# Worker crashes in PHP-FPM
grep -Ei 'exited on signal|SIGSEGV|exited with code' /var/log/php*-fpm.log

# Bursts of HTTP 500s (combined log format)
awk '$9 == 500 {print $1, $4, $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
```

If you find suspicious sequences on a server that was unpatched, treat it as a potential compromise. Rotate the database credentials, API keys and secrets that the PHP process could read, invalidate user sessions, and look for web shells and unexpected scheduled jobs.

---

## The Bigger Picture

The most notable detail here may be the timeline rather than the bug. Wiz says frontier AI models helped it go from discovery to a working pre-authentication exploit against three of the web's most popular CMS platforms in **about two days**, and **OpenAI** appears in the CVE's own credits. This is a subtle bug class: an interrupted cleanup in one request, a stale pointer, and an early read in the next request, with a cross-process OPcache race as a second primitive. Bugs like this have historically taken specialists weeks or months to find and weaponize. If that work is getting faster for defenders, it is getting faster for attackers too, and the window between patch and mass exploitation will likely keep shrinking.

The flaw also shows a recurring weakness of long-running worker processes. PHP's "share nothing" reputation rests on the idea that every request starts clean. FPM and mod\_php trade some of that isolation for speed, and every global that outlives a request becomes a possible channel between strangers. The vendor's complete state-reset patch addresses this class of problem, and I expect more scrutiny of how runtimes like PHP clean up after requests fail.

Over the next several weeks, watch for:

- **Public proof-of-concept code** or patch-diff analyses, which typically drive the jump from no exploitation to mass scanning
- Any **CISA KEV** addition or change in CISA's SSVC Exploitation rating
- Clarification from the PHP project on **end-of-life versions** in light of Wiz's claim that PHP 5.4 and later are affected
- Details on the related advisory **GHSA-w8hw-w9fx-j79w**
- **Downstream distribution advisories** (Debian, Ubuntu, Red Hat, Alpine) and **managed hosting** patch status
- Exploitation attempts against **shared hosting** environments, where one worker pool can serve many tenants

The takeaway is simple. If PHP is on your attack surface, upgrade to **8.2.35, 8.3.36, 8.4.27 or 8.5.12**, restart every worker, and check your logs. If you are still on an end-of-life PHP release, this is the bug that should finally get you to upgrade.

---

## Sources

- [NVD - CVE-2026-109619](https://nvd.nist.gov/vuln/detail/CVE-2026-109619)
- [PHP Security Advisory GHSA-6wmf-4rv5-p3rp (Vendor Advisory)](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp)
- [Wiz Research - PHP2Shell: PHP Remote Code Execution](https://www.wiz.io/blog/php2shell-php-rce)
- [Openwall oss-security Mailing List Disclosure (2026-10-21)](http://www.openwall.com/lists/oss-security/2026/10/21/7)

Tags: CVE-2026-109619, PHP, remote-code-execution, use-after-free, PHP-FPM

---

Source: [RadicalNotion.AI](https://radicalnotion.ai/blog/php2shell-critical-php-flaw-lets-attackers-hijack-web-servers-unauthenticated-20261021164259). Licensed CC BY-NC 4.0; attribute RadicalNotion.AI and link the source page when you reuse this data.
