← Back to Feed CACHED · 2026-07-31 11:26:08 · CACHE_KEY CVE-2026-63222
CVE-2026-63222 · CWE-22 · Disclosed 2026-07-31

CodeIgniter is a PHP full-stack web framework.

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
Do you agree?
01 · The Real Story

Someone left the safety off the upload gun, and now any visitor can aim it at your webroot

CVE-2026-63222 is a path traversal flaw in CodeIgniter 4 prior to version 4.7.4. When application code calls UploadedFile::move() without supplying a second argument (the target filename), the framework defaults to using the raw, unsanitized client-provided filename. An attacker can inject path traversal sequences like ../../public/shell.php into the filename field of a multipart upload, writing arbitrary content outside the intended upload directory. Because this is PHP, landing a .php file in a web-accessible path typically means immediate remote code execution.

The vendor's HIGH / 7.5 score is defensible at the framework level — unauthenticated, network-reachable, low complexity. However, it overstates real-world exposure because exploitation requires the application developer to have used the one-argument form of move(). Applications that explicitly pass a server-generated filename as the second argument are not affected. The CVSS vector also scores only Integrity impact (C:N/I:H/A:N), ignoring the practical RCE chain that follows arbitrary file write in PHP environments — so it simultaneously underrates the blast radius of a successful exploit while overrating the breadth of affected deployments.

"Framework-level file-write bug is real, but only fires when devs omit a filename argument."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Identify upload endpoint

The attacker discovers a CodeIgniter 4 application that accepts file uploads. This could be a profile picture uploader, document submission form, or any multipart file handler. The endpoint must be reachable — either unauthenticated or behind credentials the attacker already has.
Conditions required:
  • CodeIgniter 4 < 4.7.4 application with a file upload endpoint
  • Endpoint reachable over HTTP/HTTPS
Where this breaks in practice:
  • Many upload endpoints sit behind authentication
  • WAFs or reverse proxies may strip path traversal sequences from filenames
Detection/coverage: Web application scanners (Burp Suite, Nuclei) can fuzz upload filename fields for path traversal acceptance.
STEP 02

Craft traversal filename

The attacker constructs a multipart POST request where the filename field in the Content-Disposition header contains path traversal sequences such as ../../../public/cmd.php. The payload is a PHP webshell or similar script. No special encoding is required — the framework passes the raw value through.
Conditions required:
  • Application calls UploadedFile::move($targetDir) without a second filename argument
  • Server filesystem permissions allow writing to the traversal target
Where this breaks in practice:
  • Developers who pass a hardcoded or generated filename as the second argument to move() are NOT vulnerable
  • open_basedir PHP restrictions may block writes outside the app root
  • Containerized deployments with read-only filesystem layers block the write
STEP 03

File lands outside upload directory

The traversal sequences resolve against the upload target directory. If the web server user has write permissions on the resolved path, the attacker's file is written. Common targets are the public/ webroot, a writable/ directory, or any path served by Apache/Nginx.
Conditions required:
  • Web server process has write permissions on the resolved target path
  • No OS-level mandatory access control (SELinux/AppArmor) blocking the write
Where this breaks in practice:
  • Hardened deployments separate the writable upload dir from the webroot
  • SELinux httpd_sys_rw_content_t labels prevent writes to unexpected paths
Detection/coverage: File integrity monitoring (OSSEC, Wazuh, Tripwire) on webroot directories will flag unexpected new .php files.
STEP 04

Remote code execution via webshell

The attacker requests the newly written PHP file via the web server. The file executes with the permissions of the PHP process, giving the attacker command execution on the host. From here, standard post-exploitation applies: credential harvesting, lateral movement, data exfiltration.
Conditions required:
  • Written file is in a path served by the web server with PHP execution enabled
  • PHP execution not disabled in the target directory via .htaccess or nginx config
Where this breaks in practice:
  • Security-conscious configs disable PHP execution in upload/static directories
  • EDR agents on the host will flag anomalous child processes spawned by the PHP worker
