CVE-2026-39850: Verified Repro With Script Download
CVE-2026-39850: Yii2: local file inclusion via View::renderPhpFile extract of caller-controlled params
CVE-2026-39850 is verified against yiisoft/yii2 · composer. Affected versions: <= 2.0.54. Fixed in 2.0.55. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00156.
What Is CVE-2026-39850?
CVE-2026-39850 (GHSA-5vpg-rj7q-qpw2) is a high-severity local file inclusion / code injection vulnerability (CWE-98/CWE-94) in Yii2's View::renderPhpFile() method. Pruva reproduced it (reproduction REPRO-2026-00156).
CVE-2026-39850 Severity & CVSS Score
CVE-2026-39850 is rated high severity, with a CVSS base score of 7.4 out of 10.
High — serious impact or readily exploitable. Prioritize remediation.
Affected yiisoft/yii2 Versions
yiisoft/yii2 · composer versions <= 2.0.54 are affected.
How to Reproduce CVE-2026-39850
pruva-verify REPRO-2026-00156 curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00156/artifacts/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh Proof of Reproduction for CVE-2026-39850
Reproduced by Pruva's autonomous agents — 120 tool calls over 15 min. Full root-cause analysis and the complete transcript are below.
How the agent worked
Root Cause and Exploit Chain for CVE-2026-39850
Summary
CVE-2026-39850 is a Local File Inclusion (LFI) vulnerability in Yii2's View::renderPhpFile() method. The method uses extract($_params_, EXTR_OVERWRITE) before require $_file_, which allows a malicious _file_ key in the params array to overwrite the local $_file_ variable. This redirects the require statement to an attacker-controlled file path, enabling arbitrary file inclusion.
Impact
- Package:
yiisoft/yii2 - Affected versions:
<= 2.0.54 - Fixed version:
2.0.55 - CWE: CWE-98 / CWE-94 (LFI / Code Injection)
- Risk level: High (CVSS 3.1 base 7.4)
- Consequences: Attackers who control any part of the params array passed to
renderPhpFilecan read arbitrary files and potentially execute arbitrary PHP code if the included file contains PHP.
Root Cause
In yii\base\View::renderPhpFile(), the vulnerable code sequence was:
extract($_params_, EXTR_OVERWRITE);
require $_file_;
Because EXTR_OVERWRITE is used, variables in $_params_ overwrite existing local variables with the same name. If $_params_ contains a key named _file_, the local $_file_ variable (which holds the intended template path) is overwritten with the attacker-supplied value immediately before the require executes.
The fix (commit 109878b491dbffa541032bc99fb5e26d12cd0375) isolates the extract and require inside a closure:
$_renderer_ = function () {
extract(func_get_arg(1), EXTR_OVERWRITE);
require func_get_arg(0);
};
call_user_func_array($_renderer_, [$_file_, $_params_]);
Because extract runs inside the closure's local scope, it can only overwrite variables within that scope, not the $_file_ variable in the parent renderPhpFile scope. Thus the intended template path is preserved.
A similar fix was applied to yii\web\ErrorHandler::renderFile().
Reproduction Steps
The reproduction script is repro/reproduction_steps.sh.
What the script does:
- Clones the
yiisoft/yii2repository. - Creates a benign template (
safe.php) and a secret file (secret.txt). - Checks out the vulnerable tag
2.0.54. - Runs a PHP CLI script that instantiates
yii\base\Viewand callsrenderPhpFile('safe.php', ['_file_' => 'secret.txt']). - Captures the output.
- Checks out the fixed tag
2.0.55and repeats the test.
Expected evidence:
- On 2.0.54 (vulnerable), the output contains
SECRET_DATA_LINEfrom the secret file, proving LFI. - On 2.0.55 (fixed), the output contains
SAFE OUTPUTfrom the intended template, proving the fix works.
Evidence
Vulnerable build (2.0.54)
- Log:
logs/vulnerable_2.0.54.log - Excerpt:
=== RESULT === SECRET_DATA_LINE === END === VULNERABLE: _file_ param was able to override local variable and include secret file
Fixed build (2.0.55)
- Log:
logs/fixed_2.0.55.log - Excerpt:
=== RESULT === SAFE OUTPUT === END === FIXED: _file_ param did not override local variable, safe.php was rendered
Environment
- PHP 8.4.19 (cli)
- Composer 2.8.12
- Git 2.x
- Yii2 cloned from https://github.com/yiisoft/yii2
Recommendations / Next Steps
- Immediate: Upgrade
yiisoft/yii2to>= 2.0.55. - Defense in depth: Sanitize or validate user-controlled data before passing it as view params. Avoid passing raw user input directly to
renderPhpFileorrenderFile. - Testing: Add regression tests that pass
_file_and other internal variable names in view params to ensure future changes do not reintroduce scope leakage.
Additional Notes
- Idempotency: The reproduction script was run twice consecutively and produced identical results both times.
- Edge cases: The same vulnerability pattern existed in
yii\web\ErrorHandler::renderFile(), which was fixed in the same commit. The reproduction focuses onView::renderPhpFile()as the primary attack surface. - No web server required: The issue is reproducible entirely via PHP CLI, making automated testing straightforward.
CVE-2026-39850 Reproduction Transcript
The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.
Full session Replay every step — scrub the timeline or play it back.
Unknown error
Unknown error
Artifacts and Evidence for CVE-2026-39850
Scripts, logs, diffs, and output captured during the reproduction.
No artifacts available
How to Fix CVE-2026-39850
Upgrade yiisoft/yii2 · composer to 2.0.55 or later.
FAQ: CVE-2026-39850
How does the CVE-2026-39850 local file inclusion exploit work?
renderPhpFile includes a _file_ key pointing at an arbitrary path. extract($_params_, EXTR_OVERWRITE) overwrites the intended template path stored in $_file_, so the subsequent require $_file_ loads the attacker-chosen file instead — reading arbitrary files, or executing arbitrary PHP if the included file contains PHP code.Which Yii2 versions are affected by CVE-2026-39850, and where is it fixed?
109878b491dbffa541032bc99fb5e26d12cd0375, which isolates the extract and require calls inside a closure so injected _file_ keys can no longer overwrite the file path.How severe is CVE-2026-39850?
renderPhpFile can read arbitrary files and potentially execute arbitrary PHP code.How can I reproduce CVE-2026-39850?
View::renderPhpFile() with a params array containing a _file_ key pointing at an attacker-chosen file and shows that file being included instead of the intended template.References for CVE-2026-39850
Authoritative sources for CVE-2026-39850 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.