CVE-2026-77602
OpenC3 COSMOS: Authenticated remote code execution via the user-writable config overlay (table definitions, cmd/tlm definitions, and script suites)
CVE-2026-77602 is a critical vulnerability (CVSS 9.9) in Openc3 Cosmos, published September 23, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.72%, the 53rd percentile. Fixed in openc3 7.3.0.
OpenC3 COSMOS provides the functionality needed to send commands to and receive data from one or more embedded systems. From 5.1.0 until 7.3.0, authenticated non-administrator users can write content under targets_modified/ that is later executed by multiple configuration paths below the intended code-execution privilege tier. Table and command or telemetry definitions are processed through ConfigParser, PacketConfig, GENERIC_READ_CONVERSION, or GENERIC_WRITE_CONVERSION, allowing ERB rendering or Ruby and Python evaluation, while openc3-cosmos-script-runner-api/scripts/run_suite_analysis.rb executes suite procedure files through require. Storage uploads, screen saves, and script creation can place content in the overlay, and triggering table processing, a cmd/tlm reload, or suite analysis executes the content in cmd-tlm-api, decom microservices, or Script Runner with access to internal credentials and data. This issue is fixed in version 7.3.0.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
9.9
OpenC3 COSMOS: Authenticated remote code execution via the user-writable config overlay (table definitions, cmd/tlm definitions, and script suites)
OpenC3 COSMOS provides the functionality needed to send commands to and receive data from one or more embedded systems. From 5.1.0 until 7.3.0, authenticated non-administrator users can write content under targets_modified/ that is later executed by multiple configuration paths below the intended code-execution privilege tier. Table and command or telemetry definitions are processed through ConfigParser, PacketConfig, GENERIC_READ_CONVERSION, or GENERIC_WRITE_CONVERSION, allowing ERB rendering or Ruby and Python evaluation, while openc3-cosmos-script-runner-api/scripts/run_suite_analysis.rb executes suite procedure files through require. Storage uploads, screen saves, and script creation can place content in the overlay, and triggering table processing, a cmd/tlm reload, or suite analysis executes the content in cmd-tlm-api, decom microservices, or Script Runner with access to internal credentials and data. This issue is fixed in version 7.3.0.
- Record
CVE-2026-77602- CVSS 3.1
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-94
- Updated
- 2026-11-02
EUVDEUVD-2026-85566
9.9
OpenC3 COSMOS provides the functionality needed to send commands to and receive data from one or more embedded systems. From 5.1.0 until 7.3.0, authenticated non-administrator users can write content under targets_modified/ that is later executed by multiple configuration paths below the intended code-execution privilege tier. Table and command or telemetry definitions are processed through ConfigParser, PacketConfig, GENERIC_READ_CONVERSION, or GENERIC_WRITE_CONVERSION, allowing ERB rendering or Ruby and Python evaluation, while openc3-cosmos-script-runner-api/scripts/run_suite_analysis.rb executes suite procedure files through require. Storage uploads, screen saves, and script creation can place content in the overlay, and triggering table processing, a cmd/tlm reload, or suite analysis executes the content in cmd-tlm-api, decom microservices, or Script Runner with access to internal credentials and data. This issue is fixed in version 7.3.0.
- Record
EUVD-2026-85566- CVSS 3.1
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-jjq7-m736-w977
9.9
OpenC3 COSMOS: Authenticated remote code execution via the user-writable config overlay (table definitions, cmd/tlm definitions, and script suites)
Summary
COSMOS reads configuration from a user-writable overlay (targets_modified/) before the read-only plugin-installed targets/ tree, and the config subsystem executes code on those files: ConfigParser renders every file as ERB by default, a GENERIC_READ_CONVERSION / GENERIC_WRITE_CONVERSION block is evaluated as code by GenericConversion (Ruby and Python), and the Script Runner suite analysis requires a procedure file. An authenticated user can write into targets_modified/ below the admin tier (the storage-upload endpoint exempts that area from the admin gate, and the screen-save endpoint stores its body verbatim there), so the same root cause is reachable through several features, each giving arbitrary code execution on a COSMOS server.
Three vulnerable routes were identified, all reachable by an authenticated non-admin user (in the open-source edition authorize ignores the permission string, so any authenticated user qualifies):
- Table definitions (immediate).
tables#generate|report|loadreads a definition fromtargets_modified/and ERB-renders it and evaluates itsGENERIC_*_CONVERSIONblock in thecmd-tlm-apicontainer. - Command/telemetry definitions (persistent). A file written to
targets_modified/<TARGET>/cmd_tlm/is overlaid bySystem.setup_targetsand processed byPacketConfigin the decom/multi microservices: ERB-rendered in the Ruby implementation, and GENERIC-evaluated in both the Ruby and Python implementations (the PythonConfigParserdoes not run ERB). It executes on the next microservice (re)start. - Script Runner suites (immediate). A procedure written to
targets_modified/<TARGET>/procedures/isrequired by the suite analysis, reachable at the read-onlyscript_viewtier throughscripts#bodyandrunning_script#show(the analysis subprocess is spawned whenOPENC3_SERVICE_PASSWORDis configured, which it is in the shipped.env).
Details
Root cause. TargetFile.body (Ruby openc3/lib/openc3/utilities/target_file.rb, Python openc3/python/openc3/utilities/target_file.py) reads {scope}/targets_modified/{name} before {scope}/targets/{name}. The storage-upload endpoint storage_controller.rb get_upload_presigned_request is gated at system_set and exempts targets_modified/ and tmp/ from its admin check (so a write there is not admin-gated); for a target path it additionally calls authorize_bucket_path, which in the permission-enforcing edition requires tlm on the target, while in the open-source edition authorize ignores the permission string entirely. screens_controller.rb create (system_set) stores its request body verbatim under targets_modified/<target>/screens/. So a non-admin can place files in the overlay. The config subsystem then executes them.
Sink 1, ERB. ConfigParser#parse_file renders the file as ERB before parsing (run_erb defaults to true):
# openc3/lib/openc3/config/config_parser.rb:402
output = ERB.new(File.read(filename)...comment_erb(), trim_mode: "-").result(...)
Reached for table definitions via tables_controller.rb -> Table.get_definitions -> TableConfig.process_file -> parse_file, and for cmd/tlm definitions via System.setup_targets (system.rb, whose overlay loop copies targets_modified/<T>/cmd_tlm/* over the read-only files) -> PacketConfig#process_file -> parse_file.
Sink 2, GENERIC conversion. PacketConfig/TableConfig build a GenericConversion from a GENERIC_READ_CONVERSION_START .. END / GENERIC_WRITE_CONVERSION_START .. END block, and GenericConversion#call evaluates it (independent of ERB):
# openc3/lib/openc3/conversions/generic_conversion.rb (call)
eval(@code_to_eval)
# Python openc3/python/openc3/conversions/generic_conversion.py (call): compile()/exec()/eval()
The read conversion fires on tables#report/load and during telemetry decom; the write conversion fires on tables#generate and on restore_defaults.
Sink 3,…
- Record
GHSA-jjq7-m736-w977- CVSS 3.1
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-94
- Updated
- 2026-11-02
NVD
9.9
OpenC3 COSMOS provides the functionality needed to send commands to and receive data from one or more embedded systems. From 5.1.0 until 7.3.0, authenticated non-administrator users can write content under targets_modified/ that is later executed by multiple configuration paths below the intended code-execution privilege tier. Table and command or telemetry definitions are processed through ConfigParser, PacketConfig, GENERIC_READ_CONVERSION, or GENERIC_WRITE_CONVERSION, allowing ERB rendering or Ruby and Python evaluation, while openc3-cosmos-script-runner-api/scripts/run_suite_analysis.rb executes suite procedure files through require. Storage uploads, screen saves, and script creation can place content in the overlay, and triggering table processing, a cmd/tlm reload, or suite analysis executes the content in cmd-tlm-api, decom microservices, or Script Runner with access to internal credentials and data. This issue is fixed in version 7.3.0.
- Record
CVE-2026-77602- CVSS 3.1
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-94
- Updated
- 2026-11-02
OSV
9.9
OpenC3 COSMOS: Authenticated remote code execution via the user-writable config overlay (table definitions, cmd/tlm definitions, and script suites)
OpenC3 COSMOS provides the functionality needed to send commands to and receive data from one or more embedded systems. From 5.1.0 until 7.3.0, authenticated non-administrator users can write content under targets_modified/ that is later executed by multiple configuration paths below the intended code-execution privilege tier. Table and command or telemetry definitions are processed through ConfigParser, PacketConfig, GENERIC_READ_CONVERSION, or GENERIC_WRITE_CONVERSION, allowing ERB rendering or Ruby and Python evaluation, while openc3-cosmos-script-runner-api/scripts/run_suite_analysis.rb executes suite procedure files through require. Storage uploads, screen saves, and script creation can place content in the overlay, and triggering table processing, a cmd/tlm reload, or suite analysis executes the content in cmd-tlm-api, decom microservices, or Script Runner with access to internal credentials and data. This issue is fixed in version 7.3.0.
- Record
CVE-2026-77602- CVSS 3.1
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-94
- Updated
- 2026-11-02
OSVGHSA-jjq7-m736-w977
9.9
OpenC3 COSMOS: Authenticated remote code execution via the user-writable config overlay (table definitions, cmd/tlm definitions, and script suites)
Summary
COSMOS reads configuration from a user-writable overlay (targets_modified/) before the read-only plugin-installed targets/ tree, and the config subsystem executes code on those files: ConfigParser renders every file as ERB by default, a GENERIC_READ_CONVERSION / GENERIC_WRITE_CONVERSION block is evaluated as code by GenericConversion (Ruby and Python), and the Script Runner suite analysis requires a procedure file. An authenticated user can write into targets_modified/ below the admin tier (the storage-upload endpoint exempts that area from the admin gate, and the screen-save endpoint stores its body verbatim there), so the same root cause is reachable through several features, each giving arbitrary code execution on a COSMOS server.
Three vulnerable routes were identified, all reachable by an authenticated non-admin user (in the open-source edition authorize ignores the permission string, so any authenticated user qualifies):
- Table definitions (immediate).
tables#generate|report|loadreads a definition fromtargets_modified/and ERB-renders it and evaluates itsGENERIC_*_CONVERSIONblock in thecmd-tlm-apicontainer. - Command/telemetry definitions (persistent). A file written to
targets_modified/<TARGET>/cmd_tlm/is overlaid bySystem.setup_targetsand processed byPacketConfigin the decom/multi microservices: ERB-rendered in the Ruby implementation, and GENERIC-evaluated in both the Ruby and Python implementations (the PythonConfigParserdoes not run ERB). It executes on the next microservice (re)start. - Script Runner suites (immediate). A procedure written to
targets_modified/<TARGET>/procedures/isrequired by the suite analysis, reachable at the read-onlyscript_viewtier throughscripts#bodyandrunning_script#show(the analysis subprocess is spawned whenOPENC3_SERVICE_PASSWORDis configured, which it is in the shipped.env).
Details
Root cause. TargetFile.body (Ruby openc3/lib/openc3/utilities/target_file.rb, Python openc3/python/openc3/utilities/target_file.py) reads {scope}/targets_modified/{name} before {scope}/targets/{name}. The storage-upload endpoint storage_controller.rb get_upload_presigned_request is gated at system_set and exempts targets_modified/ and tmp/ from its admin check (so a write there is not admin-gated); for a target path it additionally calls authorize_bucket_path, which in the permission-enforcing edition requires tlm on the target, while in the open-source edition authorize ignores the permission string entirely. screens_controller.rb create (system_set) stores its request body verbatim under targets_modified/<target>/screens/. So a non-admin can place files in the overlay. The config subsystem then executes them.
Sink 1, ERB. ConfigParser#parse_file renders the file as ERB before parsing (run_erb defaults to true):
# openc3/lib/openc3/config/config_parser.rb:402
output = ERB.new(File.read(filename)...comment_erb(), trim_mode: "-").result(...)
Reached for table definitions via tables_controller.rb -> Table.get_definitions -> TableConfig.process_file -> parse_file, and for cmd/tlm definitions via System.setup_targets (system.rb, whose overlay loop copies targets_modified/<T>/cmd_tlm/* over the read-only files) -> PacketConfig#process_file -> parse_file.
Sink 2, GENERIC conversion. PacketConfig/TableConfig build a GenericConversion from a GENERIC_READ_CONVERSION_START .. END / GENERIC_WRITE_CONVERSION_START .. END block, and GenericConversion#call evaluates it (independent of ERB):
# openc3/lib/openc3/conversions/generic_conversion.rb (call)
eval(@code_to_eval)
# Python openc3/python/openc3/conversions/generic_conversion.py (call): compile()/exec()/eval()
The read conversion fires on tables#report/load and during telemetry decom; the write conversion fires on tables#generate and on restore_defaults.
Sink 3,…
- Record
GHSA-jjq7-m736-w977- CVSS 3.1
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-94
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
openc3RubyGems |
5.1.0 to 7.2.1 | 7.3.0 |
openc3RubyGems |
5.1.0 up to 7.3.0, plus listed versions 5.1.15.10.05.10.15.11.05.11.1 Show 45 moreShow less5.11.25.11.35.12.05.13.05.14.05.14.15.14.25.15.05.15.15.15.25.16.05.16.15.16.25.17.05.17.15.18.05.19.05.2.05.20.05.3.05.4.05.4.15.4.25.4.3.pre.beta05.5.05.5.0.pre.beta05.5.15.5.25.5.2.pre.beta05.6.05.6.15.7.05.7.25.8.05.8.15.9.05.9.16.0.06.0.16.0.26.1.06.10.06.10.16.10.26.10.3 |
7.3.0 |
History
| When | Changed | Sources |
|---|---|---|
| 2026-11-02 | created | CVE List, EUVD, GitHub Advisories, NVD, OSV |
References
github.com/OpenC3/cosmos/security/advisories/GHSA-jjq7-m736-w977
github.com/OpenC3/cosmos/pull/3488
github.com/OpenC3/cosmos/commit/71943352a28128ef3e7e894319d97a656b5cd4f2
github.com/OpenC3/cosmos/commit/7a1538a4626f82c0d1540fcaa27ffdcbbd71ff81
github.com/advisories/GHSA-jjq7-m736-w977
github.com/CVEProject/cvelistV5/tree/main/cves/2026/77xxx/CVE-2026-77602.json
nvd.nist.gov/vuln/detail/CVE-2026-77602
github.com/OpenC3/cosmos
Left out here: 27 versions and the rest of 2 source descriptions. The JSON record has them.