Skip to main content

Algernon EUVDEUVD-2026-31869

| CVE-2026-46430 MEDIUM
Exposure of Resource to Wrong Sphere (CWE-668)
2026-05-20 https://github.com/xyproto/algernon GHSA-gj84-924c-48fx
4.3
CVSS 3.1 · Vendor: https://github.com/xyproto/algernon
Share

Severity by source

Vendor (https://github.com/xyproto/algernon) PRIMARY
4.3 MEDIUM
AV:A/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
SUSE
MEDIUM
qualitative

Primary rating from Vendor (https://github.com/xyproto/algernon).

CVSS VectorVendor: https://github.com/xyproto/algernon

Attack Vector
Adjacent
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
Low
Integrity
None
Availability
None

Lifecycle Timeline

2
Source Code Evidence Fetched
May 20, 2026 - 16:32 vuln.today
Analysis Generated
May 20, 2026 - 16:32 vuln.today

DescriptionCVE.org

Summary

The SSE event server bound to 0.0.0.0:5553 on Linux/macOS by default because the platform-dependent host default in engine/flags.go:39-46 set host = "" for non-Windows, and utils.JoinHostPort("", ":5553") resolves to ":5553" - a Go http.Server.Addr of ":5553" listens on every interface. On Windows the same code chose "localhost", binding loopback only.

The result was a platform split where the OS Algernon's dev workflow is most often used on (Linux/macOS) got the network-exposed default, and only Windows users got the loopback-safe one. A LAN peer with no developer interaction could connect to <dev-laptop-ip>:5553 and read the file-change stream.

This advisory covers the bind-address default in isolation. The fix is independent of authentication (#2a) and CORS (#2b) - switching the default to loopback can be done without touching either.

Details

Root cause - platform-dependent host default in handleFlags
go
// engine/flags.go:39-46  (1.17.6)
host := ""
if runtime.GOOS == "windows" {
    host = "localhost"
    // Default Bolt database file
    ac.defaultBoltFilename = filepath.Join(serverTempDir, "algernon.db")
    // Default log file
    ac.defaultLogFile = filepath.Join(serverTempDir, "algernon.log")
}
go
// engine/config.go:388-391  (1.17.6, finalConfiguration)
if ac.eventAddr == "" {
    ac.eventAddr = utils.JoinHostPort(host, ac.defaultEventColonPort)
}

Result tabulated:

PlatformhosteventAddr after JoinHostPortEffective bind
Linux""":5553"0.0.0.0:5553 (all interfaces)
macOS""":5553"0.0.0.0:5553 (all interfaces)
Windows"localhost""localhost:5553"127.0.0.1:5553 (loopback)

The same host value also governs the main web server bind, so the platform split affects both ports. The web-server bind on Linux/macOS is a separate (defensible) design decision - a server intended to be reachable; the SSE port is *not* such a service and inherited the same default by accident.

Why this is an independent finding

The fix is a single line: change the default host value, or change the eventAddr default specifically, to "localhost" regardless of platform. No change to authentication or CORS is required to close the network-reach half of the original bundled advisory. A LAN peer can no longer connect - the listener is unreachable from another host - even if the SSE handler still has no authentication and still returns Allow-Origin: *.

PoC (against 1.17.6 on Linux/macOS)

bash
# Operator's laptop on a hotel/cafe/office WiFi:
algernon -a /path/to/project
# => SSE listener bound to 0.0.0.0:5553
# Any peer on the same subnet:
$ curl -sN http://<dev-laptop-ip>:5553/sse
id: 0
data: /path/to/project/secret-notes.md

id: 1
data: /path/to/project/.env.local

No interaction from the developer is required. The peer needs network reach and nothing else.

Impact

  • Confidentiality: medium. LAN-bounded continuous information disclosure of filenames and edit timing.
  • Integrity: none.
  • Availability: none directly.

The CVSS vector uses AV:A (adjacent network) to model the LAN-only reach. The vector for a misconfigured deployment behind a NAT-less or routed network would shift to AV:N and rise to 5.3.

Suggestions to fix

Primary fix - pick localhost as the SSE default on every platform.

go
// engine/flags.go -- platform-independent default for the event listener
// (keep the existing platform split for the WEB server if desired, but
// not for the event server)
host := "localhost"

Or, more surgically:

go
// engine/config.go -- finalConfiguration
if ac.eventAddr == "" {
    ac.eventAddr = utils.JoinHostPort("localhost", ac.defaultEventColonPort)
}

An operator who genuinely wants LAN-reachable SSE can pass --eventserver 0.0.0.0:5553 explicitly and accept the consequences.

Stronger fix - eliminate the second listener entirely. Mount the SSE handler on the main mux at /sse. The bind address is then whatever the main server uses; there is no second listener and therefore no second bind-address default to get wrong.

Live verification

Audit-host bind check (Windows 10):

$ netstat -an | findstr 5553
  TCP    127.0.0.1:5553         0.0.0.0:0              LISTENING

Confirms the Windows default is localhost. The Linux/macOS bind to 0.0.0.0:5553 is documented in the code path above; it was not exercised on the audit machine because the audit host was Windows. A maintainer reproducing on a Linux host would see 0.0.0.0:5553 LISTENING from ss -tlnp.

AnalysisAI

Algernon's auto-refresh SSE event server unintentionally exposes developer file-change streams to unauthenticated LAN peers on Linux and macOS due to a platform-dependent bind address default that was never intended to reach adjacent hosts. On non-Windows platforms, the SSE listener resolves to 0.0.0.0:5553 (all interfaces), while Windows correctly binds to 127.0.0.1:5553 - a silent asymmetry introduced in engine/flags.go that leaves developers on the most common Algernon platforms exposed whenever they work on shared networks. A publicly available proof-of-concept demonstrates that any host on the same subnet can enumerate project filenames and edit timing with a single unauthenticated curl command, with no developer interaction required; no public exploit identified at time of analysis rises to confirmed active exploitation (not in CISA KEV).

Technical ContextAI

Algernon is a Go-based web server (pkg:go/github.com_xyproto_algernon) that provides an auto-refresh feature via a Server-Sent Events (SSE) endpoint, typically used during local development to push file-change notifications to the browser. The root cause is classified under CWE-668 (Exposure of Resource to Wrong Sphere): in engine/flags.go lines 39-46, the variable host is initialized to an empty string on non-Windows platforms and to 'localhost' on Windows. This value flows into engine/config.go (finalConfiguration) where utils.JoinHostPort('', ':5553') produces the string ':5553'. In Go's net/http package, an http.Server.Addr of ':5553' instructs the runtime to listen on every available network interface (0.0.0.0:5553), not just loopback. The SSE endpoint at /sse then streams file-change events - including full project-relative file paths - to any TCP client that connects. The same host variable governs the main web server bind address, but exposing the main server to a LAN is arguably intentional for a web server; exposing the SSE event port is not, making this an unintended resource exposure rather than a deliberate design choice.

RemediationAI

Upgrade Algernon to version 1.17.7, which is confirmed as the patched release per the GitHub advisory GHSA-gj84-924c-48fx. The fix changes the SSE event server bind address default to 'localhost' on all platforms, either by updating the host default in engine/flags.go or by hardcoding 'localhost' in the eventAddr assignment in engine/config.go, so that the SSE listener is never reachable from outside the local machine without explicit operator configuration. Full advisory details are at https://github.com/xyproto/algernon/security/advisories/GHSA-gj84-924c-48fx. If an immediate upgrade is not feasible, a compensating control is to explicitly pass the --eventserver flag with a loopback address (e.g., --eventserver 127.0.0.1:5553) on every Algernon invocation; this overrides the default and restricts the SSE listener to loopback without touching authentication or CORS. A host-based firewall rule blocking inbound connections to TCP port 5553 from non-loopback sources is an alternative control with no application-level side effects, but requires firewall management discipline and does not fix the root cause. Developers who genuinely require LAN-accessible SSE can pass --eventserver 0.0.0.0:5553 explicitly after upgrading, accepting the network exposure as a deliberate choice.

Vendor StatusVendor

SUSE

Severity: Moderate
Product Status
SUSE Linux Enterprise Server 16.1 Affected
SUSE Linux Enterprise Server for SAP applications 16.1 Affected
SUSE Linux Enterprise Module for Package Hub 15 SP5 Affected
SUSE Linux Enterprise Module for Package Hub 15 SP6 Affected
openSUSE Leap 15.5 Affected

Share

EUVD-2026-31869 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy