Skip to content

Host advanced overrides allow YAML injection into agent config.yml

High
juev published GHSA-7hp6-g3pq-3pc3 May 20, 2026

Package

gomod github.com/juev/nebula-mesh (Go)

Affected versions

<= 0.3.1

Patched versions

0.3.2

Description

internal/configgen/generator.go:86,108,119 interpolates the operator-supplied ListenHost and TunDevice fields raw into a text/template that produces the agent's config.yml. internal/web/advanced.go:20-35 accepts both with only strings.TrimSpace — no character or shape validation.

Exploit

An operator (or attacker with any operator key, given the cross-tenant CRUD advisory) sets adv_tun_device to:

nebula0
lighthouse:
  am_lighthouse: true
  hosts: ["10.0.0.1"]
#

The agent fetches the rendered config on its next signed poll. On config reload, it loads the injected YAML keys: the host self-promotes to lighthouse, attracts mesh traffic, or sets am_relay: true to be selected as a relay. The ListenHost field has the same shape.

Affected

All released versions up to v0.3.0.

Threat model

  • Today: operator can compromise their own host's config (trivially allowed if they own the host, but they can also set lighthouse/relay flags that the operator-create form does NOT expose — privilege uplift within their own tenant).
  • Combined with the critical /api/v1 authz advisory: any operator key can mutate ANOTHER tenant's host overrides and inject YAML there.
  • Post-fix of the authz advisory: still relevant — the agent unconditionally trusts whatever config the server hands it, so any future operator-impersonation bug re-amplifies this.

Suggested fix

Two options, either acceptable:

  1. Input validation in parseAdvancedFromForm (internal/web/advanced.go):

    • ListenHost: regex ^[A-Za-z0-9.:\[\]_-]+$ (IPv4/IPv6/hostname)
    • TunDevice: regex ^[A-Za-z0-9_-]{1,15}$ (Linux IFNAMSIZ caps at 15)
      Reject invalid input with a form-level error; do not write to the host row.
  2. Safer marshalling: switch configgen/generator.go to marshal a typed Go struct via gopkg.in/yaml.v3 (which escapes correctly) instead of text/template string-concat. Larger change, but eliminates this entire injection class.

Option 2 is preferable long-term. Option 1 is the quick fix.

The unsafe_routes advanced field is already netip.Parse{Prefix,Addr}-validated at enroll.go:226-233 — apply the same validation discipline to the other advanced fields.

Severity

High

CVE ID

CVE-2026-47722

Weaknesses

Improper Control of Generation of Code ('Code Injection')

The product constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment. Learn more on MITRE.

Credits