Skip to content

Eval Injection via Custom Tool "Init Param" Validator Rule Allows Arbitrary JavaScript Execution

High
liuruibin published GHSA-c4xr-7rr6-43mr Oct 16, 2026

Package

1Panel-dev/MaxKB

Affected versions

<=v2.10.6-lts

Patched versions

v2.10.7-lts

Description

Summary

An Eval Injection vulnerability (resulting in arbitrary JavaScript execution, equivalent in impact to Cross-Site Scripting) exists in MaxKB's custom Tool "Init Param" feature. Any authenticated user — including an account holding only the default, lowest-privilege workspace role — can define a tool parameter whose validation rule is a raw JavaScript string. When the form that collects that parameter is opened, the stored string is passed directly to JavaScript's eval() and executes immediately, with no form submission or further interaction required beyond the form being rendered. This was confirmed by opening the affected tool's own "Debug" screen with the account that created the tool; whether a different account (e.g. another workspace member or an administrator with edit access to the tool, which the UI exposes via a separate "Init Param" management action) also triggers it was not independently re-tested in this report.

Details

  • Feature: Custom Tool creation/editing — the tool's "Init Param" definition (a parameter collected once, at tool configuration time, separate from the tool's regular runtime input parameters)
  • Vulnerable field: a validation-rule property attached to an individual init-param definition
  • Endpoints involved:
    • POST /admin/api/workspace/{workspace_id}/tool — creates the tool, accepting the parameter definitions as submitted with no rejection observed for the injected rule
    • PUT /admin/api/workspace/{workspace_id}/tool/{tool_id} — edits an existing tool's parameter definitions the same way
  • Authentication required: Yes, but only a valid login session is needed. No elevated/administrative role is required — tool creation/editing in this test was performed by an account holding only the default, non-administrative workspace role ("USER").
  • Behavior: The parameter definition, including the validation-rule content, is accepted and stored verbatim with no observed restriction on its content. When the form collecting that parameter is subsequently rendered — in this test, via the tool's own "Debug" action — the stored rule content is evaluated as live JavaScript, and any code it contains executes immediately as part of rendering the form, before any value is entered or submitted.
  • Confirmed execution: Setting the validation rule's content to alert(document.domain) caused a JavaScript alert() to fire as soon as the "Init Param" section of the tool's Debug screen was opened — before clicking "Run" and without entering any parameter value.
  • Scope of testing: Execution was confirmed for the account that created the tool, opening that same tool's own Debug screen. The application's tool-management UI exposes a separate "Init Param" action in the tool list, gated by edit permission on that specific tool, which renders the same parameter form through the same mechanism; whether a second, different account (e.g. a workspace administrator managing the shared tool library) also triggers execution through that action was not independently verified in this test.

Proof of concept

Test environment: Official Docker image 1panel/maxkb:v2.10.6-lts (latest release at time of testing).

Step 1 — Authenticate as a non-administrative account (workspace role: USER, no elevated permissions granted).

Step 2 — Create a custom tool with a malicious init-param validation rule:

POST /admin/api/workspace/default/tool HTTP/1.1
Host: 127.0.0.1:18080
Authorization: Bearer <lowpriv_token>
Content-Type: application/json

{
  "name": "xss-poc-tool-v2",
  "desc": "Eval injection PoC",
  "code": "def xss_poc_tool_v2():\n    return 'ok'",
  "input_field_list": [],
  "init_field_list": [
    {
      "field": "init_test_param",
      "label": "Init Test Param",
      "input_type": "TextInput",
      "required": false,
      "props_info": {
        "rules": [
          { "validator": "alert(document.domain)" }
        ]
      }
    }
  ]
}

Response confirms the tool, including the injected rule content, is stored and returned unmodified:

HTTP/1.1 200 OK
Content-Type: application/json

{"code": 200, "message": "Success", "data": {"id": "01a11a1d-4565-7312-906e-a1b194cc49ec", "name": "xss-poc-tool-v2", "icon": "", "desc": "Eval injection PoC", "code": "def xss_poc_tool_v2():\n    return 'ok'", "input_field_list": [], "init_field_list": [{"field": "init_test_param", "label": "Init Test Param", "required": false, "input_type": "TextInput", "props_info": {"rules": [{"validator": "alert(document.domain)"}]}}], "init_params": {}, "scope": "WORKSPACE", "is_active": false, "user_id": "01a119c9-c317-75d2-b1fe-5291104fb5a1", "template_id": null, "workspace_id": "default", "folder_id": "default", "tool_type": "CUSTOM", "label": null, "version": null, "nick_name": "lowpriv", "fileList": [], "work_flow": {}, "default_model_setting": {}, "is_publish": false}}

Step 3 — Open the newly created tool (confirming persistence via GET /admin/api/workspace/default/tool/01a11a1d-4565-7312-906e-a1b194cc49ec, which returns the same stored payload), then trigger its "Debug" action in the tool management UI (the same account that created it).

Step 4 — Observe execution: As soon as the "Init Param" section of the Debug screen is displayed, a JavaScript alert() dialog showing the application's origin (document.domain) fires — no "Run" click, no parameter value entry, and no other interaction is required.

Impact

  • Arbitrary JavaScript execution in the application's origin: Unlike markup-injection XSS, this is a direct eval() of attacker-supplied text — no HTML-escaping bypass or tag-crafting is needed; any JavaScript placed in the rule executes verbatim. This is at least as capable as a typical stored XSS and was confirmed via alert().
  • Session/credential exposure (plausible, not independently demonstrated beyond script execution): As observed throughout testing of this application, API requests are authenticated with a bearer token rather than a cookie. JavaScript executing in this origin would be expected to be able to access and exfiltrate that token from browser storage, enabling full account takeover of whoever triggers the execution. This report demonstrates script execution (alert()) only; actual token extraction/exfiltration was not performed.
  • Cross-user reach (plausible, not independently verified): The vulnerable rendering path is also reachable through a separate "Init Param" management action available to any account with edit permission on the affected tool (for a tool shared at workspace scope, this could include an administrator or other member reviewing/configuring the shared tool library), not only through the creating account's own "Debug" screen. This report confirms execution only for the creating account opening its own tool's Debug screen; execution via a second, different account was not independently tested.
  • Low attack complexity, low privilege required to inject: No administrative access is required to create the malicious tool definition — an account holding only the default, non-administrative workspace role is sufficient, as used throughout this test.
  • Account prerequisite: As with findings reported earlier for this application, exploitation requires an existing, logged-in application account; whether MaxKB offers unauthenticated public self-registration was not verified in this test.

Severity

High

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
Low
User interaction
Required
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
None

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:N

CVE ID

No known CVE

Weaknesses

Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')

The product receives input from an upstream component, but it does not neutralize or incorrectly neutralizes code syntax before using the input in a dynamic evaluation call (e.g. eval). Learn more on MITRE.

Credits