cycode 3.25.1.dev6__py3-none-any.whl → 3.25.2.dev2__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 +1 -1
- cycode/cli/app.py +9 -10
- cycode/cli/apps/activation_manager.py +6 -6
- cycode/cli/apps/ai_guardrails/command_utils.py +1 -2
- cycode/cli/apps/ai_guardrails/hooks_manager.py +6 -7
- cycode/cli/apps/ai_guardrails/ides/__init__.py +8 -9
- cycode/cli/apps/ai_guardrails/ides/_plugin_utils.py +11 -10
- cycode/cli/apps/ai_guardrails/ides/_skill_utils.py +1 -2
- cycode/cli/apps/ai_guardrails/ides/base.py +19 -21
- cycode/cli/apps/ai_guardrails/ides/claude_code.py +54 -16
- cycode/cli/apps/ai_guardrails/ides/codex.py +54 -20
- cycode/cli/apps/ai_guardrails/ides/copilot.py +23 -25
- cycode/cli/apps/ai_guardrails/ides/cursor.py +48 -10
- cycode/cli/apps/ai_guardrails/install_command.py +3 -3
- cycode/cli/apps/ai_guardrails/scan/guardrail_config.py +44 -22
- cycode/cli/apps/ai_guardrails/scan/handlers.py +79 -14
- cycode/cli/apps/ai_guardrails/scan/mcp_server_status.py +103 -0
- cycode/cli/apps/ai_guardrails/scan/payload.py +13 -14
- cycode/cli/apps/ai_guardrails/scan/policy.py +3 -3
- cycode/cli/apps/ai_guardrails/scan/scan_command.py +4 -4
- cycode/cli/apps/ai_guardrails/scan/types.py +1 -0
- cycode/cli/apps/ai_guardrails/session_start_command.py +46 -21
- cycode/cli/apps/ai_guardrails/status_command.py +2 -2
- cycode/cli/apps/ai_guardrails/uninstall_command.py +2 -2
- cycode/cli/apps/api/__init__.py +3 -3
- cycode/cli/apps/api/api_command.py +6 -6
- cycode/cli/apps/api/openapi_spec.py +4 -5
- cycode/cli/apps/auth/auth_common.py +4 -4
- cycode/cli/apps/configure/configure_command.py +2 -4
- cycode/cli/apps/configure/messages.py +2 -4
- cycode/cli/apps/configure/prompts.py +5 -7
- cycode/cli/apps/ignore/ignore_command.py +7 -7
- cycode/cli/apps/mcp/mcp_command.py +11 -11
- cycode/cli/apps/report/sbom/common.py +5 -5
- cycode/cli/apps/report/sbom/sbom_command.py +2 -2
- cycode/cli/apps/report/sbom/sbom_report_file.py +1 -2
- cycode/cli/apps/report_import/sbom/sbom_command.py +3 -3
- cycode/cli/apps/sca_options.py +3 -3
- cycode/cli/apps/scan/aggregation_report.py +4 -4
- cycode/cli/apps/scan/code_scanner.py +8 -7
- cycode/cli/apps/scan/commit_range_scanner.py +10 -10
- cycode/cli/apps/scan/detection_excluder.py +2 -4
- cycode/cli/apps/scan/pre_commit/pre_commit_command.py +3 -3
- cycode/cli/apps/scan/pre_push/pre_push_command.py +3 -3
- cycode/cli/apps/scan/pre_receive/pre_receive_command.py +2 -2
- cycode/cli/apps/scan/remote_url_resolver.py +6 -8
- cycode/cli/apps/scan/repository/repository_command.py +2 -2
- cycode/cli/apps/scan/scan_command.py +2 -2
- cycode/cli/apps/scan/scan_parameters.py +1 -3
- cycode/cli/apps/scan/scan_result.py +5 -5
- cycode/cli/console.py +2 -2
- cycode/cli/exceptions/custom_exceptions.py +1 -1
- cycode/cli/exceptions/handle_errors.py +1 -3
- cycode/cli/exceptions/handle_scan_errors.py +1 -2
- cycode/cli/files_collector/commit_range_documents.py +14 -14
- cycode/cli/files_collector/models/in_memory_zip.py +3 -3
- cycode/cli/files_collector/repository_documents.py +3 -3
- cycode/cli/files_collector/sca/base_restore_dependencies.py +7 -8
- cycode/cli/files_collector/sca/go/restore_go_dependencies.py +1 -2
- cycode/cli/files_collector/sca/maven/restore_gradle_dependencies.py +2 -3
- cycode/cli/files_collector/sca/maven/restore_maven_dependencies.py +3 -4
- cycode/cli/files_collector/sca/npm/restore_bun_dependencies.py +3 -4
- cycode/cli/files_collector/sca/npm/restore_deno_dependencies.py +1 -2
- cycode/cli/files_collector/sca/npm/restore_pnpm_dependencies.py +2 -3
- cycode/cli/files_collector/sca/npm/restore_yarn_dependencies.py +2 -3
- cycode/cli/files_collector/sca/npm/workspace/coverage.py +5 -5
- cycode/cli/files_collector/sca/npm/workspace/files.py +2 -3
- cycode/cli/files_collector/sca/npm/workspace/globs.py +1 -2
- cycode/cli/files_collector/sca/npm/workspace/resolvers.py +14 -16
- cycode/cli/files_collector/sca/php/restore_composer_dependencies.py +1 -2
- cycode/cli/files_collector/sca/python/restore_pip_dependencies.py +2 -3
- cycode/cli/files_collector/sca/python/restore_pipenv_dependencies.py +1 -2
- cycode/cli/files_collector/sca/python/restore_poetry_dependencies.py +2 -3
- cycode/cli/files_collector/sca/python/restore_uv_dependencies.py +2 -3
- cycode/cli/files_collector/sca/sca_file_collector.py +5 -5
- cycode/cli/files_collector/zip_documents.py +1 -2
- cycode/cli/models.py +8 -8
- cycode/cli/printers/console_printer.py +9 -9
- cycode/cli/printers/json_printer.py +2 -2
- cycode/cli/printers/printer_base.py +3 -3
- cycode/cli/printers/rich_printer.py +2 -2
- cycode/cli/printers/tables/table.py +4 -4
- cycode/cli/printers/tables/table_models.py +2 -2
- cycode/cli/printers/tables/table_printer_base.py +2 -2
- cycode/cli/printers/text_printer.py +4 -4
- cycode/cli/printers/utils/code_snippet_syntax.py +1 -1
- cycode/cli/printers/utils/detection_data.py +3 -3
- cycode/cli/printers/utils/sca_ossf.py +4 -4
- cycode/cli/printers/utils/sca_policy_details.py +2 -1
- cycode/cli/user_settings/config_file_manager.py +10 -10
- cycode/cli/user_settings/configuration_manager.py +6 -6
- cycode/cli/user_settings/credentials_manager.py +5 -6
- cycode/cli/utils/get_api_client.py +5 -5
- cycode/cli/utils/git_proxy.py +8 -8
- cycode/cli/utils/host_info.py +21 -38
- cycode/cli/utils/ignore_utils.py +13 -15
- cycode/cli/utils/jwt_utils.py +2 -4
- cycode/cli/utils/path_utils.py +6 -6
- cycode/cli/utils/progress_bar.py +4 -4
- cycode/cli/utils/scan_batch.py +2 -1
- cycode/cli/utils/scan_utils.py +2 -2
- cycode/cli/utils/shell_executor.py +3 -4
- cycode/cli/utils/task_timer.py +4 -4
- cycode/cli/utils/trust_store.py +0 -17
- cycode/cli/utils/url_utils.py +1 -2
- cycode/cli/utils/version_checker.py +4 -5
- cycode/cli/utils/yaml_utils.py +1 -1
- cycode/config.py +1 -2
- cycode/cyclient/ai_security_manager_client.py +27 -21
- cycode/cyclient/auth_client.py +2 -4
- cycode/cyclient/base_token_auth_client.py +2 -2
- cycode/cyclient/client_creator.py +4 -6
- cycode/cyclient/cycode_client_base.py +10 -9
- cycode/cyclient/cycode_dev_based_client.py +1 -3
- cycode/cyclient/headers.py +1 -2
- cycode/cyclient/import_sbom_client.py +3 -4
- cycode/cyclient/models.py +88 -30
- cycode/cyclient/report_client.py +1 -2
- cycode/cyclient/scan_client.py +8 -7
- cycode/logger.py +4 -4
- {cycode-3.25.1.dev6.dist-info → cycode-3.25.2.dev2.dist-info}/METADATA +12 -19
- {cycode-3.25.1.dev6.dist-info → cycode-3.25.2.dev2.dist-info}/RECORD +125 -124
- {cycode-3.25.1.dev6.dist-info → cycode-3.25.2.dev2.dist-info}/WHEEL +1 -1
- {cycode-3.25.1.dev6.dist-info → cycode-3.25.2.dev2.dist-info}/entry_points.txt +0 -0
- {cycode-3.25.1.dev6.dist-info → cycode-3.25.2.dev2.dist-info}/licenses/LICENCE +0 -0
|
@@ -4,7 +4,6 @@ import json
|
|
|
4
4
|
import os
|
|
5
5
|
import time
|
|
6
6
|
from pathlib import Path
|
|
7
|
-
from typing import Optional
|
|
8
7
|
|
|
9
8
|
from cycode.cli.consts import CYCODE_CONFIGURATION_DIRECTORY
|
|
10
9
|
from cycode.cli.user_settings.credentials_manager import CredentialsManager
|
|
@@ -20,7 +19,7 @@ _CACHE_TTL_SECONDS = int(os.getenv('CYCODE_SPEC_CACHE_TTL', str(24 * 60 * 60)))
|
|
|
20
19
|
_OPENAPI_SPEC_PATH = '/v4/api-docs/cycode-api-swagger.json'
|
|
21
20
|
|
|
22
21
|
|
|
23
|
-
def get_openapi_spec(client_id:
|
|
22
|
+
def get_openapi_spec(client_id: str | None = None, client_secret: str | None = None) -> dict:
|
|
24
23
|
"""Get the OpenAPI spec, using cache if fresh, otherwise fetching from API.
|
|
25
24
|
|
|
26
25
|
The spec is only fetched when the user actually invokes `cycode platform ...`.
|
|
@@ -45,7 +44,7 @@ def get_openapi_spec(client_id: Optional[str] = None, client_secret: Optional[st
|
|
|
45
44
|
return _fetch_and_cache_spec(client_id, client_secret)
|
|
46
45
|
|
|
47
46
|
|
|
48
|
-
def _load_cached_spec() ->
|
|
47
|
+
def _load_cached_spec() -> dict | None:
|
|
49
48
|
"""Load spec from local cache if it exists and is fresh."""
|
|
50
49
|
if not _CACHE_FILE.exists():
|
|
51
50
|
return None
|
|
@@ -64,7 +63,7 @@ def _load_cached_spec() -> Optional[dict]:
|
|
|
64
63
|
return None
|
|
65
64
|
|
|
66
65
|
|
|
67
|
-
def resolve_credentials(client_id:
|
|
66
|
+
def resolve_credentials(client_id: str | None = None, client_secret: str | None = None) -> tuple[str, str]:
|
|
68
67
|
"""Resolve credentials from args or the CLI's standard credential chain."""
|
|
69
68
|
if not client_id or not client_secret:
|
|
70
69
|
credentials_manager = CredentialsManager()
|
|
@@ -81,7 +80,7 @@ def resolve_credentials(client_id: Optional[str] = None, client_secret: Optional
|
|
|
81
80
|
return client_id, client_secret
|
|
82
81
|
|
|
83
82
|
|
|
84
|
-
def _fetch_and_cache_spec(client_id:
|
|
83
|
+
def _fetch_and_cache_spec(client_id: str | None = None, client_secret: str | None = None) -> dict:
|
|
85
84
|
"""Fetch OpenAPI spec from API and cache to disk.
|
|
86
85
|
|
|
87
86
|
Uses CycodeTokenBasedClient for auth and retries. The spec is served from the app URL,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import TYPE_CHECKING
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
2
2
|
|
|
3
3
|
from cycode.cli.apps.auth.models import AuthInfo
|
|
4
4
|
from cycode.cli.exceptions.custom_exceptions import HttpUnauthorizedError, RequestHttpError
|
|
@@ -11,7 +11,7 @@ if TYPE_CHECKING:
|
|
|
11
11
|
from typer import Context
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
def get_authorization_info(ctx: 'Context') ->
|
|
14
|
+
def get_authorization_info(ctx: 'Context') -> AuthInfo | None:
|
|
15
15
|
printer = ctx.obj.get('console_printer')
|
|
16
16
|
|
|
17
17
|
client_id = ctx.obj.get('client_id')
|
|
@@ -50,8 +50,8 @@ def get_authorization_info(ctx: 'Context') -> Optional[AuthInfo]:
|
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
def _try_oidc_authorization(
|
|
53
|
-
ctx: 'Context', printer: any, client_id:
|
|
54
|
-
) ->
|
|
53
|
+
ctx: 'Context', printer: any, client_id: str | None, id_token: str | None
|
|
54
|
+
) -> AuthInfo | None:
|
|
55
55
|
if not client_id or not id_token:
|
|
56
56
|
return None
|
|
57
57
|
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from typing import Optional
|
|
2
|
-
|
|
3
1
|
from cycode.cli.apps.configure.consts import CONFIGURATION_MANAGER, CREDENTIALS_MANAGER
|
|
4
2
|
from cycode.cli.apps.configure.messages import (
|
|
5
3
|
get_credentials_environment_variables_override_warning,
|
|
@@ -18,8 +16,8 @@ from cycode.cli.console import console
|
|
|
18
16
|
|
|
19
17
|
|
|
20
18
|
def _should_update_value(
|
|
21
|
-
old_value:
|
|
22
|
-
new_value:
|
|
19
|
+
old_value: str | None,
|
|
20
|
+
new_value: str | None,
|
|
23
21
|
) -> bool:
|
|
24
22
|
if not new_value:
|
|
25
23
|
return False
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from typing import Optional
|
|
2
|
-
|
|
3
1
|
from cycode.cli.apps.configure.consts import (
|
|
4
2
|
CONFIGURATION_MANAGER,
|
|
5
3
|
CREDENTIALS_ARE_SET_IN_ENVIRONMENT_VARIABLES_MESSAGE,
|
|
@@ -19,7 +17,7 @@ def get_credentials_update_result_message() -> str:
|
|
|
19
17
|
return CREDENTIALS_UPDATED_SUCCESSFULLY_MESSAGE.format(filename=CREDENTIALS_MANAGER.get_filename())
|
|
20
18
|
|
|
21
19
|
|
|
22
|
-
def get_credentials_environment_variables_override_warning() ->
|
|
20
|
+
def get_credentials_environment_variables_override_warning() -> str | None:
|
|
23
21
|
if _are_credentials_exist_in_environment_variables():
|
|
24
22
|
return CREDENTIALS_ARE_SET_IN_ENVIRONMENT_VARIABLES_MESSAGE
|
|
25
23
|
|
|
@@ -38,7 +36,7 @@ def get_urls_update_result_message() -> str:
|
|
|
38
36
|
)
|
|
39
37
|
|
|
40
38
|
|
|
41
|
-
def get_urls_environment_variables_override_warning() ->
|
|
39
|
+
def get_urls_environment_variables_override_warning() -> str | None:
|
|
42
40
|
if _are_urls_exist_in_environment_variables():
|
|
43
41
|
return URLS_ARE_SET_IN_ENVIRONMENT_VARIABLES_MESSAGE
|
|
44
42
|
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
from typing import Optional
|
|
2
|
-
|
|
3
1
|
import typer
|
|
4
2
|
|
|
5
3
|
from cycode.cli import consts
|
|
6
4
|
from cycode.cli.utils.string_utils import obfuscate_text
|
|
7
5
|
|
|
8
6
|
|
|
9
|
-
def get_client_id_input(current_client_id:
|
|
7
|
+
def get_client_id_input(current_client_id: str | None) -> str | None:
|
|
10
8
|
prompt_text = 'Cycode Client ID'
|
|
11
9
|
|
|
12
10
|
prompt_suffix = ' []: '
|
|
@@ -17,7 +15,7 @@ def get_client_id_input(current_client_id: Optional[str]) -> Optional[str]:
|
|
|
17
15
|
return new_client_id or current_client_id
|
|
18
16
|
|
|
19
17
|
|
|
20
|
-
def get_client_secret_input(current_client_secret:
|
|
18
|
+
def get_client_secret_input(current_client_secret: str | None) -> str | None:
|
|
21
19
|
prompt_text = 'Cycode Client Secret'
|
|
22
20
|
|
|
23
21
|
prompt_suffix = ' []: '
|
|
@@ -28,7 +26,7 @@ def get_client_secret_input(current_client_secret: Optional[str]) -> Optional[st
|
|
|
28
26
|
return new_client_secret or current_client_secret
|
|
29
27
|
|
|
30
28
|
|
|
31
|
-
def get_app_url_input(current_app_url:
|
|
29
|
+
def get_app_url_input(current_app_url: str | None) -> str:
|
|
32
30
|
prompt_text = 'Cycode APP URL'
|
|
33
31
|
|
|
34
32
|
default = consts.DEFAULT_CYCODE_APP_URL
|
|
@@ -38,7 +36,7 @@ def get_app_url_input(current_app_url: Optional[str]) -> str:
|
|
|
38
36
|
return typer.prompt(text=prompt_text, default=default, type=str)
|
|
39
37
|
|
|
40
38
|
|
|
41
|
-
def get_api_url_input(current_api_url:
|
|
39
|
+
def get_api_url_input(current_api_url: str | None) -> str:
|
|
42
40
|
prompt_text = 'Cycode API URL'
|
|
43
41
|
|
|
44
42
|
default = consts.DEFAULT_CYCODE_API_URL
|
|
@@ -48,7 +46,7 @@ def get_api_url_input(current_api_url: Optional[str]) -> str:
|
|
|
48
46
|
return typer.prompt(text=prompt_text, default=default, type=str)
|
|
49
47
|
|
|
50
48
|
|
|
51
|
-
def get_id_token_input(current_id_token:
|
|
49
|
+
def get_id_token_input(current_id_token: str | None) -> str | None:
|
|
52
50
|
prompt_text = 'Cycode ID Token'
|
|
53
51
|
|
|
54
52
|
prompt_suffix = ' []: '
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import re
|
|
2
|
-
from typing import Annotated
|
|
2
|
+
from typing import Annotated
|
|
3
3
|
|
|
4
4
|
import click
|
|
5
5
|
import typer
|
|
@@ -22,7 +22,7 @@ def _is_package_pattern_valid(package: str) -> bool:
|
|
|
22
22
|
|
|
23
23
|
def ignore_command( # noqa: C901
|
|
24
24
|
by_path: Annotated[
|
|
25
|
-
|
|
25
|
+
str | None,
|
|
26
26
|
typer.Option(
|
|
27
27
|
help='Ignore a specific file or directory while scanning.',
|
|
28
28
|
show_default=False,
|
|
@@ -30,7 +30,7 @@ def ignore_command( # noqa: C901
|
|
|
30
30
|
),
|
|
31
31
|
] = None,
|
|
32
32
|
by_rule: Annotated[
|
|
33
|
-
|
|
33
|
+
str | None,
|
|
34
34
|
typer.Option(
|
|
35
35
|
help='Ignore scanning a specific Secrets rule ID or IaC rule ID.',
|
|
36
36
|
show_default=False,
|
|
@@ -38,7 +38,7 @@ def ignore_command( # noqa: C901
|
|
|
38
38
|
),
|
|
39
39
|
] = None,
|
|
40
40
|
by_value: Annotated[
|
|
41
|
-
|
|
41
|
+
str | None,
|
|
42
42
|
typer.Option(
|
|
43
43
|
help='Ignore a specific value.',
|
|
44
44
|
show_default=False,
|
|
@@ -46,7 +46,7 @@ def ignore_command( # noqa: C901
|
|
|
46
46
|
),
|
|
47
47
|
] = None,
|
|
48
48
|
by_sha: Annotated[
|
|
49
|
-
|
|
49
|
+
str | None,
|
|
50
50
|
typer.Option(
|
|
51
51
|
help='Ignore a specific SHA512 representation of a string.',
|
|
52
52
|
show_default=False,
|
|
@@ -54,7 +54,7 @@ def ignore_command( # noqa: C901
|
|
|
54
54
|
),
|
|
55
55
|
] = None,
|
|
56
56
|
by_package: Annotated[
|
|
57
|
-
|
|
57
|
+
str | None,
|
|
58
58
|
typer.Option(
|
|
59
59
|
help='Ignore scanning a specific package version. Expected pattern: [cyan]name@version[/].',
|
|
60
60
|
show_default=False,
|
|
@@ -62,7 +62,7 @@ def ignore_command( # noqa: C901
|
|
|
62
62
|
),
|
|
63
63
|
] = None,
|
|
64
64
|
by_cve: Annotated[
|
|
65
|
-
|
|
65
|
+
str | None,
|
|
66
66
|
typer.Option(
|
|
67
67
|
help='Ignore scanning a specific CVE. Expected pattern: [cyan]CVE-YYYY-NNN[/].',
|
|
68
68
|
show_default=False,
|
|
@@ -6,7 +6,7 @@ import shutil
|
|
|
6
6
|
import sys
|
|
7
7
|
import tempfile
|
|
8
8
|
import uuid
|
|
9
|
-
from typing import Annotated, Any
|
|
9
|
+
from typing import Annotated, Any
|
|
10
10
|
|
|
11
11
|
import anyio
|
|
12
12
|
import typer
|
|
@@ -229,8 +229,8 @@ def _build_scan_summary(result: dict[str, Any]) -> str:
|
|
|
229
229
|
|
|
230
230
|
async def _cycode_scan_tool(
|
|
231
231
|
scan_type: ScanTypeOption,
|
|
232
|
-
files:
|
|
233
|
-
paths:
|
|
232
|
+
files: dict[str, str] | None = None,
|
|
233
|
+
paths: list[str] | None = None,
|
|
234
234
|
) -> str:
|
|
235
235
|
_tool_call_id = _gen_random_id()
|
|
236
236
|
_logger.info('Scan tool called, %s', {'scan_type': scan_type, 'call_id': _tool_call_id})
|
|
@@ -288,8 +288,8 @@ async def _cycode_scan_tool(
|
|
|
288
288
|
|
|
289
289
|
|
|
290
290
|
async def cycode_secret_scan(
|
|
291
|
-
paths:
|
|
292
|
-
files:
|
|
291
|
+
paths: list[str] | None = _PATHS_TOOL_FIELD,
|
|
292
|
+
files: dict[str, str] | None = _FILES_TOOL_FIELD,
|
|
293
293
|
) -> str:
|
|
294
294
|
"""Scan for hardcoded secrets.
|
|
295
295
|
|
|
@@ -309,8 +309,8 @@ async def cycode_secret_scan(
|
|
|
309
309
|
|
|
310
310
|
|
|
311
311
|
async def cycode_sca_scan(
|
|
312
|
-
paths:
|
|
313
|
-
files:
|
|
312
|
+
paths: list[str] | None = _PATHS_TOOL_FIELD,
|
|
313
|
+
files: dict[str, str] | None = _FILES_TOOL_FIELD,
|
|
314
314
|
) -> str:
|
|
315
315
|
"""Scan for Software Composition Analysis (SCA) - vulnerabilities and license issues.
|
|
316
316
|
|
|
@@ -337,8 +337,8 @@ async def cycode_sca_scan(
|
|
|
337
337
|
|
|
338
338
|
|
|
339
339
|
async def cycode_iac_scan(
|
|
340
|
-
paths:
|
|
341
|
-
files:
|
|
340
|
+
paths: list[str] | None = _PATHS_TOOL_FIELD,
|
|
341
|
+
files: dict[str, str] | None = _FILES_TOOL_FIELD,
|
|
342
342
|
) -> str:
|
|
343
343
|
"""Scan for Infrastructure as Code (IaC) misconfigurations.
|
|
344
344
|
|
|
@@ -360,8 +360,8 @@ async def cycode_iac_scan(
|
|
|
360
360
|
|
|
361
361
|
|
|
362
362
|
async def cycode_sast_scan(
|
|
363
|
-
paths:
|
|
364
|
-
files:
|
|
363
|
+
paths: list[str] | None = _PATHS_TOOL_FIELD,
|
|
364
|
+
files: dict[str, str] | None = _FILES_TOOL_FIELD,
|
|
365
365
|
) -> str:
|
|
366
366
|
"""Scan for Static Application Security Testing (SAST) - code quality and security flaws.
|
|
367
367
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import pathlib
|
|
2
2
|
import time
|
|
3
3
|
from platform import platform
|
|
4
|
-
from typing import TYPE_CHECKING
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
5
|
|
|
6
6
|
from cycode.cli import consts
|
|
7
7
|
from cycode.cli.apps.report.sbom.sbom_report_file import SbomReportFile
|
|
@@ -20,7 +20,7 @@ def _poll_report_execution_until_completed(
|
|
|
20
20
|
progress_bar: 'BaseProgressBar',
|
|
21
21
|
client: 'ReportClient',
|
|
22
22
|
report_execution_id: int,
|
|
23
|
-
polling_timeout:
|
|
23
|
+
polling_timeout: int | None = None,
|
|
24
24
|
) -> ReportExecutionSchema:
|
|
25
25
|
if polling_timeout is None:
|
|
26
26
|
polling_timeout = configuration_manager.get_report_polling_timeout_in_seconds()
|
|
@@ -50,8 +50,8 @@ def send_report_feedback(
|
|
|
50
50
|
report_command_type: str,
|
|
51
51
|
request_report_parameters: dict,
|
|
52
52
|
report_execution_id: int,
|
|
53
|
-
error_message:
|
|
54
|
-
request_zip_file_size:
|
|
53
|
+
error_message: str | None = None,
|
|
54
|
+
request_zip_file_size: int | None = None,
|
|
55
55
|
**kwargs,
|
|
56
56
|
) -> None:
|
|
57
57
|
try:
|
|
@@ -77,7 +77,7 @@ def create_sbom_report(
|
|
|
77
77
|
progress_bar: 'BaseProgressBar',
|
|
78
78
|
client: 'ReportClient',
|
|
79
79
|
report_execution_id: int,
|
|
80
|
-
output_file:
|
|
80
|
+
output_file: pathlib.Path | None,
|
|
81
81
|
output_format: str,
|
|
82
82
|
) -> None:
|
|
83
83
|
report_execution = _poll_report_execution_until_completed(progress_bar, client, report_execution_id)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
-
from typing import Annotated
|
|
2
|
+
from typing import Annotated
|
|
3
3
|
|
|
4
4
|
import click
|
|
5
5
|
import typer
|
|
@@ -32,7 +32,7 @@ def sbom_command(
|
|
|
32
32
|
),
|
|
33
33
|
] = SbomOutputFormatOption.JSON,
|
|
34
34
|
output_file: Annotated[
|
|
35
|
-
|
|
35
|
+
Path | None,
|
|
36
36
|
typer.Option(
|
|
37
37
|
help='Output file.',
|
|
38
38
|
show_default='Autogenerated filename saved to the current directory',
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import pathlib
|
|
3
3
|
import re
|
|
4
|
-
from typing import Optional
|
|
5
4
|
|
|
6
5
|
import typer
|
|
7
6
|
|
|
@@ -9,7 +8,7 @@ from cycode.cli.console import console
|
|
|
9
8
|
|
|
10
9
|
|
|
11
10
|
class SbomReportFile:
|
|
12
|
-
def __init__(self, storage_path: str, output_format: str, output_file:
|
|
11
|
+
def __init__(self, storage_path: str, output_format: str, output_file: pathlib.Path | None) -> None:
|
|
13
12
|
if output_file is None:
|
|
14
13
|
output_file = pathlib.Path(storage_path)
|
|
15
14
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
-
from typing import Annotated
|
|
2
|
+
from typing import Annotated
|
|
3
3
|
|
|
4
4
|
import typer
|
|
5
5
|
|
|
@@ -24,13 +24,13 @@ def sbom_command(
|
|
|
24
24
|
str, typer.Option('--vendor', '-v', help='Vendor Name.', case_sensitive=False, show_default=False)
|
|
25
25
|
],
|
|
26
26
|
labels: Annotated[
|
|
27
|
-
|
|
27
|
+
list[str] | None,
|
|
28
28
|
typer.Option(
|
|
29
29
|
'--label', '-l', help='Label, can be specified multiple times.', case_sensitive=False, show_default=False
|
|
30
30
|
),
|
|
31
31
|
] = None,
|
|
32
32
|
owners: Annotated[
|
|
33
|
-
|
|
33
|
+
list[str] | None,
|
|
34
34
|
typer.Option(
|
|
35
35
|
'--owner',
|
|
36
36
|
'-o',
|
cycode/cli/apps/sca_options.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
-
from typing import Annotated
|
|
2
|
+
from typing import Annotated
|
|
3
3
|
|
|
4
4
|
import typer
|
|
5
5
|
|
|
@@ -25,7 +25,7 @@ GradleAllSubProjectsOption = Annotated[
|
|
|
25
25
|
]
|
|
26
26
|
|
|
27
27
|
MavenSettingsFileOption = Annotated[
|
|
28
|
-
|
|
28
|
+
Path | None,
|
|
29
29
|
typer.Option(
|
|
30
30
|
'--maven-settings-file',
|
|
31
31
|
show_default=False,
|
|
@@ -49,7 +49,7 @@ def apply_sca_restore_options_to_context(
|
|
|
49
49
|
ctx: typer.Context,
|
|
50
50
|
no_restore: bool,
|
|
51
51
|
gradle_all_sub_projects: bool,
|
|
52
|
-
maven_settings_file:
|
|
52
|
+
maven_settings_file: Path | None,
|
|
53
53
|
stop_on_error: bool = False,
|
|
54
54
|
) -> None:
|
|
55
55
|
ctx.obj['no_restore'] = no_restore
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import TYPE_CHECKING
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
2
2
|
|
|
3
3
|
import typer
|
|
4
4
|
|
|
@@ -10,13 +10,13 @@ if TYPE_CHECKING:
|
|
|
10
10
|
logger = get_logger('Aggregation Report URL')
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
def _set_aggregation_report_url(ctx: typer.Context, aggregation_report_url:
|
|
13
|
+
def _set_aggregation_report_url(ctx: typer.Context, aggregation_report_url: str | None = None) -> None:
|
|
14
14
|
ctx.obj['aggregation_report_url'] = aggregation_report_url
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
def try_get_aggregation_report_url_if_needed(
|
|
18
18
|
scan_parameters: dict, cycode_client: 'ScanClient', scan_type: str
|
|
19
|
-
) ->
|
|
19
|
+
) -> str | None:
|
|
20
20
|
if not scan_parameters.get('report', False):
|
|
21
21
|
return None
|
|
22
22
|
|
|
@@ -37,6 +37,6 @@ def try_set_aggregation_report_url_if_needed(
|
|
|
37
37
|
aggregation_report_url = try_get_aggregation_report_url_if_needed(scan_parameters, cycode_client, scan_type)
|
|
38
38
|
if aggregation_report_url:
|
|
39
39
|
_set_aggregation_report_url(ctx, aggregation_report_url)
|
|
40
|
-
logger.debug('Aggregation report URL set successfully', {'aggregation_report_url': aggregation_report_url})
|
|
40
|
+
logger.debug('Aggregation report URL set successfully, %s', {'aggregation_report_url': aggregation_report_url})
|
|
41
41
|
else:
|
|
42
42
|
logger.debug('No aggregation report URL found or report generation is disabled')
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import time
|
|
3
3
|
import zipfile
|
|
4
|
+
from collections.abc import Callable
|
|
4
5
|
from platform import platform
|
|
5
|
-
from typing import TYPE_CHECKING
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
6
7
|
|
|
7
8
|
import requests
|
|
8
9
|
import typer
|
|
@@ -147,7 +148,7 @@ def _get_scan_documents_thread_func(
|
|
|
147
148
|
is_git_diff: bool,
|
|
148
149
|
is_commit_range: bool,
|
|
149
150
|
scan_parameters: dict,
|
|
150
|
-
prezipped:
|
|
151
|
+
prezipped: 'InMemoryZip | None' = None,
|
|
151
152
|
) -> Callable[[list[Document]], tuple[str, CliError, LocalScanResult]]:
|
|
152
153
|
cycode_client = ctx.obj['client']
|
|
153
154
|
scan_type = ctx.obj['scan_type']
|
|
@@ -363,7 +364,7 @@ def _perform_scan_v4_async(
|
|
|
363
364
|
scan_parameters: dict,
|
|
364
365
|
is_git_diff: bool,
|
|
365
366
|
is_commit_range: bool,
|
|
366
|
-
on_upload_progress:
|
|
367
|
+
on_upload_progress: Callable | None = None,
|
|
367
368
|
) -> ZippedFileScanResult:
|
|
368
369
|
upload_link = cycode_client.get_upload_link(scan_type)
|
|
369
370
|
logger.debug('Got upload link, %s', {'upload_id': upload_link.upload_id})
|
|
@@ -390,7 +391,7 @@ def _perform_scan_async(
|
|
|
390
391
|
scan_type: str,
|
|
391
392
|
scan_parameters: dict,
|
|
392
393
|
is_commit_range: bool,
|
|
393
|
-
on_upload_progress:
|
|
394
|
+
on_upload_progress: Callable | None = None,
|
|
394
395
|
) -> ZippedFileScanResult:
|
|
395
396
|
scan_async_result = cycode_client.zipped_file_scan_async(
|
|
396
397
|
zipped_documents,
|
|
@@ -429,7 +430,7 @@ def _perform_scan(
|
|
|
429
430
|
is_commit_range: bool,
|
|
430
431
|
scan_parameters: dict,
|
|
431
432
|
should_use_sync_flow: bool = False,
|
|
432
|
-
on_upload_progress:
|
|
433
|
+
on_upload_progress: Callable | None = None,
|
|
433
434
|
) -> ZippedFileScanResult:
|
|
434
435
|
if should_use_sync_flow:
|
|
435
436
|
# it does not support commit range scans; should_use_sync_flow handles it
|
|
@@ -463,7 +464,7 @@ def poll_scan_results(
|
|
|
463
464
|
scan_id: str,
|
|
464
465
|
scan_type: str,
|
|
465
466
|
scan_parameters: dict,
|
|
466
|
-
polling_timeout:
|
|
467
|
+
polling_timeout: int | None = None,
|
|
467
468
|
) -> 'ZippedFileScanResult':
|
|
468
469
|
if polling_timeout is None:
|
|
469
470
|
polling_timeout = configuration_manager.get_scan_polling_timeout_in_seconds()
|
|
@@ -504,7 +505,7 @@ def report_scan_status(
|
|
|
504
505
|
files_to_scan_count: int,
|
|
505
506
|
zip_size: int,
|
|
506
507
|
command_scan_type: str,
|
|
507
|
-
error_message:
|
|
508
|
+
error_message: str | None,
|
|
508
509
|
) -> None:
|
|
509
510
|
try:
|
|
510
511
|
end_scan_time = time.time()
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import os
|
|
2
|
-
from typing import TYPE_CHECKING
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
3
3
|
|
|
4
4
|
import click
|
|
5
5
|
import requests
|
|
@@ -72,7 +72,7 @@ def _perform_commit_range_scan_async(
|
|
|
72
72
|
to_commit_zipped_documents: 'InMemoryZip',
|
|
73
73
|
scan_type: str,
|
|
74
74
|
scan_parameters: dict,
|
|
75
|
-
timeout:
|
|
75
|
+
timeout: int | None = None,
|
|
76
76
|
) -> ZippedFileScanResult:
|
|
77
77
|
scan_async_result = cycode_client.commit_range_scan_async(
|
|
78
78
|
from_commit_zipped_documents, to_commit_zipped_documents, scan_type, scan_parameters
|
|
@@ -90,7 +90,7 @@ def _perform_commit_range_scan_v4_async(
|
|
|
90
90
|
to_commit_zipped_documents: 'InMemoryZip',
|
|
91
91
|
scan_type: str,
|
|
92
92
|
scan_parameters: dict,
|
|
93
|
-
timeout:
|
|
93
|
+
timeout: int | None = None,
|
|
94
94
|
) -> ZippedFileScanResult:
|
|
95
95
|
from_upload_link = cycode_client.get_upload_link(scan_type)
|
|
96
96
|
logger.debug('Got from-commit upload link, %s', {'upload_id': from_upload_link.upload_id})
|
|
@@ -120,8 +120,8 @@ def _scan_commit_range_documents(
|
|
|
120
120
|
ctx: typer.Context,
|
|
121
121
|
from_documents_to_scan: list[Document],
|
|
122
122
|
to_documents_to_scan: list[Document],
|
|
123
|
-
scan_parameters:
|
|
124
|
-
timeout:
|
|
123
|
+
scan_parameters: dict | None = None,
|
|
124
|
+
timeout: int | None = None,
|
|
125
125
|
) -> None:
|
|
126
126
|
cycode_client = ctx.obj['client']
|
|
127
127
|
scan_type = ctx.obj['scan_type']
|
|
@@ -265,7 +265,7 @@ def _scan_sca_commit_range(ctx: typer.Context, repo_path: str, commit_range: str
|
|
|
265
265
|
|
|
266
266
|
|
|
267
267
|
def _scan_secret_commit_range(
|
|
268
|
-
ctx: typer.Context, repo_path: str, commit_range: str, max_commits_count:
|
|
268
|
+
ctx: typer.Context, repo_path: str, commit_range: str, max_commits_count: int | None = None
|
|
269
269
|
) -> None:
|
|
270
270
|
commit_diff_documents_to_scan = collect_commit_range_diff_documents(ctx, repo_path, commit_range, max_commits_count)
|
|
271
271
|
diff_documents_to_scan = excluder.exclude_irrelevant_documents_to_scan(
|
|
@@ -329,7 +329,7 @@ def _scan_sca_pre_commit(
|
|
|
329
329
|
repo_path: str,
|
|
330
330
|
base_ref: str = consts.GIT_HEAD_COMMIT_REV,
|
|
331
331
|
include_unstaged: bool = False,
|
|
332
|
-
paths:
|
|
332
|
+
paths: list[str] | None = None,
|
|
333
333
|
) -> None:
|
|
334
334
|
scan_parameters = get_scan_parameters(ctx, (repo_path,))
|
|
335
335
|
|
|
@@ -367,7 +367,7 @@ def _scan_secret_pre_commit(
|
|
|
367
367
|
repo_path: str,
|
|
368
368
|
base_ref: str = consts.GIT_HEAD_COMMIT_REV,
|
|
369
369
|
include_unstaged: bool = False,
|
|
370
|
-
paths:
|
|
370
|
+
paths: list[str] | None = None,
|
|
371
371
|
) -> None:
|
|
372
372
|
# collect_file_contents=False: the secret scan only ever uses diff_documents below, so skip
|
|
373
373
|
# building from_ref_documents/working_copy_documents (a disk read per changed file it would
|
|
@@ -395,7 +395,7 @@ def _scan_sast_pre_commit(
|
|
|
395
395
|
repo_path: str,
|
|
396
396
|
base_ref: str = consts.GIT_HEAD_COMMIT_REV,
|
|
397
397
|
include_unstaged: bool = False,
|
|
398
|
-
paths:
|
|
398
|
+
paths: list[str] | None = None,
|
|
399
399
|
**_,
|
|
400
400
|
) -> None:
|
|
401
401
|
scan_parameters = get_scan_parameters(ctx, (repo_path,))
|
|
@@ -435,7 +435,7 @@ def scan_pre_commit(
|
|
|
435
435
|
repo_path: str,
|
|
436
436
|
base_ref: str = consts.GIT_HEAD_COMMIT_REV,
|
|
437
437
|
include_unstaged: bool = False,
|
|
438
|
-
paths:
|
|
438
|
+
paths: list[str] | None = None,
|
|
439
439
|
) -> None:
|
|
440
440
|
scan_type = ctx.obj['scan_type']
|
|
441
441
|
if scan_type not in _SCAN_TYPE_TO_PRE_COMMIT_HANDLER:
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from typing import Optional
|
|
2
|
-
|
|
3
1
|
from cycode.cli import consts
|
|
4
2
|
from cycode.cli.cli_types import SeverityOption
|
|
5
3
|
from cycode.cli.config import configuration_manager
|
|
@@ -116,7 +114,7 @@ def _is_detection_sha_configured_in_exclusions(detection: Detection, exclusions:
|
|
|
116
114
|
return detection_sha in exclusions
|
|
117
115
|
|
|
118
116
|
|
|
119
|
-
def _get_package_name(detection: Detection) ->
|
|
117
|
+
def _get_package_name(detection: Detection) -> str | None:
|
|
120
118
|
package_name = detection.detection_details.get('vulnerable_component')
|
|
121
119
|
package_version = detection.detection_details.get('vulnerable_component_version')
|
|
122
120
|
|
|
@@ -130,7 +128,7 @@ def _get_package_name(detection: Detection) -> Optional[str]:
|
|
|
130
128
|
return None
|
|
131
129
|
|
|
132
130
|
|
|
133
|
-
def _get_cve_identifier(detection: Detection) ->
|
|
131
|
+
def _get_cve_identifier(detection: Detection) -> str | None:
|
|
134
132
|
return detection.detection_details.get('alert', {}).get('cve_identifier')
|
|
135
133
|
|
|
136
134
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import os
|
|
2
2
|
from pathlib import Path
|
|
3
|
-
from typing import Annotated
|
|
3
|
+
from typing import Annotated
|
|
4
4
|
|
|
5
5
|
import typer
|
|
6
6
|
|
|
@@ -47,7 +47,7 @@ def _validate_base_ref(repo_path: str, base_ref: str) -> None:
|
|
|
47
47
|
|
|
48
48
|
def pre_commit_command(
|
|
49
49
|
ctx: typer.Context,
|
|
50
|
-
_: Annotated[
|
|
50
|
+
_: Annotated[list[str] | None, typer.Argument(help='Ignored arguments', hidden=True)] = None,
|
|
51
51
|
base_ref: Annotated[
|
|
52
52
|
str,
|
|
53
53
|
typer.Option(
|
|
@@ -66,7 +66,7 @@ def pre_commit_command(
|
|
|
66
66
|
),
|
|
67
67
|
] = False,
|
|
68
68
|
paths: Annotated[
|
|
69
|
-
|
|
69
|
+
list[Path] | None,
|
|
70
70
|
typer.Option(
|
|
71
71
|
'--path',
|
|
72
72
|
help='Optional paths to scope the diff scan to (e.g. the file currently open in an IDE). '
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import os
|
|
3
|
-
from typing import Annotated
|
|
3
|
+
from typing import Annotated
|
|
4
4
|
|
|
5
5
|
import typer
|
|
6
6
|
|
|
@@ -28,7 +28,7 @@ from cycode.logger import set_logging_level
|
|
|
28
28
|
|
|
29
29
|
def pre_push_command(
|
|
30
30
|
ctx: typer.Context,
|
|
31
|
-
_: Annotated[
|
|
31
|
+
_: Annotated[list[str] | None, typer.Argument(help='Ignored arguments', hidden=True)] = None,
|
|
32
32
|
) -> None:
|
|
33
33
|
try:
|
|
34
34
|
if should_skip_pre_receive_scan():
|
|
@@ -63,7 +63,7 @@ def pre_push_command(
|
|
|
63
63
|
handle_scan_exception(ctx, e)
|
|
64
64
|
|
|
65
65
|
|
|
66
|
-
def _get_pre_push_commit_range() ->
|
|
66
|
+
def _get_pre_push_commit_range() -> str | None:
|
|
67
67
|
commit_range = get_pre_commit_framework_push_range()
|
|
68
68
|
if commit_range:
|
|
69
69
|
logger.debug('Using push details from the pre-commit framework, %s', {'commit_range': commit_range})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import os
|
|
3
|
-
from typing import Annotated
|
|
3
|
+
from typing import Annotated
|
|
4
4
|
|
|
5
5
|
import typer
|
|
6
6
|
|
|
@@ -25,7 +25,7 @@ from cycode.logger import set_logging_level
|
|
|
25
25
|
|
|
26
26
|
def pre_receive_command(
|
|
27
27
|
ctx: typer.Context,
|
|
28
|
-
_: Annotated[
|
|
28
|
+
_: Annotated[list[str] | None, typer.Argument(help='Ignored arguments', hidden=True)] = None,
|
|
29
29
|
) -> None:
|
|
30
30
|
try:
|
|
31
31
|
if should_skip_pre_receive_scan():
|