Skip to content

Conversation

@Arabindaksha-Mishra
Copy link
Contributor

@Arabindaksha-Mishra Arabindaksha-Mishra commented Oct 30, 2025

[Buganizer ID: 435105909] Fix: Resolve credential theft vulnerability in Bitbucket URL check

Description

What problem does this PR solve?

This PR replaces the naive string check with a robust URL parsing and validation process:

The self.repo_url is now parsed at the beginning of the init method using urlparse.

The hostname is safely extracted using parsed_url.hostname or "" to prevent errors on URLs that might not have a host (e.g., relative paths).

A new boolean, is_bitbucket_host, is created. It validates that the hostname is either exactly BITBUCKET_HOST or ends with SUB_BITBUCKET_HOST.

This secure is_bitbucket_host variable is now used in the elif condition, ensuring that the x-token-auth logic only runs for legitimate, validated Bitbucket domains.

The URL reconstruction logic was also updated to correctly use the parsed hostname and parsed_url object.

This fix not only patches the security vulnerability but also correctly handles legitimate Bitbucket subdomains (e.g., my-workspace.bitbucket.org), which a simple == check would have broken.

Checklist:

Please ensure you have completed the following items before submitting your PR.
This helps us review your contribution faster and more efficiently.

General Checks:

  • I have read and followed the project's contributing.md guide.
  • My code follows the project's coding style guidelines.
  • I have performed a self-review of my own code.
  • My changes do not introduce any new warnings.
  • My changes pass all existing tests.
  • I have added new tests where appropriate to cover my changes. (If applicable)
  • I have updated the documentation where necessary (e.g., README, API docs). (If applicable)

Open-Source Specific Checks:

  • My changes do not introduce any Personally Identifiable Information (PII) or sensitive customer data.
  • My changes do not expose any internal-only code examples, configurations, or URLs.
  • All code examples, comments, and messages are generic and suitable for a public repository.
  • I understand that any internal context or sensitive details related to this work are handled separately in internal systems (Buganizer for Google team members).

For Google Team Members and Reviewers Only:

  • I have included the Buganizer ID in the PR title or description (e.g., "Internal Buganizer ID: 123456789" or "Related Buganizer: go/buganizer/123456789").
  • I have ensured that all internal discussions and PII related to this work remain in Buganizer.

Screenshots (If Applicable)

If your changes involve UI or visual elements, please include screenshots or GIFs here.
Ensure any sensitive data is redacted or generalized.


Further Comments / Questions

Any additional comments, questions, or areas where you'd like specific feedback.

@Arabindaksha-Mishra Arabindaksha-Mishra requested a review from a team as a code owner October 30, 2025 09:34
@github-actions
Copy link

Marketplace Validation Failed

Click to view the full report

Pre-Build Validation:

Click to view details

🧩 git_sync

Validation Name Details
⚠️ Integration Version Bump project.toml and release_notes.yml files must be updated before PR

@github-actions
Copy link

Integration Tests Failed

Click to view the full report

🧩 git_sync

✅ Passed ❌ Failed ⏭️ Skipped
0 1 0

❌ Failed Tests

tests/test_defaults/test_imports.py::test_imports
def test_imports() -> None:
        """Import all integration modules to validate there are no import errors."""
>       import_all_integration_modules(common.INTEGRATION_PATH)

tests/test_defaults/test_imports.py:24: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.venv/lib/python3.11/site-packages/integration_testing/default_tests/import_test.py:39: in import_all_integration_modules
    importlib.import_module(import_)
/opt/hostedtoolcache/Python/3.11.13/x64/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
<frozen importlib._bootstrap>:1204: in _gcd_import
    ???
<frozen importlib._bootstrap>:1176: in _find_and_load
    ???
<frozen importlib._bootstrap>:1147: in _find_and_load_unlocked
    ???
<frozen importlib._bootstrap>:690: in _load_unlocked
    ???
<frozen importlib._bootstrap_external>:940: in exec_module
    ???
<frozen importlib._bootstrap>:241: in _call_with_frames_removed
    ???
jobs/PullJobs.py:20: in <module>
    from ..core.GitSyncManager import GitSyncManager
core/GitSyncManager.py:39: in <module>
    from .GitManager import Git
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    # Copyright 2025 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    from __future__ import annotations
    
    import json
    import os
    import shutil
    import stat
    from io import StringIO, IOBase
    import sys
    from typing import TYPE_CHECKING, Union, TextIO, Any
    from urllib.parse import urlparse, urlunparse
    
    import dulwich
    import paramiko.rsakey
    from dulwich import client as _mod_client
    from dulwich import porcelain
    from dulwich.contrib.paramiko_vendor import _ParamikoWrapper
    from dulwich.contrib.requests_vendor import RequestsHttpGitClient
    from dulwich.errors import GitProtocolError, HangupException
    from dulwich.object_store import tree_lookup_path
    from dulwich.objects import Blob, Commit, ShaFile, Tree
    from dulwich.refs import HEADREF, LOCAL_BRANCH_PREFIX
    from dulwich.repo import Repo
    from paramiko.ssh_exception import SSHException
    import hashlib
    import base64
    import paramiko.ed25519key
    
    
    from .definitions import File, Metadata
