Skip to content

fix(oci): allow missing auths field in DockerConfig#353

Open
Mrkod-ER wants to merge 3 commits into
konflux-ci:mainfrom
Mrkod-ER:fix/docker-config-auths
Open

fix(oci): allow missing auths field in DockerConfig#353
Mrkod-ER wants to merge 3 commits into
konflux-ci:mainfrom
Mrkod-ER:fix/docker-config-auths

Conversation

@Mrkod-ER
Copy link
Copy Markdown
Contributor

@Mrkod-ER Mrkod-ER commented Mar 27, 2026

Summary

Fixes #352

Problem

By default, Docker stores credentials using base64 encoding directly inside the ~/.docker/config.json text file under the "auths" property. This is notoriously insecure because anyone with access to that file can easily read the plaintext passwords.

To solve this, Docker actively utilizes credential helpers (credsStore or credHelpers) as an alternative vault (like Apple Keychain or Windows Credential Manager) to secure authentication data deep inside the operating system. Because it is storing them securely in that external vault, Docker intentionally deletes those plaintext passwords and intrinsically does not write the auths field inside of the config.json file anymore!

This exact security behavior is explicitly confirmed by the official Docker Login Credential Store Docs:

"By default, Docker stores credentials using base64 encoding in the configuration file (~/.docker/config.json). This method is not secure because anyone with access to the file can read the credentials. A credential store provides a more secure way to handle credentials."

The Root Cause (Pydantic Crash):
The way the DockerConfig Python class was originally defined made the auths field absolutely compulsory to run.

Because Pydantic is a strict validator, defining a variable inside a class without providing a default fallback forces it to be strictly required. So, when our tool hits DockerConfig.model_validate_json() to try and read a modern, vault-secured configuration file, Pydantic immediately crashes the entire program simply because Docker successfully removed the dangerous plaintext field that our code incorrectly demanded.

The Fix: By making auths optional in the Python code via pydantic.Field(default_factory=dict), you permanently squash this fatal assumption without breaking any existing application logic around parsing tokens!

Files Changed

  • mobster/src/mobster/oci/__init__.py

Screenshots

Before (tests failing):
Screenshot 2026-03-27 191819

After (tests passing):
Screenshot 2026-03-27 192540

@snyk-io
Copy link
Copy Markdown

snyk-io Bot commented Mar 27, 2026

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@Mrkod-ER
Copy link
Copy Markdown
Contributor Author

@ralphbean could you please take a look when you get a chance?

@Allda
Copy link
Copy Markdown
Collaborator

Allda commented Mar 31, 2026

@jedinym, since you implement this par,t do you see any problem with making the field empty by default? I am bit worried it can break any logic that depends on the auths

@Allda
Copy link
Copy Markdown
Collaborator

Allda commented Mar 31, 2026

/ok-to-test

@Allda
Copy link
Copy Markdown
Collaborator

Allda commented Mar 31, 2026

/ok-to-test

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Mar 31, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.56%. Comparing base (1897df6) to head (be4cfc7).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #353   +/-   ##
=======================================
  Coverage   95.56%   95.56%           
=======================================
  Files          57       57           
  Lines        3905     3905           
=======================================
  Hits         3732     3732           
  Misses        173      173           
Flag Coverage Δ
unit-tests 95.56% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@eskultety
Copy link
Copy Markdown

@Allda you don't require any DCO nor meaningful commit messages in this project?
@Mrkod-ER Neither the linked issue nor the PR provides an authoritative reference to the docker docs on why the current Pydantic model is in fact incorrect in requiring the auths field to be present: https://docs.docker.com/reference/cli/docker/#credential-store-options and https://docs.docker.com/reference/cli/docker/login/#credential-stores which I would personally require for a successful merge.

@Mrkod-ER
Copy link
Copy Markdown
Contributor Author

Hi @eskultety, when I was running the tests locally on my own machine, I originally discovered this issue because 11 different unit tests instantly failed with a Pydantic crash. I dove deep into that issue and came to find out that my personal ~/.docker/config.json looks exactly like the official osxkeychain example from the Credential stores page you linked ( literally just {"credsStore": "desktop.exe"} with no auths field ).
in (src/mobster/oci/init.py ) the DockerConfig Python class defines the auths variable like this: auths: dict[str, AuthDetails]
Because Pydantic is a strict validator, whenever a class variable has a type definition but no default value, Pydantic treats it as strictly required.
So when Pydantic reads a perfectly valid credsStore Docker config without the auths key, it throws a fatal ValidationError: Field required and crashes the entire tool.


Screenshot 2026-03-31 221133

@Mrkod-ER
Copy link
Copy Markdown
Contributor Author

Mrkod-ER commented Apr 1, 2026

Hi @eskultety, sorry I had not properly described the problem earlier, but now I have fully updated the PR as you requested.

I added the authoritative links proving that Docker intentionally stores authentication data somewhere external (and therefore removes it from the config.json file) strictly for security reasons. The summary now clearly explains how this completely standard Docker behavior crashed the tool solely because of the strict way we originally defined that auths variable in Pydantic.

Let me know if there is anything else I can do.

@Allda
Copy link
Copy Markdown
Collaborator

Allda commented Apr 8, 2026

In general, the unit test should not touch or load any of your private auth Docker config files. It looks like these unit tests, which are failing, are not mocking the make_oci_auth_file correctly. Since in the production Mobster usescase we always require the auths to be available, I am leaning towards properly mocking these tests instead of applying the proposed fix.

If you have a capacity and would like to mock it properly, the contribution would be much appreciated. If not, I'll find someone from our team to fix it.

@Mrkod-ER
Copy link
Copy Markdown
Contributor Author

Mrkod-ER commented Apr 8, 2026

In general, the unit test should not touch or load any of your private auth Docker config files. It looks like these unit tests, which are failing, are not mocking the make_oci_auth_file correctly. Since in the production Mobster usescase we always require the auths to be available, I am leaning towards properly mocking these tests instead of applying the proposed fix.

If you have a capacity and would like to mock it properly, the contribution would be much appreciated. If not, I'll find someone from our team to fix it.

Hi @Allda, okay that makes sense, I hadn't thought about it from that angle. I'll take a look at mocking make_oci_auth_file properly and update the PR once I get it working.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tool crashes with Pydantic ValidationError when Docker config auths field is missing

4 participants