Affected: gr-satellites >= 3.6.0, <= 5.9.0 (SIDS support added in commit 6e242066, 2020-11-18, first released in v3.6.0)
Severity: Medium (CVSS 3.1: 4.3, AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N)
Summary
The telemetry_servers: field in a SatYAML file accepts a
SIDS <url> entry. When present, every received frame for that
satellite is POSTed to the operator-specified URL via
urllib.request.urlopen at python/submit.py:124. The URL is not
validated beyond server.startswith('SIDS ') — no scheme allow-list,
no host allow-list, no timeout.
An operator who loads a malicious .yml from a mailing list, community
wiki, or "support for satellite X" pull request silently POSTs their
telemetry data (callsign, GPS, RF hex bytes) to whatever URL the YAML
author chose.
CPython's urllib handler set includes file://, http://,
https://, ftp://, and data:, so the attacker can read local
files (response body is discarded but the read happens), poke at
internal RFC1918 addresses, and probe localhost services.
Why this isn't an operator-misconfiguration bug
gr-satellites' own documentation doesn't warn operators to load only
trusted YAML. A grep of docs/source/ for trust, untrust,
malicious, attacker, and verify in any SatYAML context returns
zero matches. The command_line.rst:77-78 paragraph actively
encourages user-created or user-modified YAML loading without any
caveat:
"Specifying the path of a SatYAML file is useful if the user has
modified some of the files bundled with gr-satellites or has created
their own ones."
Operators reasonably treat shared YAML as benign.
What this is not
Read-only SSRF; not escalatable to RCE in v5.9.0. file:// + data=
is silently ignored by CPython's FileHandler.file_open(); gopher://,
dict://, ldap://, jar://, sftp://, tftp:// aren't in CPython's
default handler set; HTTP redirect to file:// is blocked since
CVE-2019-9948 (Python ≥ 3.7.6).
Reproduction
disclosure/bundle-2026-05-24/v2/pocs/F104-satyaml-ssrf/:
poc_F104_satyaml_ssrf.py — standalone, no GR; reimplements the
loader + urlopen path and drives it against an in-process mock
exfil listener
malicious_satellite.yml + mock_listener.py — for verifying
against a real gr_satellites install
Fix
- Add a scheme allow-list (http/https only) in
satyaml.py at YAML
load time
- Add the same allow-list as defence-in-depth in
submit.py before
urlopen()
- Add a security warning to
docs/source/satyaml.rst telling
operators to load YAML only from trusted sources
Long-form advisory
https://github.com/Marnick39/gr-satellites/blob/audit-advisories/disclosure/bundle-2026-05-24/v2/ADVISORY-08-F104-satyaml-ssrf.md
Affected: gr-satellites
>= 3.6.0, <= 5.9.0(SIDS support added in commit6e242066, 2020-11-18, first released in v3.6.0)Severity: Medium (CVSS 3.1: 4.3, AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N)
Summary
The
telemetry_servers:field in a SatYAML file accepts aSIDS <url>entry. When present, every received frame for thatsatellite is POSTed to the operator-specified URL via
urllib.request.urlopenatpython/submit.py:124. The URL is notvalidated beyond
server.startswith('SIDS ')— no scheme allow-list,no host allow-list, no timeout.
An operator who loads a malicious
.ymlfrom a mailing list, communitywiki, or "support for satellite X" pull request silently POSTs their
telemetry data (callsign, GPS, RF hex bytes) to whatever URL the YAML
author chose.
CPython's
urllibhandler set includesfile://,http://,https://,ftp://, anddata:, so the attacker can read localfiles (response body is discarded but the read happens), poke at
internal RFC1918 addresses, and probe localhost services.
Why this isn't an operator-misconfiguration bug
gr-satellites' own documentation doesn't warn operators to load only
trusted YAML. A grep of
docs/source/fortrust,untrust,malicious,attacker, andverifyin any SatYAML context returnszero matches. The
command_line.rst:77-78paragraph activelyencourages user-created or user-modified YAML loading without any
caveat:
Operators reasonably treat shared YAML as benign.
What this is not
Read-only SSRF; not escalatable to RCE in v5.9.0.
file://+data=is silently ignored by CPython's
FileHandler.file_open();gopher://,dict://,ldap://,jar://,sftp://,tftp://aren't in CPython'sdefault handler set; HTTP redirect to
file://is blocked sinceCVE-2019-9948 (Python ≥ 3.7.6).
Reproduction
disclosure/bundle-2026-05-24/v2/pocs/F104-satyaml-ssrf/:poc_F104_satyaml_ssrf.py— standalone, no GR; reimplements theloader + urlopen path and drives it against an in-process mock
exfil listener
malicious_satellite.yml+mock_listener.py— for verifyingagainst a real
gr_satellitesinstallFix
satyaml.pyat YAMLload time
submit.pybeforeurlopen()docs/source/satyaml.rsttellingoperators to load YAML only from trusted sources
Long-form advisory
https://github.com/Marnick39/gr-satellites/blob/audit-advisories/disclosure/bundle-2026-05-24/v2/ADVISORY-08-F104-satyaml-ssrf.md