-
Notifications
You must be signed in to change notification settings - Fork 62
Expand file tree
/
Copy pathscan_command.py
More file actions
185 lines (161 loc) · 6.66 KB
/
scan_command.py
File metadata and controls
185 lines (161 loc) · 6.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
import os
from pathlib import Path
from typing import Annotated, Optional
import click
import typer
from cycode.cli.apps.activation_manager import report_cli_activation, should_report_cli_activation
from cycode.cli.apps.sca_options import (
GradleAllSubProjectsOption,
MavenSettingsFileOption,
NoRestoreOption,
apply_sca_restore_options_to_context,
)
from cycode.cli.apps.scan.remote_url_resolver import _try_get_git_remote_url
from cycode.cli.cli_types import ExportTypeOption, ScanTypeOption, ScaScanTypeOption, SeverityOption
from cycode.cli.consts import (
ISSUE_DETECTED_STATUS_CODE,
NO_ISSUES_STATUS_CODE,
)
from cycode.cli.files_collector.file_excluder import excluder
from cycode.cli.utils import scan_utils
from cycode.cli.utils.get_api_client import get_scan_cycode_client
_EXPORT_RICH_HELP_PANEL = 'Export options'
_SCA_RICH_HELP_PANEL = 'SCA options'
_SECRET_RICH_HELP_PANEL = 'Secret options'
def scan_command(
ctx: typer.Context,
scan_type: Annotated[
ScanTypeOption,
typer.Option(
'--scan-type',
'-t',
help='Specify the type of scan you wish to execute.',
case_sensitive=False,
),
] = ScanTypeOption.SECRET,
soft_fail: Annotated[
bool, typer.Option('--soft-fail', help='Run the scan without failing; always return a non-error status code.')
] = False,
severity_threshold: Annotated[
SeverityOption,
typer.Option(
help='Show violations only for the specified level or higher.',
case_sensitive=False,
),
] = SeverityOption.INFO,
sync: Annotated[
bool,
typer.Option(
'--sync', help='Run scan synchronously (INTERNAL FOR IDEs).', show_default='asynchronously', hidden=True
),
] = False,
report: Annotated[
bool,
typer.Option(
'--cycode-report',
help='When specified, displays a link to the scan report in the Cycode platform in the console output.',
),
] = False,
show_secret: Annotated[
bool, typer.Option('--show-secret', help='Show Secrets in plain text.', rich_help_panel=_SECRET_RICH_HELP_PANEL)
] = False,
sca_scan: Annotated[
list[ScaScanTypeOption],
typer.Option(
help='Specify the type of SCA scan you wish to execute.',
rich_help_panel=_SCA_RICH_HELP_PANEL,
),
] = (ScaScanTypeOption.PACKAGE_VULNERABILITIES, ScaScanTypeOption.LICENSE_COMPLIANCE),
monitor: Annotated[
bool,
typer.Option(
'--monitor',
help='When specified, the scan results are recorded in the Discovery module.',
rich_help_panel=_SCA_RICH_HELP_PANEL,
),
] = False,
no_restore: NoRestoreOption = False,
gradle_all_sub_projects: GradleAllSubProjectsOption = False,
maven_settings_file: MavenSettingsFileOption = None,
export_type: Annotated[
ExportTypeOption,
typer.Option(
'--export-type',
case_sensitive=False,
help='Specify the export type. '
'HTML and SVG will export terminal output and rely on --output option. '
'JSON always exports JSON.',
rich_help_panel=_EXPORT_RICH_HELP_PANEL,
),
] = None,
export_file: Annotated[
Optional[Path],
typer.Option(
'--export-file',
help='Export file. Path to the file where the export will be saved.',
dir_okay=False,
writable=True,
rich_help_panel=_EXPORT_RICH_HELP_PANEL,
),
] = None,
) -> None:
""":mag: [bold cyan]Scan code for vulnerabilities (Secrets, IaC, SCA, SAST).[/]
This command scans your code for various types of security issues, including:
* [yellow]Secrets:[/] Hardcoded credentials and sensitive information.
* [dodger_blue1]Infrastructure as Code (IaC):[/] Misconfigurations in Terraform, CloudFormation, etc.
* [green]Software Composition Analysis (SCA):[/] Vulnerabilities and license issues in dependencies.
* [magenta]Static Application Security Testing (SAST):[/] Code quality and security flaws.
Example usage:
* `cycode scan path <PATH>`: Scan a specific local directory or file.
* `cycode scan repository <PATH>`: Scan Git related files in a local Git repository.
* `cycode scan commit-history <PATH>`: Scan the commit history of a local Git repository.
"""
if export_file and export_type is None:
raise typer.BadParameter(
'Export type must be specified when --export-file is provided.',
param_hint='--export-type',
)
if export_type and export_file is None:
raise typer.BadParameter(
'Export file must be specified when --export-type is provided.',
param_hint='--export-file',
)
ctx.obj['show_secret'] = show_secret
ctx.obj['soft_fail'] = soft_fail
ctx.obj['scan_type'] = scan_type
ctx.obj['sync'] = sync
ctx.obj['severity_threshold'] = severity_threshold
ctx.obj['monitor'] = monitor
ctx.obj['report'] = report
apply_sca_restore_options_to_context(ctx, no_restore, gradle_all_sub_projects, maven_settings_file)
scan_client = get_scan_cycode_client(ctx)
ctx.obj['client'] = scan_client
plugin_app_name = ctx.obj.get('plugin_app_name')
plugin_app_version = ctx.obj.get('plugin_app_version')
if should_report_cli_activation(plugin_app_name, plugin_app_version):
report_cli_activation(scan_client.scan_cycode_client, plugin_app_name, plugin_app_version)
# Get remote URL from current working directory
remote_url = _try_get_git_remote_url(os.getcwd())
remote_scan_config = scan_client.get_scan_configuration_safe(scan_type, remote_url)
if remote_scan_config:
excluder.apply_scan_config(str(scan_type), remote_scan_config)
ctx.obj['scan_config'] = remote_scan_config
if export_type and export_file:
console_printer = ctx.obj['console_printer']
console_printer.enable_recording(export_type, export_file)
_sca_scan_to_context(ctx, sca_scan)
def _sca_scan_to_context(ctx: typer.Context, sca_scan_user_selected: list[str]) -> None:
for sca_scan_option_selected in sca_scan_user_selected:
ctx.obj[sca_scan_option_selected] = True
@click.pass_context
def scan_command_result_callback(ctx: click.Context, *_, **__) -> None:
ctx.obj['scan_finalized'] = True
progress_bar = ctx.obj.get('progress_bar')
if progress_bar:
progress_bar.stop()
if ctx.obj['soft_fail']:
raise typer.Exit(0)
exit_code = NO_ISSUES_STATUS_CODE
if scan_utils.is_scan_failed(ctx):
exit_code = ISSUE_DETECTED_STATUS_CODE
raise typer.Exit(exit_code)