Skip to content

[SCM-1028] Fix clear password logging vulnerability #237

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

mhoffrog
Copy link

@mhoffrog mhoffrog commented Mar 31, 2025

JIRA

SCM-1028 Vulnerability: Clear text password is logged by JGit provider and by gitexe remoteinfo on a ls-remote failure

Changes

  • GitUtil.java:

    • add method maskPasswordInUrl(String urlWithCredentials)
      • implementation taken from AnonymousCommandLine.java
      • improve regex pattern to be more precise
      • replace wrapped with delimiters ':' and '@' to avoid replacing the password within probable other places of the URL to avoid password guessing by using e.g. redundant URL parameters
  • AnonymousCommandLine.java:

    • move current password masking implementation to GitUtil
    • use implementation from GitUtil
  • GitScmProviderRepository.java:

    • add method getFetchUrlWithMaskedPassword()
    • add method getPushUrlWithMaskedPassword()
    • toString():
      • 👉 BREAKING change: provide URL content with masked password to reduce risk of usage within logs or exceptions with showing passwords by that
  • JGitUtils.java:

    • method prepareSession(Git git, GitScmProviderRepository repository):
      • log using methods:
        • GitScmProviderRepository.getFetchUrlWithMaskedPassword()
        • GitScmProviderRepository.getPushUrlWithMaskedPassword()
  • GitRemoteInfoCommand.java:

    • use GitScmProviderRepository.getFetchUrlWithMaskedPassword() for exception message
  • Update JUnit tests accordingly:

    • GitScmProviderRepositoryTest.java
    • GitCommandLineUtilsTest.java

Test result

  • All JUnit tests passed

@mhoffrog
Copy link
Author

mhoffrog commented Apr 1, 2025

Fixed issue with @see in JavaDoc of GitUtil.java by recent force push.

@mhoffrog
Copy link
Author

mhoffrog commented Apr 1, 2025

fixed spotless violations

- GitUtil.java:
  - add method maskPasswordInUrl(String urlWithCredentials)
    - implementation taken from AnonymousCommandLine.java
    - improve regex pattern to be more precise
    - replace wrapped with delimiters ':' and '@' to avoid replacing
      the password within probable other places of the URL
      to avoid password guessing by using e.g. redundant URL parameters

- AnonymousCommandLine.java:
  - move current password masking implementation to GitUtil
  - use implementation from GitUtil

- GitScmProviderRepository.java:
  - add method getFetchUrlWithMaskedPassword()
  - add method getPushUrlWithMaskedPassword()
  - toString():
    - BREAKING change: provide URL content with masked password
      to reduce risk of usage within logs or exceptions
      with showing passwords by that

- JGitUtils.java:
  - method prepareSession(Git git, GitScmProviderRepository repository):
    - log using methods:
      - GitScmProviderRepository.getFetchUrlWithMaskedPassword()
      - GitScmProviderRepository.getPushUrlWithMaskedPassword()

- GitRemoteInfoCommand.java:
  - use GitScmProviderRepository.getFetchUrlWithMaskedPassword()
    for exception message

- Update JUnit tests accordingly:
  - GitScmProviderRepositoryTest.java
  - GitCommandLineUtilsTest.java
@mhoffrog
Copy link
Author

mhoffrog commented Apr 2, 2025

@michael-o Update according to resolved conversations above.

@mhoffrog mhoffrog requested a review from michael-o April 2, 2025 20:35
public static String maskPasswordInUrl(String urlWithCredentials) {
String output = urlWithCredentials;
final Matcher passwordMatcher = PASSWORD_IN_URL_PATTERN.matcher(output);
if (passwordMatcher.find()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you use find() and not matches() although your regex goes from start to end?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That code was taken 1:1 from AnonymousCommandLine.java - did not want to touch this - see comment below.

if (passwordMatcher.find()) {
// clear password with delimiters
final String clearPasswordWithDelimiters = passwordMatcher.group(1);
// to be replaced in output by stars with delimiters
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stars => asterisks

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This phrasing is being used at ScmResult.java as well. Did keep this for consistency. Shall we update it everywhere to asterisks then?

Copy link
Author

@mhoffrog mhoffrog left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@michael-o Many thanks for your review! Please find my answers accordingly and let me know if / what should be changed or improved.

public static String maskPasswordInUrl(String urlWithCredentials) {
String output = urlWithCredentials;
final Matcher passwordMatcher = PASSWORD_IN_URL_PATTERN.matcher(output);
if (passwordMatcher.find()) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That code was taken 1:1 from AnonymousCommandLine.java - did not want to touch this - see comment below.

if (passwordMatcher.find()) {
// clear password with delimiters
final String clearPasswordWithDelimiters = passwordMatcher.group(1);
// to be replaced in output by stars with delimiters
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This phrasing is being used at ScmResult.java as well. Did keep this for consistency. Shall we update it everywhere to asterisks then?

/**
* Provides an anonymous output to mask password. Considering URL of type :
* <<protocol>>://<<user>>:<<password>>@
* <<host_definition>>
*/
@Override
public String toString() {
String output = super.toString();
final Matcher passwordMatcher = passwordPattern.matcher(output);
if (passwordMatcher.find()) {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@michael-o This is the place where the find() did have been taken from - did not want to touch this.

@mhoffrog mhoffrog requested a review from michael-o April 7, 2025 09:26
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.

2 participants