>   from constants import BITBUCKET_HOST,SUB_BITBUCKET_HOST
E   ModuleNotFoundError: No module named 'constants'

core/GitManager.py:44: ModuleNotFoundError

@github-actions
Copy link

Marketplace Validation Failed

Click to view the full report

Pre-Build Validation:

Click to view details

🧩 git_sync

Validation Name Details
⚠️ Uv Lock Error happened while executing a command: uv lock --check: Using CPython 3.11.13 interpreter at: /opt/hostedtoolcache/Python/3.11.13/x64/bin/python Resolved 66 packages in 786ms The lockfile at uv.lock needs to be updated, but --check was provided. To update the lockfile, run uv lock.

@github-actions
Copy link

Integration Tests Failed

Click to view the full report

🧩 git_sync

✅ Passed ❌ Failed ⏭️ Skipped
0 1 0

❌ Failed Tests

tests/test_defaults/test_imports.py::test_imports
def test_imports() -> None:
        """Import all integration modules to validate there are no import errors."""
>       import_all_integration_modules(common.INTEGRATION_PATH)

tests/test_defaults/test_imports.py:24: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.venv/lib/python3.11/site-packages/integration_testing/default_tests/import_test.py:39: in import_all_integration_modules
    importlib.import_module(import_)
/opt/hostedtoolcache/Python/3.11.13/x64/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
<frozen importlib._bootstrap>:1204: in _gcd_import
    ???
<frozen importlib._bootstrap>:1176: in _find_and_load
    ???
<frozen importlib._bootstrap>:1147: in _find_and_load_unlocked
    ???
<frozen importlib._bootstrap>:690: in _load_unlocked
    ???
<frozen importlib._bootstrap_external>:940: in exec_module
    ???
<frozen importlib._bootstrap>:241: in _call_with_frames_removed
    ???
jobs/PullJobs.py:20: in <module>
    from ..core.GitSyncManager import GitSyncManager
core/GitSyncManager.py:39: in <module>
    from .GitManager import Git
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    # Copyright 2025 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    from __future__ import annotations
    
    import json
    import os
    import shutil
    import stat
    from io import StringIO, IOBase
    import sys
    from typing import TYPE_CHECKING, Union, TextIO, Any
    from urllib.parse import urlparse, urlunparse
    
    import dulwich
    import paramiko.rsakey
    from dulwich import client as _mod_client
    from dulwich import porcelain
    from dulwich.contrib.paramiko_vendor import _ParamikoWrapper
    from dulwich.contrib.requests_vendor import RequestsHttpGitClient
    from dulwich.errors import GitProtocolError, HangupException
    from dulwich.object_store import tree_lookup_path
    from dulwich.objects import Blob, Commit, ShaFile, Tree
    from dulwich.refs import HEADREF, LOCAL_BRANCH_PREFIX
    from dulwich.repo import Repo
    from paramiko.ssh_exception import SSHException
    import hashlib
    import base64
    import paramiko.ed25519key
    
    
    from .definitions import File, Metadata
>   from constants import BITBUCKET_HOST,SUB_BITBUCKET_HOST
E   ModuleNotFoundError: No module named 'constants'

core/GitManager.py:44: ModuleNotFoundError

@github-actions
Copy link

Integration Tests Failed

Click to view the full report

🧩 git_sync

✅ Passed ❌ Failed ⏭️ Skipped
0 1 0

❌ Failed Tests

tests/test_defaults/test_imports.py::test_imports
def test_imports() -> None:
        """Import all integration modules to validate there are no import errors."""
>       import_all_integration_modules(common.INTEGRATION_PATH)

tests/test_defaults/test_imports.py:24: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.venv/lib/python3.11/site-packages/integration_testing/default_tests/import_test.py:39: in import_all_integration_modules
    importlib.import_module(import_)
/opt/hostedtoolcache/Python/3.11.13/x64/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
<frozen importlib._bootstrap>:1204: in _gcd_import
    ???
<frozen importlib._bootstrap>:1176: in _find_and_load
    ???
<frozen importlib._bootstrap>:1147: in _find_and_load_unlocked
    ???
<frozen importlib._bootstrap>:690: in _load_unlocked
    ???
<frozen importlib._bootstrap_external>:940: in exec_module
    ???
<frozen importlib._bootstrap>:241: in _call_with_frames_removed
    ???
jobs/PullJobs.py:20: in <module>
    from ..core.GitSyncManager import GitSyncManager
