CVE-2019-14825
Description
A cleartext password storage issue was discovered in Katello, versions 3.x.x.x before katello 3.12.0.9. Registry credentials used during container image discovery were inadvertently logged without being masked. This flaw could expose the registry credentials to other privileged users.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Katello 3.x versions prior to 3.12.0.9 logged container registry credentials in plaintext, allowing other privileged users to capture them.
### root cause CVE-2019-14825 is a cleartext password storage vulnerability in Katello (content management plugin for Red Hat Satellite). The bug resides in the container image discovery feature. When Katello discovers container images from external registries, the authentication credentials (username and password) used for registry access were written to log files without any masking or redaction. [1][4]
### exploitation The vulnerability requires the attacker to already have privileged access to the Katello server, such that they can read log files produced by the application. No special authentication to the registry is needed beyond the credentials already stored by Katello. The attack vector is local to the system logs. [1][2]
### impact A privileged adversary who can access the application logs obtains the cleartext registry credentials. These credentials can then be reused to authenticate to the container registry directly, potentially allowing the attacker to pull or push container images, or access other resources protected by the same credentials. [1][4]
### mitigation Red Hat released an advisory RHSA-2019:3172 for Satellite 6.6, and the fix was included in Katello version 3.12.0.9. Users should update to this version or later. The GitHub pull request [3] references the fix that clears or masks the credentials from proxy settings in logs. No workarounds are documented; updating is the recommended action. [1][3]
AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
katelloRubyGems | >= 3.0.0.0, < 3.12.2 | 3.12.2 |
Affected products
2- Red Hat/katellov5Range: katello versions 3.x.x.x before katello 3.12.0.9
Patches
2332484232b66Refs #27485 - Clear proxy settings for tests
1 file changed · +1 −0
test/actions/katello/repository/discover_test.rb+1 −0 modified@@ -13,6 +13,7 @@ module Actions let(:action_class) { ::Actions::Katello::Repository::Discover } def setup + SETTINGS[:katello][:cdn_proxy] = {} get_organization #ensure we have an org label end
4eefa678a905Fixes #27485 - encrypt discovery password within task
2 files changed · +57 −12
app/lib/actions/katello/repository/discover.rb+10 −12 modified@@ -1,8 +1,9 @@ module Actions module Katello module Repository - class Discover < Actions::Base + class Discover < Actions::EntryAction include Dynflow::Action::Cancellable + include EncryptValue input_format do param :url, String @@ -17,22 +18,24 @@ class Discover < Actions::Base end def plan(url, content_type, upstream_username, upstream_password, search) - plan_self(url: url, content_type: content_type, upstream_username: upstream_username, upstream_password: upstream_password, search: search) + password = encrypt_field(upstream_password) + plan_self(url: url, content_type: content_type, upstream_username: upstream_username, upstream_password: password, search: search) end def run(event = nil) output[:repo_urls] = output[:repo_urls] || [] output[:crawled] = output[:crawled] || [] output[:to_follow] = output[:to_follow] || [input[:url]] - repo_discovery = ::Katello::RepoDiscovery.new(input[:url], input[:content_type], - input[:upstream_username], input[:upstream_password], - input[:search], proxy, - output[:crawled], output[:repo_urls], output[:to_follow]) - match(event, (on nil do unless output[:to_follow].empty? + password = decrypt_field(input[:upstream_password]) + repo_discovery = ::Katello::RepoDiscovery.new(input[:url], input[:content_type], + input[:upstream_username], password, + input[:search], proxy, + output[:crawled], output[:repo_urls], output[:to_follow]) + repo_discovery.run(output[:to_follow].shift) suspend { |suspended_action| world.clock.ping suspended_action, 0.001 } end @@ -42,11 +45,6 @@ def run(event = nil) end)) end - # @return <String> urls found by the action - def task_input - input[:url] - end - # @return [Array<String>] urls found by the action def task_output output[:repo_urls] || []
test/actions/katello/repository/discover_test.rb+47 −0 added@@ -0,0 +1,47 @@ +require 'katello_test_helper' + +module EncryptionKey + ENCRYPTION_KEY = nil +end + +module Actions + describe Katello::Repository::CloneToVersion do + include Dynflow::Testing + include Support::Actions::Fixtures + include FactoryBot::Syntax::Methods + + let(:action_class) { ::Actions::Katello::Repository::Discover } + + def setup + get_organization #ensure we have an org label + end + + def test_discovers_without_encryption + EncryptionKey.const_set(:ENCRYPTION_KEY, nil) + + mock_discovery = mock + url = 'http://foo.com' + ::Katello::RepoDiscovery.expects(:new).with(url, 'yum', 'admin', 'secret', nil, {}, [], [], [url]).returns(mock_discovery) + mock_discovery.expects(:run).with("http://foo.com").once + + task = ForemanTasks.sync_task(action_class, url, 'yum', 'admin', 'secret', nil) + + refute_empty task.input[:upstream_password] + assert_equal task.input[:upstream_password], 'secret' + end + + def test_discovers_with_hidden_password + EncryptionKey.const_set(:ENCRYPTION_KEY, 'ebf26a286b3edec3d31ac10e8e97bd60') + + mock_discovery = mock + url = 'http://foo.com' + ::Katello::RepoDiscovery.expects(:new).with(url, 'yum', 'admin', 'secret', nil, {}, [], [], [url]).returns(mock_discovery) + mock_discovery.expects(:run).with("http://foo.com").once + + task = ForemanTasks.sync_task(action_class, url, 'yum', 'admin', 'secret', nil) + + refute_empty task.input[:upstream_password] + refute_equal task.input[:upstream_password], 'secret' + end + end +end
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
14- github.com/advisories/GHSA-m4wh-848j-9w2rghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2019-14825ghsaADVISORY
- access.redhat.com/errata/RHSA-2019:3172ghsaWEB
- access.redhat.com/security/cve/CVE-2019-14825ghsaWEB
- bugzilla.redhat.com/show_bug.cgighsaWEB
- bugzilla.redhat.com/show_bug.cgighsaWEB
- bugzilla.redhat.com/show_bug.cgighsaWEB
- github.com/Katello/katello/commit/332484232b66b7907a8104a19ea97eb697b75c79ghsaWEB
- github.com/Katello/katello/commit/4eefa678a905140620ca8b390d48fe318d36e4eaghsaWEB
- github.com/Katello/katello/commits/3.12.2ghsaWEB
- github.com/Katello/katello/pull/8244ghsaWEB
- github.com/Katello/katello/pull/8253ghsaWEB
- github.com/rubysec/ruby-advisory-db/blob/master/gems/katello/CVE-2019-14825.ymlghsaWEB
- projects.theforeman.org/issues/27485ghsaWEB
News mentions
0No linked articles in our index yet.