CVE-2026-42084
Description
OpenC3 COSMOS provides the functionality needed to send commands to and receive data from one or more embedded systems. Prior to versions 6.10.5 and 7.0.0-rc3, the OpenC3 password change functionality allows a user to change their password without providing the old password, by accepting a valid session token instead. In assumed breach scenarios, this behaviour can be exploited by an attacker who has already obtained a valid session token, to gain persistence in hijacked account (including admin) and prevent legitimate users from accessing the account. This issue has been patched in versions 6.10.5 and 7.0.0-rc3.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
openc3RubyGems | < 6.10.5 | 6.10.5 |
openc3RubyGems | >= 7.0.0.pre.rc1, < 7.0.0-rc3 | 7.0.0-rc3 |
Affected products
3Patches
12e623714e342Merge pull request #2905 from OpenC3/bug/set-password
4 files changed · +30 −23
openc3-cosmos-cmd-tlm-api/app/controllers/auth_controller.rb+1 −1 modified@@ -44,7 +44,7 @@ def verify end begin - if OpenC3::AuthModel.verify_no_service(params[:password], no_password: false) + if OpenC3::AuthModel.verify_no_service(params[:password], mode: :password) render :plain => OpenC3::AuthModel.generate_session() else record_user_bad_attempt
openc3/lib/openc3/models/auth_model.rb+25 −18 modified@@ -58,36 +58,43 @@ def self.verify(token, no_password: true, service_only: false) return false if service_only - return verify_no_service(token, no_password: no_password) + mode = no_password ? :token : :any + return verify_no_service(token, mode: mode) end # Checks whether the provided token is a valid user password or session token. # @param token [String] the plaintext password or session token to check (required) - # @param no_password [Boolean] enforces use of a session token (default: true) + # @param mode [String] optionally restrict verification to just the password or token. Valid values: :password, :token, or :any (default :token) # @return [Boolean] whether the provided password/token is valid - def self.verify_no_service(token, no_password: true) + def self.verify_no_service(token, mode: :token) + modes = [:password, :token, :any] + raise ArgumentError, "Invalid mode '#{mode}': must be one of #{modes}" unless modes.include?(mode) + return false if token.nil? or token.empty? # Check cached session tokens and password hash time = Time.now - return true if @@session_cache and (time - @@session_cache_time) < SESSION_CACHE_TIMEOUT and @@session_cache[token] - unless no_password - return true if @@pw_hash_cache and (time - @@pw_hash_cache_time) < PW_HASH_CACHE_TIMEOUT and Argon2::Password.verify_password(token, @@pw_hash_cache) + unless mode == :password + return true if @@session_cache and (time - @@session_cache_time) < SESSION_CACHE_TIMEOUT and @@session_cache[token] + + # Check stored session tokens + @@session_cache = Store.hgetall(SESSIONS_KEY) + @@session_cache_time = time + return true if @@session_cache[token] end - # Check stored session tokens - @@session_cache = Store.hgetall(SESSIONS_KEY) - @@session_cache_time = time - return true if @@session_cache[token] + unless mode == :token + return true if @@pw_hash_cache and (time - @@pw_hash_cache_time) < PW_HASH_CACHE_TIMEOUT and Argon2::Password.verify_password(token, @@pw_hash_cache) - return false if no_password + # Check stored password hash + pw_hash = Store.get(PRIMARY_KEY) + raise "invalid password hash" if pw_hash.nil? || !pw_hash.start_with?("$argon2") # Catch users who didn't run the migration utility when upgrading to COSMOS 7 + @@pw_hash_cache = pw_hash + @@pw_hash_cache_time = time + return true if Argon2::Password.verify_password(token, @@pw_hash_cache) + end - # Check stored password hash - pw_hash = Store.get(PRIMARY_KEY) - raise "invalid password hash" if pw_hash.nil? || !pw_hash.start_with?("$argon2") # Catch users who didn't run the migration utility when upgrading to COSMOS 7 - @@pw_hash_cache = pw_hash - @@pw_hash_cache_time = time - return Argon2::Password.verify_password(token, @@pw_hash_cache) + return false end def self.set(password, old_password, key = PRIMARY_KEY) @@ -96,7 +103,7 @@ def self.set(password, old_password, key = PRIMARY_KEY) if set?(key) raise "old_password must not be nil or empty" if old_password.nil? or old_password.empty? - raise "old_password incorrect" unless verify_no_service(old_password, no_password: false) + raise "old_password incorrect" unless verify_no_service(old_password, mode: :password) end pw_hash = Argon2::Password.create(password, profile: ARGON2_PROFILE) Store.set(key, pw_hash)
openc3/spec/models/auth_model_spec.rb+3 −3 modified@@ -43,8 +43,8 @@ module OpenC3 raise_error(/old_password incorrect/) AuthModel.set('newpassword', AUTH_INITIAL_PASSWORD) - expect(AuthModel.verify_no_service(AUTH_INITIAL_PASSWORD, no_password: false)).to eq(false) - expect(AuthModel.verify_no_service('newpassword', no_password: false)).to eq(true) + expect(AuthModel.verify_no_service(AUTH_INITIAL_PASSWORD, mode: :any)).to eq(false) + expect(AuthModel.verify_no_service('newpassword', mode: :any)).to eq(true) end it "self.verify" do @@ -63,7 +63,7 @@ module OpenC3 it "raises when stored password hash is SHA256" do @redis.set(PW_HASH_PRIMARY_KEY, Digest::SHA256.hexdigest(AUTH_INITIAL_PASSWORD)) - expect{ AuthModel.verify_no_service(AUTH_INITIAL_PASSWORD, no_password: false) }.to \ + expect{ AuthModel.verify_no_service(AUTH_INITIAL_PASSWORD, mode: :any) }.to \ raise_error(/invalid password hash/) end end
playwright/tests/auth.p.spec.ts+1 −1 modified@@ -17,7 +17,7 @@ test.describe('Auth API', () => { return } - const maxRequests = Number.parseInt(process.env.OPENC3_AUTH_RATE_LIMIT_TO || '10') + const maxRequests = Number.parseInt(process.env.OPENC3_AUTH_RATE_LIMIT_TO || '10') + 10 let gotRateLimited = false for (let i = 0; i <= maxRequests; i++) {
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/OpenC3/cosmos/commit/2e623714e3426d5ae81b6f8239d4a2a6937ef776nvdPatchWEB
- github.com/OpenC3/cosmos/security/advisories/GHSA-wgx6-g857-jjf7nvdExploitVendor AdvisoryWEB
- github.com/advisories/GHSA-wgx6-g857-jjf7ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-42084ghsaADVISORY
- github.com/OpenC3/cosmos/releases/tag/v6.10.5nvdRelease NotesWEB
- github.com/OpenC3/cosmos/releases/tag/v7.0.0-rc3nvdRelease NotesWEB
News mentions
0No linked articles in our index yet.