{"id":"GHSA-7hp6-g3pq-3pc3","revision":"36198b04dfc943eea54405734624c680","records":[{"revision":"36198b04dfc943eea54405734624c680","observedAt":"2026-10-24T13:19:41.952+00:00","statement":{"source":"osv","id":"GHSA-7hp6-g3pq-3pc3","aliases":["CVE-2026-47722","GO-2026-5223"],"title":"nebula-mesh: Host advanced overrides allow YAML injection into agent config.yml","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.\n\n## Exploit\nAn operator (or attacker with any operator key, given the cross-tenant CRUD advisory) sets `adv_tun_device` to:\n\n```\nnebula0\nlighthouse:\n  am_lighthouse: true\n  hosts: [\"10.0.0.1\"]\n#\n```\n\nThe 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.\n\n## Affected\nAll released versions prior to v0.3.2.\n\n## Threat model\n- **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).\n- **Combined with the critical /api/v1 authz advisory**: any operator key can mutate ANOTHER tenant's host overrides and inject YAML there.\n- **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.\n\n## Suggested fix\nTwo options, either acceptable:\n\n1. **Input validation** in `parseAdvancedFromForm` (`internal/web/advanced.go`):\n   - `ListenHost`: regex `^[A-Za-z0-9.:\\[\\]_-]+$` (IPv4/IPv6/hostname)\n   - `TunDevice`: regex `^[A-Za-z0-9_-]{1,15}$` (Linux IFNAMSIZ caps at 15)\n   Reject invalid input with a form-level error; do not write to the host row.\n\n2. **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.\n\nOption 2 is preferable long-term. Option 1 is the quick fix.\n\nThe `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.","state":0,"publishedAt":"2026-06-08T23:08:15+00:00","modifiedAt":"2026-06-25T19:56:05.1537382+00:00","affected":[{"ecosystem":"Go","name":"github.com/juev/nebula-mesh","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"0.3.2"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V4","vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"HIGH"}],"references":["https://github.com/juev/nebula-mesh/security/advisories/GHSA-7hp6-g3pq-3pc3","https://github.com/forgekeep/nebula-mesh/issues/126","https://github.com/forgekeep/nebula-mesh/commit/c1506f7344ab375a145a7449b193af3f19bb41ef","https://github.com/juev/nebula-mesh"],"sourceUrl":"https://github.com/advisories/GHSA-7hp6-g3pq-3pc3","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-7hp6-g3pq-3pc3","identifiers":["GHSA-7hp6-g3pq-3pc3","CVE-2026-47722","GO-2026-5223"]},"retained":false,"historicalAffected":[]}],"coverage":[]}