Detection/coverage: EDR/HIDS will detect webshell behavior patterns (e.g., www-data spawning whoami, id, or reverse shells). YARA rules for common PHP webshell signatures.
03 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationNo evidence of active exploitation as of 2026-07-31. Not listed on CISA KEV.
Proof of ConceptNo public PoC exploit identified. The traversal payload is trivial to construct (../../filename.php in the upload filename field), so weaponization requires minimal effort once a vulnerable endpoint is found.
EPSS ScoreNot yet scored — CVE disclosed today (2026-07-31). Expect low-to-moderate initial EPSS given the application-specific prerequisite.
KEV StatusNot listed on CISA KEV catalog.
CVSS VectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N — Network-accessible, no auth, no user interaction. Integrity-only impact in the vendor's assessment, but practical RCE follows in PHP environments.
Affected VersionsCodeIgniter 4 < 4.7.4 (all 4.x releases prior to the fix).
Fixed VersionCodeIgniter 4.7.4 — released 2026-07-31. Update via composer update codeigniter4/framework.
Exposure Data~120,000 live websites use CodeIgniter per BuiltWith. Subset on CI4 with the vulnerable move() pattern is significantly smaller. No Shodan/GreyNoise scanning campaigns observed.
Disclosure Date2026-07-31 (coordinated disclosure, patch available same day).
Advisory IDsGHSA-c9w5-rwh3-7pm9 (primary); GHSA-hhmc-q9hp-r662 (related upload validation hardening).
04 · The Call

noisgate verdict.

Final Verdict
= UNCHANGED to HIGH (6.5/10)

The single most decisive factor for the downgrade from 7.5 to 6.5 is the application-specific code pattern requirement: only CodeIgniter apps that call UploadedFile::move() without a second filename argument are vulnerable, materially narrowing the exploitable population below what a blanket 7.5 implies. The verdict remains HIGH rather than MEDIUM because in the subset of apps that do use this pattern, the chain from unauthenticated upload to arbitrary file write to RCE is low-friction and high-impact.

HIGH Vulnerability mechanism and affected versions
MEDIUM Fraction of CodeIgniter deployments using vulnerable code pattern
LOW Exploitation in the wild (CVE is hours old)

Why this verdict

  • Unauthenticated remote vector with low complexity — the CVSS base metrics (AV:N/AC:L/PR:N/UI:N) are accurate at the framework level; the vulnerable move() call does not validate filenames at all.
  • Application-pattern prerequisite narrows exposure — only apps calling move($dir) without the second argument are affected. Developers who generate server-side filenames (a common best practice) are immune. This meaningfully reduces the reachable population below what a 7.5 implies.
  • PHP file write = practical RCE — the vendor's Integrity-only scoring (C:N/A:N) understates the real blast radius. In PHP environments, arbitrary file write to a web-accessible path is functionally equivalent to full server compromise. This prevents a deeper downgrade.
  • Role multiplier: CodeIgniter is a general-purpose PHP web framework, not a canonically high-value infrastructure component. Typical deployments are line-of-business web applications. The blast radius of a successful exploit is per-application/per-host, not fleet-scale or identity-scale. A compromised CI4 app does not directly yield domain admin, hypervisor access, or supply-chain pivot. This role profile does not trigger the HIGH/CRITICAL floor rule.

Why not higher?

