GHSA-X3G7-QRWC-F6C5

Vulnerability from github – Published: 2026-08-20 18:36 – Updated: 2026-08-20 18:36
VLAI
Summary
Ember has unneutralized terminal escape/control sequences from Caddy logs injected into the operator's TUI
Details

Summary

Ember's interactive TUI renders fields taken from the monitored Caddy server's access logs — most notably the request URI — straight to the operator's terminal without neutralising terminal escape or control sequences (CWE-150). Those log fields are populated from arbitrary, unauthenticated HTTP requests, so any remote client can embed ANSI/OSC/CSI control bytes that the operator's terminal emulator interprets when the log row is displayed. The bytes survive the whole pipeline: Caddy escapes them into its JSON access log as unicode escapes, ember's ParseLogLine decodes them back to raw 0x1b/0x07 bytes, and the row formatters concatenate them into the bubbletea View() output with no encoding before they reach os.Stdout.

Impact

An unauthenticated, remote attacker who can send HTTP requests to the Caddy server that ember monitors can inject terminal escape sequences into the operator's TUI. The trigger is a single ordinary HTTP request with control bytes in the request target. It requires no authentication; because the payload is reflected through Caddy's normal access log, it works even when ember's log listener is bound only to loopback. When the operator views the Logs tab — ember's default, zero-config mode — the terminal emulator interprets the injected sequences. Broadly-supported, demonstrated impact includes:

  • Monitoring-dashboard spoofing — CSI cursor/erase/scroll sequences forge or hide log rows so the operator misjudges the monitored server's state.
  • Clipboard hijacking (OSC 52) — attacker-chosen text is written into the operator's system clipboard, staging a payload the operator may later paste into a shell.
  • Window-title spoofing (OSC 0/2) — to support social engineering.

The impact ceiling depends on the operator's terminal emulator and usually requires a further operator action (e.g. a paste) to fully escalate; this is not general-case RCE, though specific terminal emulators have historically escalated escape sequences further. The Certificates and Routes tabs share the same unneutralised render path as secondary sinks. The --json/--once and daemon (--expose) modes are not affected, as they do not render to an interactive terminal.

References

  • https://github.com/alexandre-daubois/ember/blob/main/internal/ui/logtable.go#L18 — the unneutralised render helper (fitCellLeft) and row formatters (the sink)
  • https://github.com/alexandre-daubois/ember/blob/main/internal/fetcher/lognetlistener.go — the unauthenticated TCP access-log listener (input source)
  • https://github.com/alexandre-daubois/ember/blob/main/internal/fetcher/logentry.go — ParseLogLine, where the JSON decode restores raw control bytes
  • https://cwe.mitre.org/data/definitions/150.html — CWE-150: Improper Neutralization of Escape, Meta, or Control Sequences
Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/alexandre-daubois/ember"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "1.4.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-54162"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-150"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-08-20T18:36:01Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "## Summary\n\nEmber\u0027s interactive TUI renders fields taken from the monitored Caddy server\u0027s access logs \u2014 most notably the request URI \u2014 straight to the operator\u0027s terminal without neutralising terminal escape or control sequences (CWE-150). Those log fields are populated from arbitrary, unauthenticated HTTP requests, so any remote client can embed ANSI/OSC/CSI control bytes that the operator\u0027s terminal emulator interprets when the log row is displayed. The bytes survive the whole pipeline: Caddy escapes them into its JSON access log as unicode escapes, ember\u0027s `ParseLogLine` decodes them back to raw `0x1b`/`0x07` bytes, and the row formatters concatenate them into the bubbletea `View()` output with no encoding before they reach `os.Stdout`.\n\n## Impact\n\nAn **unauthenticated, remote** attacker who can send HTTP requests to the Caddy server that ember monitors can inject terminal escape sequences into the operator\u0027s TUI. The trigger is a single ordinary HTTP request with control bytes in the request target. It requires no authentication; because the payload is reflected through Caddy\u0027s normal access log, it works even when ember\u0027s log listener is bound only to loopback. When the operator views the Logs tab \u2014 ember\u0027s default, zero-config mode \u2014 the terminal emulator interprets the injected sequences. Broadly-supported, demonstrated impact includes:\n\n- **Monitoring-dashboard spoofing** \u2014 CSI cursor/erase/scroll sequences forge or hide log rows so the operator misjudges the monitored server\u0027s state.\n- **Clipboard hijacking (OSC 52)** \u2014 attacker-chosen text is written into the operator\u0027s system clipboard, staging a payload the operator may later paste into a shell.\n- **Window-title spoofing (OSC 0/2)** \u2014 to support social engineering.\n\nThe impact ceiling depends on the operator\u0027s terminal emulator and usually requires a further operator action (e.g. a paste) to fully escalate; this is not general-case RCE, though specific terminal emulators have historically escalated escape sequences further. The Certificates and Routes tabs share the same unneutralised render path as secondary sinks. The `--json`/`--once` and daemon (`--expose`) modes are not affected, as they do not render to an interactive terminal.\n\n## References\n\n- https://github.com/alexandre-daubois/ember/blob/main/internal/ui/logtable.go#L18 \u2014 the unneutralised render helper (`fitCellLeft`) and row formatters (the sink)\n- https://github.com/alexandre-daubois/ember/blob/main/internal/fetcher/lognetlistener.go \u2014 the unauthenticated TCP access-log listener (input source)\n- https://github.com/alexandre-daubois/ember/blob/main/internal/fetcher/logentry.go \u2014 `ParseLogLine`, where the JSON decode restores raw control bytes\n- https://cwe.mitre.org/data/definitions/150.html \u2014 CWE-150: Improper Neutralization of Escape, Meta, or Control Sequences",
  "id": "GHSA-x3g7-qrwc-f6c5",
  "modified": "2026-08-20T18:36:01Z",
  "published": "2026-08-20T18:36:01Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/alexandre-daubois/ember/security/advisories/GHSA-x3g7-qrwc-f6c5"
    },
    {
      "type": "WEB",
      "url": "https://github.com/alexandre-daubois/ember/commit/fcb7160e58dba58d6f9b5033cc312fdedc8c9f6b"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/alexandre-daubois/ember"
    },
    {
      "type": "WEB",
      "url": "https://github.com/alexandre-daubois/ember/releases/tag/v1.4.2"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:N/I:L/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Ember has unneutralized terminal escape/control sequences from Caddy logs injected into the operator\u0027s TUI"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

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.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…

Loading…