cycode 3.8.8.dev1__py3-none-any.whl → 3.8.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
cycode/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = '3.8.8.dev1' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
1
+ __version__ = '3.8.9' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
@@ -8,6 +8,10 @@ from cycode.cli.exceptions.handle_report_sbom_errors import handle_report_except
8
8
  from cycode.cli.utils.get_api_client import get_report_cycode_client
9
9
  from cycode.cli.utils.progress_bar import SbomReportProgressBarSection
10
10
  from cycode.cli.utils.sentry import add_breadcrumb
11
+ from cycode.cli.utils.url_utils import sanitize_repository_url
12
+ from cycode.logger import get_logger
13
+
14
+ logger = get_logger('Repository URL Command')
11
15
 
12
16
 
13
17
  def repository_url_command(
@@ -28,8 +32,13 @@ def repository_url_command(
28
32
  start_scan_time = time.time()
29
33
  report_execution_id = -1
30
34
 
35
+ # Sanitize repository URL to remove any embedded credentials/tokens before sending to API
36
+ sanitized_uri = sanitize_repository_url(uri)
37
+ if sanitized_uri != uri:
38
+ logger.debug('Sanitized repository URL to remove credentials')
39
+
31
40
  try:
32
- report_execution = client.request_sbom_report_execution(report_parameters, repository_url=uri)
41
+ report_execution = client.request_sbom_report_execution(report_parameters, repository_url=sanitized_uri)
33
42
  report_execution_id = report_execution.id
34
43
 
35
44
  create_sbom_report(progress_bar, client, report_execution_id, output_file, output_format)
@@ -3,6 +3,7 @@ from typing import Optional
3
3
  from cycode.cli import consts
4
4
  from cycode.cli.utils.git_proxy import git_proxy
5
5
  from cycode.cli.utils.shell_executor import shell
6
+ from cycode.cli.utils.url_utils import sanitize_repository_url
6
7
  from cycode.logger import get_logger
7
8
 
8
9
  logger = get_logger('Remote URL Resolver')
@@ -102,7 +103,11 @@ def _try_get_git_remote_url(path: str) -> Optional[str]:
102
103
  repo = git_proxy.get_repo(path, search_parent_directories=True)
103
104
  remote_url = repo.remotes[0].config_reader.get('url')
104
105
  logger.debug('Found Git remote URL, %s', {'remote_url': remote_url, 'repo_path': repo.working_dir})
105
- return remote_url
106
+ # Sanitize URL to remove any embedded credentials/tokens before returning
107
+ sanitized_url = sanitize_repository_url(remote_url)
108
+ if sanitized_url != remote_url:
109
+ logger.debug('Sanitized repository URL to remove credentials')
110
+ return sanitized_url
106
111
  except Exception as e:
107
112
  logger.debug('Failed to get Git remote URL. Probably not a Git repository', exc_info=e)
108
113
  return None
@@ -124,7 +129,9 @@ def get_remote_url_scan_parameter(paths: tuple[str, ...]) -> Optional[str]:
124
129
  # - len(paths)*2 Plastic SCM subprocess calls
125
130
  remote_url = _try_get_any_remote_url(path)
126
131
  if remote_url:
127
- remote_urls.add(remote_url)
132
+ # URLs are already sanitized in _try_get_git_remote_url, but sanitize again as safety measure
133
+ sanitized_url = sanitize_repository_url(remote_url)
134
+ remote_urls.add(sanitized_url)
128
135
 
129
136
  if len(remote_urls) == 1:
130
137
  # we are resolving remote_url only if all paths belong to the same repo (identical remote URLs),
@@ -0,0 +1,64 @@
1
+ from typing import Optional
2
+ from urllib.parse import urlparse, urlunparse
3
+
4
+ from cycode.logger import get_logger
5
+
6
+ logger = get_logger('URL Utils')
7
+
8
+
9
+ def sanitize_repository_url(url: Optional[str]) -> Optional[str]:
10
+ """Remove credentials (username, password, tokens) from repository URL.
11
+
12
+ This function sanitizes repository URLs to prevent sending PAT tokens or other
13
+ credentials to the API. It handles both HTTP/HTTPS URLs with embedded credentials
14
+ and SSH URLs (which are returned as-is since they don't contain credentials in the URL).
15
+
16
+ Args:
17
+ url: Repository URL that may contain credentials (e.g., https://token@github.com/user/repo.git)
18
+
19
+ Returns:
20
+ Sanitized URL without credentials (e.g., https://github.com/user/repo.git), or None if input is None
21
+
22
+ Examples:
23
+ >>> sanitize_repository_url('https://token@github.com/user/repo.git')
24
+ 'https://github.com/user/repo.git'
25
+ >>> sanitize_repository_url('https://user:token@github.com/user/repo.git')
26
+ 'https://github.com/user/repo.git'
27
+ >>> sanitize_repository_url('git@github.com:user/repo.git')
28
+ 'git@github.com:user/repo.git'
29
+ >>> sanitize_repository_url(None)
30
+ None
31
+ """
32
+ if not url:
33
+ return url
34
+
35
+ # Handle SSH URLs - no credentials to remove
36
+ # ssh:// URLs have the format ssh://git@host/path
37
+ if url.startswith('ssh://'):
38
+ return url
39
+ # git@host:path format (scp-style)
40
+ if '@' in url and '://' not in url and url.startswith('git@'):
41
+ return url
42
+
43
+ try:
44
+ parsed = urlparse(url)
45
+ # Remove username and password from netloc
46
+ # Reconstruct URL without credentials
47
+ sanitized_netloc = parsed.hostname
48
+ if parsed.port:
49
+ sanitized_netloc = f'{sanitized_netloc}:{parsed.port}'
50
+
51
+ return urlunparse(
52
+ (
53
+ parsed.scheme,
54
+ sanitized_netloc,
55
+ parsed.path,
56
+ parsed.params,
57
+ parsed.query,
58
+ parsed.fragment,
59
+ )
60
+ )
61
+ except Exception as e:
62
+ logger.debug('Failed to sanitize repository URL, returning original, %s', {'url': url, 'error': str(e)})
63
+ # If parsing fails, return original URL to avoid breaking functionality
64
+ return url
@@ -6,8 +6,12 @@ from requests import Response
6
6
 
7
7
  from cycode.cli.exceptions.custom_exceptions import CycodeError
8
8
  from cycode.cli.files_collector.models.in_memory_zip import InMemoryZip
9
+ from cycode.cli.utils.url_utils import sanitize_repository_url
9
10
  from cycode.cyclient import models
10
11
  from cycode.cyclient.cycode_client_base import CycodeClientBase
12
+ from cycode.logger import get_logger
13
+
14
+ logger = get_logger('Report Client')
11
15
 
12
16
 
13
17
  @dataclasses.dataclass
@@ -49,7 +53,11 @@ class ReportClient:
49
53
  # entity type required only for zipped-file
50
54
  request_data = {'report_parameters': params.to_json(without_entity_type=zip_file is None)}
51
55
  if repository_url:
52
- request_data['repository_url'] = repository_url
56
+ # Sanitize repository URL to remove any embedded credentials/tokens before sending to API
57
+ sanitized_url = sanitize_repository_url(repository_url)
58
+ if sanitized_url != repository_url:
59
+ logger.debug('Sanitized repository URL to remove credentials')
60
+ request_data['repository_url'] = sanitized_url
53
61
 
54
62
  request_args = {
55
63
  'url_path': url_path,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cycode
3
- Version: 3.8.8.dev1
3
+ Version: 3.8.9
4
4
  Summary: Boost security in your dev lifecycle via SAST, SCA, Secrets & IaC scanning.
5
5
  License-Expression: MIT
6
6
  License-File: LICENCE
@@ -1,4 +1,4 @@
1
- cycode/__init__.py,sha256=IbeAIXQ8zYtLhBZo-147Djq0Q27imvmk_BEILmTVxWY,114
1
+ cycode/__init__.py,sha256=F3i3LbZj9g_0kdJeoKIrqojUc7ewqAylI2F_iZTTGEE,109
2
2
  cycode/__main__.py,sha256=Z3bD5yrA7yPvAChcADQrqCaZd0ChGI1gdiwALwbWJ6U,104
3
3
  cycode/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  cycode/cli/app.py,sha256=Th7skHthoJN1EuDtgjl4flflFqejfxaTORKmMKSXE00,6412
@@ -28,7 +28,7 @@ cycode/cli/apps/report/sbom/common.py,sha256=TefLoLxbxi4yDq6b-639udlGqfgLDznGGRw
28
28
  cycode/cli/apps/report/sbom/path/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
29
  cycode/cli/apps/report/sbom/path/path_command.py,sha256=We_0ykbXILN_JreKH5ySK2SVfgh1hnpPeWB6jkDawpQ,3110
30
30
  cycode/cli/apps/report/sbom/repository_url/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
- cycode/cli/apps/report/sbom/repository_url/repository_url_command.py,sha256=VO4jSR748BEpCuOrAvOK4_rNLw63lO4iHCTfWkWdfMQ,2179
31
+ cycode/cli/apps/report/sbom/repository_url/repository_url_command.py,sha256=euNULmXK1oVLLNZ_R2GUN2ESDsYswrpEph-bjnHxock,2580
32
32
  cycode/cli/apps/report/sbom/sbom_command.py,sha256=bykQnmO0CCNInkih6bGmCcq5HFH-ItkFHPoxz683HCc,2229
33
33
  cycode/cli/apps/report/sbom/sbom_report_file.py,sha256=uyaJRvmg1K4DvJaMppbCf6yCj6UU-NdvNg-ZVZk0jx4,1576
34
34
  cycode/cli/apps/report_import/__init__.py,sha256=T9KSL2TwQKQTNbck7JBlQAf7w8W3Q3VQLn_BCzVLWrA,424
@@ -50,7 +50,7 @@ cycode/cli/apps/scan/pre_push/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5N
50
50
  cycode/cli/apps/scan/pre_push/pre_push_command.py,sha256=Z0OJc3JDuI-pE1yLYYjuQh-kZhdZIExUPfaub73TZZE,2505
51
51
  cycode/cli/apps/scan/pre_receive/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
52
  cycode/cli/apps/scan/pre_receive/pre_receive_command.py,sha256=PanKeThapAmxapjvZwGMgux6G4RzjUUPcxebb-qFRMM,2612
53
- cycode/cli/apps/scan/remote_url_resolver.py,sha256=EzHgV7XaJ3TedY35vDrFVGN7qjpaNl8lnYRNSRs3fvQ,5155
53
+ cycode/cli/apps/scan/remote_url_resolver.py,sha256=JCjaAzDMxGFDT7twBpZzjgEHGwlaGIxWG_Y7DSehsb0,5651
54
54
  cycode/cli/apps/scan/repository/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
55
  cycode/cli/apps/scan/repository/repository_command.py,sha256=R1pNaxwuFI3Y7sisBp6PwCa-aCvCmPZoAKg5F1iwyCA,3432
56
56
  cycode/cli/apps/scan/scan_ci/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -145,6 +145,7 @@ cycode/cli/utils/sentry.py,sha256=hHWYtiGKD6vRi8S6Jx9hycs5JpJvGlkBImXZfWfWB1o,36
145
145
  cycode/cli/utils/shell_executor.py,sha256=CuHeXoYM6VaYtDernWtf49_s1EfuU8nWxj4MPIAciww,1290
146
146
  cycode/cli/utils/string_utils.py,sha256=jrZ5B7351hVEibHQzyrAqJJoP3R3jgpONNEw3wMAUVA,2032
147
147
  cycode/cli/utils/task_timer.py,sha256=wxfM2TtJGjc1F17CIja_Qmt6zd4a1qdMwuz0ltgTDAg,2722
148
+ cycode/cli/utils/url_utils.py,sha256=2ZhRCbQsKnvAl5MBugQ5CrwuALP8uivsCI6chlqxahM,2304
148
149
  cycode/cli/utils/version_checker.py,sha256=0f5PaTk02ZkDxzBqZOeMV9mU_CWcx6HKW80jUKFOOZs,8239
149
150
  cycode/cli/utils/yaml_utils.py,sha256=R-tqzl0C-zoa42rS7nfWeHu3GJ0jpbQUyyqYYU2hleM,1818
150
151
  cycode/config.py,sha256=jHORGZQcAXkAGSf2XreC-RQoc8sdNWja69QKtPWTbWo,1044
@@ -163,12 +164,12 @@ cycode/cyclient/headers.py,sha256=5aLezpRDBzueH9T1hB_6VyUydRpTs3rN17CDDPn1BxI,14
163
164
  cycode/cyclient/import_sbom_client.py,sha256=M0RAn2dDh9woI3SUkgSHCQxhbARoLpyAM3amOausz8E,2749
164
165
  cycode/cyclient/logger.py,sha256=oTkay7QzoOIVQ71cGOy4ukkijYGA3IKJlHkL24Px5ds,70
165
166
  cycode/cyclient/models.py,sha256=U_37PROmaat5ehliH1YZ71iVecF7dPvXPTNOoj67Thg,15017
166
- cycode/cyclient/report_client.py,sha256=h12pz3vWCwDF73BhqFX7iDSxBgQDFwkiGh3hmul2nsM,3965
167
+ cycode/cyclient/report_client.py,sha256=Scq30NeJPzgXv0hPLO1U05AdE9i_2iu6cIrSKpEJ-cM,4399
167
168
  cycode/cyclient/scan_client.py,sha256=uTBEjgfaCVuJREo73p_zkIVA23NQfdJ1d1-bzc7nSKk,12682
168
169
  cycode/cyclient/scan_config_base.py,sha256=mXsPZGYCtp85rv5GIige40yQZXuRcEKUW-VQJ0vgFzk,1201
169
170
  cycode/logger.py,sha256=xAzpkWLZhixO4egRcYn4HXM9lIfx5wHdpkHxNc5jrX8,2225
170
- cycode-3.8.8.dev1.dist-info/METADATA,sha256=40JQ3R0S6BNnD1bwd1xvnE1RHgDTCDQTOOaTlW9eGw8,79037
171
- cycode-3.8.8.dev1.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
172
- cycode-3.8.8.dev1.dist-info/entry_points.txt,sha256=iDcVJM8ByLElVgvBgtYxDjw1kT7O8Mo0LcWZIT5L3Ig,45
173
- cycode-3.8.8.dev1.dist-info/licenses/LICENCE,sha256=2Wx4N6mD_4xB7-E3hPkZ3MPhpJy__k_I8MaCSO-PDRo,1068
174
- cycode-3.8.8.dev1.dist-info/RECORD,,
171
+ cycode-3.8.9.dist-info/METADATA,sha256=s5uUTInVCjsaQLRho10cZNs0q479yaVY731EHgm3Rl4,79032
172
+ cycode-3.8.9.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
173
+ cycode-3.8.9.dist-info/entry_points.txt,sha256=iDcVJM8ByLElVgvBgtYxDjw1kT7O8Mo0LcWZIT5L3Ig,45
174
+ cycode-3.8.9.dist-info/licenses/LICENCE,sha256=2Wx4N6mD_4xB7-E3hPkZ3MPhpJy__k_I8MaCSO-PDRo,1068
175
+ cycode-3.8.9.dist-info/RECORD,,