The vulnerability cannot be upgraded to CRITICAL because it requires a specific application code pattern — not all CodeIgniter 4 installations are vulnerable by default. CodeIgniter is not a canonically high-value-role component (it's not an IdP, hypervisor, domain controller, or security agent), so the blast radius is limited to the individual application host. There is no evidence of active exploitation or public PoC weaponization as of disclosure day.

Why not lower?

Despite the code-pattern prerequisite, the vulnerability cannot be reduced to MEDIUM because when the pattern IS present, the attack is unauthenticated, remotely exploitable, requires no user interaction, and results in arbitrary file write that chains trivially to RCE in PHP. The traversal payload is dead simple to construct — no specialized tooling or deep target knowledge required. The absence of exploitation evidence reflects only that the CVE is hours old.

05 · Compensating Control

What to do — in priority order.

  1. Audit application code for one-argument move() calls — Search your codebase for ->move( calls that pass only a directory argument without a filename. If found, add an explicit server-generated filename as the second argument immediately. This eliminates the vulnerability regardless of framework version. Do this within the noisgate mitigation SLA of 30 days for HIGH.
  2. Upgrade to CodeIgniter 4.7.4 — Run composer update codeigniter4/framework to pull the patched version. The fix sanitizes the default filename when no second argument is provided. Target completion within the noisgate remediation SLA of 180 days, but prefer sooner given the trivial exploit path.
  3. Disable PHP execution in upload directories — Configure your web server (Apache .htaccess with php_flag engine off, or nginx location block with deny all for .php) to prevent execution of any PHP files in upload directories. This breaks the RCE chain even if the file write succeeds.
  4. Deploy WAF rule to strip path traversal from upload filenames — Add a WAF rule (ModSecurity, Cloudflare, AWS WAF) that blocks or sanitizes multipart upload requests where the filename field in Content-Disposition contains ../ or ..\ sequences. This provides defense-in-depth at the network edge.
  5. Enable file integrity monitoring on webroot — Configure FIM (Wazuh, OSSEC, Tripwire) to alert on new .php files appearing in web-accessible directories. This won't prevent the write but ensures rapid detection of successful exploitation.
What doesn't work
  • Network segmentation alone — the upload endpoint is the application's intended public surface; network controls don't help unless you can block all untrusted uploads entirely.
  • Content-Type validation — the traversal is in the *filename* field, not the file content or MIME type. Validating that the upload is an image doesn't prevent the path traversal.
  • open_basedir in most configurationsopen_basedir restricts PHP file *reads*, but move_uploaded_file() (which UploadedFile wraps) often operates outside open_basedir restrictions depending on PHP version and SAPI.
06 · Verification

Crowdsourced verification payload.

Run this on each target host where a CodeIgniter 4 application is deployed. Requires read access to the Composer lock file in the project root. Example: bash check_cve_2026_63222.sh /var/www/myapp

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_cve_2026_63222.sh — Check for CVE-2026-63222 (CodeIgniter UploadedFile path traversal)
# Usage: bash check_cve_2026_63222.sh /path/to/codeigniter4/project
# Requires: read access to composer.lock; jq installed
# Exit codes: 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN

set -euo pipefail

PROJECT_DIR="${1:-}"

if [ -z "$PROJECT_DIR" ]; then
  echo "Usage: $0 /path/to/codeigniter4/project"
  exit 2
fi

LOCKFILE="$PROJECT_DIR/composer.lock"

if [ ! -f "$LOCKFILE" ]; then
  echo "UNKNOWN — composer.lock not found at $LOCKFILE"
  exit 2
fi

if ! command -v jq &>/dev/null; then
  echo "UNKNOWN — jq is required but not installed"
  exit 2
fi

# Extract codeigniter4/framework version from composer.lock
CI_VERSION=$(jq -r '.packages[] | select(.name == "codeigniter4/framework") | .version' "$LOCKFILE" 2>/dev/null | sed 's/^v//')

if [ -z "$CI_VERSION" ] || [ "$CI_VERSION" = "null" ]; then
  echo "UNKNOWN — codeigniter4/framework not found in composer.lock"
  exit 2
fi

echo "Detected codeigniter4/framework version: $CI_VERSION"

# Compare versions: vulnerable if < 4.7.4
# Use sort -V for version comparison
MIN_SAFE="4.7.4"
OLDEST=$(printf '%s\n%s' "$CI_VERSION" "$MIN_SAFE" | sort -V | head -n1)

if [ "$CI_VERSION" = "$MIN_SAFE" ] || [ "$OLDEST" = "$MIN_SAFE" ]; then
  echo "PATCHED — version $CI_VERSION >= $MIN_SAFE"
  exit 0
else
  echo "VULNERABLE — version $CI_VERSION < $MIN_SAFE (CVE-2026-63222)"
  # Bonus: check for vulnerable code pattern
  echo ""
  echo "Checking for potentially vulnerable move() calls (one-argument pattern):"
  grep -rn '->move(' "$PROJECT_DIR/app" --include='*.php' 2>/dev/null | grep -v ',\s*' || echo "  No one-argument move() calls found in app/ (may still exist in other dirs)"
  exit 1
fi
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning: Run a Composer audit (composer audit) or the verification script above across your CodeIgniter 4 deployments to identify instances running < 4.7.4. Simultaneously, search your codebase for ->move( calls that omit the second filename argument — those are the actually exploitable instances. For any confirmed vulnerable pattern, add an explicit server-generated filename as the second argument immediately as a code-level mitigation. Under the noisgate mitigation SLA for HIGH severity, deploy compensating controls (WAF traversal rules, disable PHP in upload dirs) within 30 days. Under the noisgate remediation SLA, upgrade all instances to CodeIgniter 4.7.4 via composer update within 180 days, though given the trivial exploit chain, pushing the Composer update this week is strongly recommended. No active exploitation is known, but weaponization is trivially easy — don't wait for a scanner to tell you someone already did it.

Sources

  1. CodeIgniter 4.7.4 Changelog
  2. GHSA-c9w5-rwh3-7pm9 — UploadedFile::move() Path Traversal
  3. CodeIgniter Uploaded Files Documentation
  4. CodeIgniter4 GitHub CHANGELOG
  5. BuiltWith — CodeIgniter Usage Statistics
  6. Enlyft — CodeIgniter Market Share
  7. FIRST EPSS Model
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.