core/GitSyncManager.py:39: in <module>
    from .GitManager import Git
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    # Copyright 2025 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    from __future__ import annotations
    
    import json
    import os
    import shutil
    import stat
    from io import StringIO, IOBase
    import sys
    from typing import TYPE_CHECKING, Union, TextIO, Any
    from urllib.parse import urlparse, urlunparse
    
    import dulwich
    import paramiko.rsakey
    from dulwich import client as _mod_client
    from dulwich import porcelain
    from dulwich.contrib.paramiko_vendor import _ParamikoWrapper
    from dulwich.contrib.requests_vendor import RequestsHttpGitClient
    from dulwich.errors import GitProtocolError, HangupException
    from dulwich.object_store import tree_lookup_path
    from dulwich.objects import Blob, Commit, ShaFile, Tree
    from dulwich.refs import HEADREF, LOCAL_BRANCH_PREFIX
    from dulwich.repo import Repo
    from paramiko.ssh_exception import SSHException
    import hashlib
    import base64
    import paramiko.ed25519key
    
    
    from .definitions import File, Metadata
>   from constants import BITBUCKET_HOST,SUB_BITBUCKET_HOST
E   ModuleNotFoundError: No module named 'constants'

core/GitManager.py:44: ModuleNotFoundError

@github-actions
Copy link

Integration Tests Failed

Click to view the full report

🧩 git_sync

✅ Passed ❌ Failed ⏭️ Skipped
0 1 0

❌ Failed Tests

tests/test_defaults/test_imports.py::test_imports
def test_imports() -> None:
        """Import all integration modules to validate there are no import errors."""
>       import_all_integration_modules(common.INTEGRATION_PATH)

tests/test_defaults/test_imports.py:24: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.venv/lib/python3.11/site-packages/integration_testing/default_tests/import_test.py:39: in import_all_integration_modules
    importlib.import_module(import_)
/opt/hostedtoolcache/Python/3.11.13/x64/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
<frozen importlib._bootstrap>:1204: in _gcd_import
    ???
<frozen importlib._bootstrap>:1176: in _find_and_load
    ???
<frozen importlib._bootstrap>:1147: in _find_and_load_unlocked
    ???
<frozen importlib._bootstrap>:690: in _load_unlocked
    ???
<frozen importlib._bootstrap_external>:940: in exec_module
    ???
<frozen importlib._bootstrap>:241: in _call_with_frames_removed
    ???
jobs/PullJobs.py:20: in <module>
    from ..core.GitSyncManager import GitSyncManager
core/GitSyncManager.py:39: in <module>
    from .GitManager import Git
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    # Copyright 2025 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    from __future__ import annotations
    
    import json
    import os
    import shutil
    import stat
    from io import StringIO, IOBase
    import sys
    from typing import TYPE_CHECKING, Union, TextIO, Any
    from urllib.parse import urlparse, urlunparse
    
    import dulwich
    import paramiko.rsakey
    from dulwich import client as _mod_client
    from dulwich import porcelain
    from dulwich.contrib.paramiko_vendor import _ParamikoWrapper
    from dulwich.contrib.requests_vendor import RequestsHttpGitClient
    from dulwich.errors import GitProtocolError, HangupException
    from dulwich.object_store import tree_lookup_path
    from dulwich.objects import Blob, Commit, ShaFile, Tree
    from dulwich.refs import HEADREF, LOCAL_BRANCH_PREFIX
    from dulwich.repo import Repo
    from paramiko.ssh_exception import SSHException
    import hashlib
    import base64
    import paramiko.ed25519key
    
    
    from .definitions import File, Metadata
>   from constants import BITBUCKET_HOST,SUB_BITBUCKET_HOST
E   ModuleNotFoundError: No module named 'constants'

core/GitManager.py:44: ModuleNotFoundError

@Arabindaksha-Mishra Arabindaksha-Mishra changed the title Fix_Inefficient regular expression Fix_Incomplete URL substring sanitization Oct 30, 2025
@TalShafir1 TalShafir1 added the Bug Something isn't working label Nov 4, 2025
netloc = f"x-token-auth:{self.password}@{parsed.hostname}"
self.repo_url = urlunparse(parsed._replace(netloc=netloc))
elif is_bitbucket_host and "x-token-auth" not in self.repo_url:
# This is now secure AND flexible
Copy link
Member

Choose a reason for hiding this comment

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

Please remove the comment

Suggested change
# This is now secure AND flexible

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@TalShafir1 TalShafir1 requested a review from a team as a code owner November 26, 2025 10:07
integration_version: 43.0
item_name: GitSync
item_type: Integration
publish_time: '2025-10-29'
Copy link
Member

Choose a reason for hiding this comment

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

Please update the publish time

@github-actions github-actions bot added the Stale label Dec 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Something isn't working Git Sync Stale

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants