cycode 3.10.3.dev1__tar.gz → 3.10.4.dev1__tar.gz
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-3.10.3.dev1 → cycode-3.10.4.dev1}/PKG-INFO +31 -11
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/README.md +32 -12
- cycode-3.10.4.dev1/cycode/__init__.py +1 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/report/sbom/path/path_command.py +11 -14
- cycode-3.10.4.dev1/cycode/cli/apps/sca_options.py +47 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/scan/code_scanner.py +76 -4
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/scan/commit_range_scanner.py +51 -8
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/scan/scan_command.py +10 -30
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/cli_types.py +1 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/consts.py +5 -2
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/sca/base_restore_dependencies.py +28 -4
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/sca/go/restore_go_dependencies.py +4 -4
- cycode-3.10.4.dev1/cycode/cli/files_collector/sca/npm/restore_deno_dependencies.py +46 -0
- cycode-3.10.4.dev1/cycode/cli/files_collector/sca/npm/restore_npm_dependencies.py +67 -0
- cycode-3.10.4.dev1/cycode/cli/files_collector/sca/npm/restore_pnpm_dependencies.py +70 -0
- cycode-3.10.4.dev1/cycode/cli/files_collector/sca/npm/restore_yarn_dependencies.py +70 -0
- cycode-3.10.4.dev1/cycode/cli/files_collector/sca/php/restore_composer_dependencies.py +54 -0
- cycode-3.10.4.dev1/cycode/cli/files_collector/sca/python/restore_pipenv_dependencies.py +45 -0
- cycode-3.10.4.dev1/cycode/cli/files_collector/sca/python/restore_poetry_dependencies.py +62 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/sca/sca_file_collector.py +13 -1
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/zip_documents.py +5 -1
- cycode-3.10.4.dev1/cycode/cli/utils/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/utils/scan_batch.py +5 -1
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/utils/scan_utils.py +5 -0
- cycode-3.10.4.dev1/cycode/cyclient/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cyclient/models.py +20 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cyclient/scan_client.py +61 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/pyproject.toml +1 -1
- cycode-3.10.3.dev1/cycode/__init__.py +0 -1
- cycode-3.10.3.dev1/cycode/cli/files_collector/sca/npm/restore_npm_dependencies.py +0 -180
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/LICENCE +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/__main__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/app.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/ai_guardrails/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/ai_guardrails/command_utils.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/ai_guardrails/consts.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/ai_guardrails/hooks_manager.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/ai_guardrails/install_command.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/ai_guardrails/scan/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/ai_guardrails/scan/consts.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/ai_guardrails/scan/handlers.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/ai_guardrails/scan/payload.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/ai_guardrails/scan/policy.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/ai_guardrails/scan/response_builders.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/ai_guardrails/scan/scan_command.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/ai_guardrails/scan/types.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/ai_guardrails/scan/utils.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/ai_guardrails/status_command.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/ai_guardrails/uninstall_command.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/ai_remediation/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/ai_remediation/ai_remediation_command.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/ai_remediation/apply_fix.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/ai_remediation/print_remediation.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/auth/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/auth/auth_command.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/auth/auth_common.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/auth/auth_manager.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/auth/models.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/configure/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/configure/configure_command.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/configure/consts.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/configure/messages.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/configure/prompts.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/ignore/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/ignore/ignore_command.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/mcp/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/mcp/mcp_command.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/report/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/report/report_command.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/report/sbom/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/report/sbom/common.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/report/sbom/path/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/report/sbom/repository_url/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/report/sbom/repository_url/repository_url_command.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/report/sbom/sbom_command.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/report/sbom/sbom_report_file.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/report_import/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/report_import/report_import_command.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/report_import/sbom/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/report_import/sbom/sbom_command.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/scan/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/scan/aggregation_report.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/scan/commit_history/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/scan/commit_history/commit_history_command.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/scan/detection_excluder.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/scan/path/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/scan/path/path_command.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/scan/pre_commit/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/scan/pre_commit/pre_commit_command.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/scan/pre_push/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/scan/pre_push/pre_push_command.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/scan/pre_receive/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/scan/pre_receive/pre_receive_command.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/scan/remote_url_resolver.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/scan/repository/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/scan/repository/repository_command.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/scan/scan_ci/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/scan/scan_ci/ci_integrations.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/scan/scan_ci/scan_ci_command.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/scan/scan_parameters.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/scan/scan_result.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/status/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/status/get_cli_status.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/status/models.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/status/status_command.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/apps/status/version_command.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/config.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/console.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/exceptions/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/exceptions/custom_exceptions.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/exceptions/handle_ai_remediation_errors.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/exceptions/handle_auth_errors.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/exceptions/handle_errors.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/exceptions/handle_report_sbom_errors.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/exceptions/handle_scan_errors.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/commit_range_documents.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/documents_walk_ignore.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/file_excluder.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/iac/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/iac/tf_content_generator.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/models/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/models/in_memory_zip.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/path_documents.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/repository_documents.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/sca/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/sca/go/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/sca/maven/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/sca/maven/restore_gradle_dependencies.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/sca/maven/restore_maven_dependencies.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/sca/npm/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/sca/nuget/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/sca/nuget/restore_nuget_dependencies.py +0 -0
- {cycode-3.10.3.dev1/cycode/cli/files_collector/sca/ruby → cycode-3.10.4.dev1/cycode/cli/files_collector/sca/php}/__init__.py +0 -0
- {cycode-3.10.3.dev1/cycode/cli/files_collector/sca/sbt → cycode-3.10.4.dev1/cycode/cli/files_collector/sca/python}/__init__.py +0 -0
- {cycode-3.10.3.dev1/cycode/cli/printers/tables → cycode-3.10.4.dev1/cycode/cli/files_collector/sca/ruby}/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/sca/ruby/restore_ruby_dependencies.py +0 -0
- {cycode-3.10.3.dev1/cycode/cli/printers/utils/detection_ordering → cycode-3.10.4.dev1/cycode/cli/files_collector/sca/sbt}/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/sca/sbt/restore_sbt_dependencies.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/files_collector/walk_ignore.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/logger.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/main.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/models.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/printers/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/printers/console_printer.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/printers/json_printer.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/printers/printer_base.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/printers/rich_printer.py +0 -0
- {cycode-3.10.3.dev1/cycode/cli/user_settings → cycode-3.10.4.dev1/cycode/cli/printers/tables}/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/printers/tables/sca_table_printer.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/printers/tables/table.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/printers/tables/table_models.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/printers/tables/table_printer.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/printers/tables/table_printer_base.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/printers/text_printer.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/printers/utils/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/printers/utils/code_snippet_syntax.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/printers/utils/detection_data.py +0 -0
- {cycode-3.10.3.dev1/cycode/cli/utils → cycode-3.10.4.dev1/cycode/cli/printers/utils/detection_ordering}/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/printers/utils/detection_ordering/common_ordering.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/printers/utils/detection_ordering/sca_ordering.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/printers/utils/rich_helpers.py +0 -0
- {cycode-3.10.3.dev1/cycode/cyclient → cycode-3.10.4.dev1/cycode/cli/user_settings}/__init__.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/user_settings/base_file_manager.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/user_settings/config_file_manager.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/user_settings/configuration_manager.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/user_settings/credentials_manager.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/user_settings/jwt_creator.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/utils/enum_utils.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/utils/get_api_client.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/utils/git_proxy.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/utils/ignore_utils.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/utils/jwt_utils.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/utils/path_utils.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/utils/progress_bar.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/utils/shell_executor.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/utils/string_utils.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/utils/task_timer.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/utils/url_utils.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/utils/version_checker.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cli/utils/yaml_utils.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/config.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cyclient/ai_security_manager_client.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cyclient/ai_security_manager_service_config.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cyclient/auth_client.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cyclient/base_token_auth_client.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cyclient/client_creator.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cyclient/config.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cyclient/config_dev.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cyclient/cycode_client.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cyclient/cycode_client_base.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cyclient/cycode_dev_based_client.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cyclient/cycode_oidc_based_client.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cyclient/cycode_token_based_client.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cyclient/headers.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cyclient/import_sbom_client.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cyclient/logger.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cyclient/report_client.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/cyclient/scan_config_base.py +0 -0
- {cycode-3.10.3.dev1 → cycode-3.10.4.dev1}/cycode/logger.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cycode
|
|
3
|
-
Version: 3.10.
|
|
3
|
+
Version: 3.10.4.dev1
|
|
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
|
|
@@ -710,15 +710,33 @@ In the previous example, if you wanted to only scan a branch named `dev`, you co
|
|
|
710
710
|
> [!NOTE]
|
|
711
711
|
> This option is only available to SCA scans.
|
|
712
712
|
|
|
713
|
-
|
|
714
|
-
To disable lock restore in use `--no-restore` option.
|
|
713
|
+
When running an SCA scan, Cycode CLI automatically attempts to restore (generate) a dependency lockfile for each supported manifest file it finds. This allows scanning transitive dependencies, not just the ones listed directly in the manifest. To skip this step and scan only direct dependencies, use the `--no-restore` flag.
|
|
715
714
|
|
|
716
|
-
|
|
717
|
-
* `sbt-dependency-lock` plugin: Install the plugin by adding the following line to `project/plugins.sbt`:
|
|
715
|
+
The following ecosystems support automatic lockfile restoration:
|
|
718
716
|
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
717
|
+
| Ecosystem | Manifest file | Lockfile generated | Tool invoked (when lockfile is absent) |
|
|
718
|
+
|---|---|---|---|
|
|
719
|
+
| npm | `package.json` | `package-lock.json` | `npm install --package-lock-only --ignore-scripts --no-audit` |
|
|
720
|
+
| Yarn | `package.json` | `yarn.lock` | `yarn install --ignore-scripts` |
|
|
721
|
+
| pnpm | `package.json` | `pnpm-lock.yaml` | `pnpm install --ignore-scripts` |
|
|
722
|
+
| Deno | `deno.json` / `deno.jsonc` | `deno.lock` | *(read existing lockfile only)* |
|
|
723
|
+
| Go | `go.mod` | `go.mod.graph` | `go list -m -json all` + `go mod graph` |
|
|
724
|
+
| Maven | `pom.xml` | `bcde.mvndeps` | `mvn dependency:tree` |
|
|
725
|
+
| Gradle | `build.gradle` / `build.gradle.kts` | `gradle-dependencies-generated.txt` | `gradle dependencies -q --console plain` |
|
|
726
|
+
| SBT | `build.sbt` | `build.sbt.lock` | `sbt dependencyLockWrite` |
|
|
727
|
+
| NuGet | `*.csproj` | `packages.lock.json` | `dotnet restore --use-lock-file` |
|
|
728
|
+
| Ruby | `Gemfile` | `Gemfile.lock` | `bundle --quiet` |
|
|
729
|
+
| Poetry | `pyproject.toml` | `poetry.lock` | `poetry lock` |
|
|
730
|
+
| Pipenv | `Pipfile` | `Pipfile.lock` | `pipenv lock` |
|
|
731
|
+
| PHP Composer | `composer.json` | `composer.lock` | `composer update --no-cache --no-install --no-scripts --ignore-platform-reqs` |
|
|
732
|
+
|
|
733
|
+
If a lockfile already exists alongside the manifest, Cycode reads it directly without running any install command.
|
|
734
|
+
|
|
735
|
+
**SBT prerequisite:** The `sbt-dependency-lock` plugin must be installed. Add the following line to `project/plugins.sbt`:
|
|
736
|
+
|
|
737
|
+
```text
|
|
738
|
+
addSbtPlugin("software.purpledragon" % "sbt-dependency-lock" % "1.5.1")
|
|
739
|
+
```
|
|
722
740
|
|
|
723
741
|
### Repository Scan
|
|
724
742
|
|
|
@@ -1351,9 +1369,11 @@ For example:\
|
|
|
1351
1369
|
|
|
1352
1370
|
The `path` subcommand supports the following additional options:
|
|
1353
1371
|
|
|
1354
|
-
| Option
|
|
1355
|
-
|
|
1356
|
-
| `--
|
|
1372
|
+
| Option | Description |
|
|
1373
|
+
|-----------------------------|-------------------------------------------------------------------------------------------------------------------------------------|
|
|
1374
|
+
| `--no-restore` | Skip lockfile restoration and scan direct dependencies only. See [Lock Restore Option](#lock-restore-option) for details. |
|
|
1375
|
+
| `--gradle-all-sub-projects` | Run the Gradle restore command for all sub-projects (use from the root of a multi-project Gradle build). |
|
|
1376
|
+
| `--maven-settings-file` | For Maven only, allows using a custom [settings.xml](https://maven.apache.org/settings.html) file when building the dependency tree. |
|
|
1357
1377
|
|
|
1358
1378
|
# Import Command
|
|
1359
1379
|
|
|
@@ -668,15 +668,33 @@ In the previous example, if you wanted to only scan a branch named `dev`, you co
|
|
|
668
668
|
> [!NOTE]
|
|
669
669
|
> This option is only available to SCA scans.
|
|
670
670
|
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
671
|
+
When running an SCA scan, Cycode CLI automatically attempts to restore (generate) a dependency lockfile for each supported manifest file it finds. This allows scanning transitive dependencies, not just the ones listed directly in the manifest. To skip this step and scan only direct dependencies, use the `--no-restore` flag.
|
|
672
|
+
|
|
673
|
+
The following ecosystems support automatic lockfile restoration:
|
|
674
|
+
|
|
675
|
+
| Ecosystem | Manifest file | Lockfile generated | Tool invoked (when lockfile is absent) |
|
|
676
|
+
|---|---|---|---|
|
|
677
|
+
| npm | `package.json` | `package-lock.json` | `npm install --package-lock-only --ignore-scripts --no-audit` |
|
|
678
|
+
| Yarn | `package.json` | `yarn.lock` | `yarn install --ignore-scripts` |
|
|
679
|
+
| pnpm | `package.json` | `pnpm-lock.yaml` | `pnpm install --ignore-scripts` |
|
|
680
|
+
| Deno | `deno.json` / `deno.jsonc` | `deno.lock` | *(read existing lockfile only)* |
|
|
681
|
+
| Go | `go.mod` | `go.mod.graph` | `go list -m -json all` + `go mod graph` |
|
|
682
|
+
| Maven | `pom.xml` | `bcde.mvndeps` | `mvn dependency:tree` |
|
|
683
|
+
| Gradle | `build.gradle` / `build.gradle.kts` | `gradle-dependencies-generated.txt` | `gradle dependencies -q --console plain` |
|
|
684
|
+
| SBT | `build.sbt` | `build.sbt.lock` | `sbt dependencyLockWrite` |
|
|
685
|
+
| NuGet | `*.csproj` | `packages.lock.json` | `dotnet restore --use-lock-file` |
|
|
686
|
+
| Ruby | `Gemfile` | `Gemfile.lock` | `bundle --quiet` |
|
|
687
|
+
| Poetry | `pyproject.toml` | `poetry.lock` | `poetry lock` |
|
|
688
|
+
| Pipenv | `Pipfile` | `Pipfile.lock` | `pipenv lock` |
|
|
689
|
+
| PHP Composer | `composer.json` | `composer.lock` | `composer update --no-cache --no-install --no-scripts --ignore-platform-reqs` |
|
|
690
|
+
|
|
691
|
+
If a lockfile already exists alongside the manifest, Cycode reads it directly without running any install command.
|
|
692
|
+
|
|
693
|
+
**SBT prerequisite:** The `sbt-dependency-lock` plugin must be installed. Add the following line to `project/plugins.sbt`:
|
|
694
|
+
|
|
695
|
+
```text
|
|
696
|
+
addSbtPlugin("software.purpledragon" % "sbt-dependency-lock" % "1.5.1")
|
|
697
|
+
```
|
|
680
698
|
|
|
681
699
|
### Repository Scan
|
|
682
700
|
|
|
@@ -1309,9 +1327,11 @@ For example:\
|
|
|
1309
1327
|
|
|
1310
1328
|
The `path` subcommand supports the following additional options:
|
|
1311
1329
|
|
|
1312
|
-
| Option
|
|
1313
|
-
|
|
1314
|
-
| `--
|
|
1330
|
+
| Option | Description |
|
|
1331
|
+
|-----------------------------|-------------------------------------------------------------------------------------------------------------------------------------|
|
|
1332
|
+
| `--no-restore` | Skip lockfile restoration and scan direct dependencies only. See [Lock Restore Option](#lock-restore-option) for details. |
|
|
1333
|
+
| `--gradle-all-sub-projects` | Run the Gradle restore command for all sub-projects (use from the root of a multi-project Gradle build). |
|
|
1334
|
+
| `--maven-settings-file` | For Maven only, allows using a custom [settings.xml](https://maven.apache.org/settings.html) file when building the dependency tree. |
|
|
1315
1335
|
|
|
1316
1336
|
# Import Command
|
|
1317
1337
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '3.10.4.dev1' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import time
|
|
2
2
|
from pathlib import Path
|
|
3
|
-
from typing import Annotated
|
|
3
|
+
from typing import Annotated
|
|
4
4
|
|
|
5
5
|
import typer
|
|
6
6
|
|
|
7
7
|
from cycode.cli import consts
|
|
8
8
|
from cycode.cli.apps.report.sbom.common import create_sbom_report, send_report_feedback
|
|
9
|
+
from cycode.cli.apps.sca_options import (
|
|
10
|
+
GradleAllSubProjectsOption,
|
|
11
|
+
MavenSettingsFileOption,
|
|
12
|
+
NoRestoreOption,
|
|
13
|
+
apply_sca_restore_options_to_context,
|
|
14
|
+
)
|
|
9
15
|
from cycode.cli.exceptions.handle_report_sbom_errors import handle_report_exception
|
|
10
16
|
from cycode.cli.files_collector.path_documents import get_relevant_documents
|
|
11
17
|
from cycode.cli.files_collector.sca.sca_file_collector import add_sca_dependencies_tree_documents_if_needed
|
|
@@ -14,8 +20,6 @@ from cycode.cli.utils.get_api_client import get_report_cycode_client
|
|
|
14
20
|
from cycode.cli.utils.progress_bar import SbomReportProgressBarSection
|
|
15
21
|
from cycode.cli.utils.scan_utils import is_cycodeignore_allowed_by_scan_config
|
|
16
22
|
|
|
17
|
-
_SCA_RICH_HELP_PANEL = 'SCA options'
|
|
18
|
-
|
|
19
23
|
|
|
20
24
|
def path_command(
|
|
21
25
|
ctx: typer.Context,
|
|
@@ -23,18 +27,11 @@ def path_command(
|
|
|
23
27
|
Path,
|
|
24
28
|
typer.Argument(exists=True, resolve_path=True, help='Path to generate SBOM report for.', show_default=False),
|
|
25
29
|
],
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
'--maven-settings-file',
|
|
30
|
-
show_default=False,
|
|
31
|
-
help='When specified, Cycode will use this settings.xml file when building the maven dependency tree.',
|
|
32
|
-
dir_okay=False,
|
|
33
|
-
rich_help_panel=_SCA_RICH_HELP_PANEL,
|
|
34
|
-
),
|
|
35
|
-
] = None,
|
|
30
|
+
no_restore: NoRestoreOption = False,
|
|
31
|
+
gradle_all_sub_projects: GradleAllSubProjectsOption = False,
|
|
32
|
+
maven_settings_file: MavenSettingsFileOption = None,
|
|
36
33
|
) -> None:
|
|
37
|
-
ctx
|
|
34
|
+
apply_sca_restore_options_to_context(ctx, no_restore, gradle_all_sub_projects, maven_settings_file)
|
|
38
35
|
|
|
39
36
|
client = get_report_cycode_client(ctx)
|
|
40
37
|
report_parameters = ctx.obj['report_parameters']
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Annotated, Optional
|
|
3
|
+
|
|
4
|
+
import typer
|
|
5
|
+
|
|
6
|
+
_SCA_RICH_HELP_PANEL = 'SCA options'
|
|
7
|
+
|
|
8
|
+
NoRestoreOption = Annotated[
|
|
9
|
+
bool,
|
|
10
|
+
typer.Option(
|
|
11
|
+
'--no-restore',
|
|
12
|
+
help='When specified, Cycode will not run restore command. Will scan direct dependencies [b]only[/]!',
|
|
13
|
+
rich_help_panel=_SCA_RICH_HELP_PANEL,
|
|
14
|
+
),
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
GradleAllSubProjectsOption = Annotated[
|
|
18
|
+
bool,
|
|
19
|
+
typer.Option(
|
|
20
|
+
'--gradle-all-sub-projects',
|
|
21
|
+
help='When specified, Cycode will run gradle restore command for all sub projects. '
|
|
22
|
+
'Should run from root project directory [b]only[/]!',
|
|
23
|
+
rich_help_panel=_SCA_RICH_HELP_PANEL,
|
|
24
|
+
),
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
MavenSettingsFileOption = Annotated[
|
|
28
|
+
Optional[Path],
|
|
29
|
+
typer.Option(
|
|
30
|
+
'--maven-settings-file',
|
|
31
|
+
show_default=False,
|
|
32
|
+
help='When specified, Cycode will use this settings.xml file when building the maven dependency tree.',
|
|
33
|
+
dir_okay=False,
|
|
34
|
+
rich_help_panel=_SCA_RICH_HELP_PANEL,
|
|
35
|
+
),
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def apply_sca_restore_options_to_context(
|
|
40
|
+
ctx: typer.Context,
|
|
41
|
+
no_restore: bool,
|
|
42
|
+
gradle_all_sub_projects: bool,
|
|
43
|
+
maven_settings_file: Optional[Path],
|
|
44
|
+
) -> None:
|
|
45
|
+
ctx.obj['no_restore'] = no_restore
|
|
46
|
+
ctx.obj['gradle_all_sub_projects'] = gradle_all_sub_projects
|
|
47
|
+
ctx.obj['maven_settings_file'] = maven_settings_file
|
|
@@ -29,12 +29,15 @@ from cycode.cli.utils.scan_utils import (
|
|
|
29
29
|
generate_unique_scan_id,
|
|
30
30
|
is_cycodeignore_allowed_by_scan_config,
|
|
31
31
|
set_issue_detected_by_scan_results,
|
|
32
|
+
should_use_presigned_upload,
|
|
32
33
|
)
|
|
33
34
|
from cycode.cyclient.models import ZippedFileScanResult
|
|
34
35
|
from cycode.logger import get_logger
|
|
35
36
|
|
|
36
37
|
if TYPE_CHECKING:
|
|
37
38
|
from cycode.cli.files_collector.models.in_memory_zip import InMemoryZip
|
|
39
|
+
from cycode.cli.printers.console_printer import ConsolePrinter
|
|
40
|
+
from cycode.cli.utils.progress_bar import BaseProgressBar
|
|
38
41
|
from cycode.cyclient.scan_client import ScanClient
|
|
39
42
|
|
|
40
43
|
start_scan_time = time.time()
|
|
@@ -106,7 +109,10 @@ def _should_use_sync_flow(command_scan_type: str, scan_type: str, sync_option: b
|
|
|
106
109
|
|
|
107
110
|
|
|
108
111
|
def _get_scan_documents_thread_func(
|
|
109
|
-
ctx: typer.Context,
|
|
112
|
+
ctx: typer.Context,
|
|
113
|
+
is_git_diff: bool,
|
|
114
|
+
is_commit_range: bool,
|
|
115
|
+
scan_parameters: dict,
|
|
110
116
|
) -> Callable[[list[Document]], tuple[str, CliError, LocalScanResult]]:
|
|
111
117
|
cycode_client = ctx.obj['client']
|
|
112
118
|
scan_type = ctx.obj['scan_type']
|
|
@@ -180,6 +186,36 @@ def _get_scan_documents_thread_func(
|
|
|
180
186
|
return _scan_batch_thread_func
|
|
181
187
|
|
|
182
188
|
|
|
189
|
+
def _run_presigned_upload_scan(
|
|
190
|
+
scan_batch_thread_func: Callable,
|
|
191
|
+
scan_type: str,
|
|
192
|
+
documents_to_scan: list[Document],
|
|
193
|
+
progress_bar: 'BaseProgressBar',
|
|
194
|
+
printer: 'ConsolePrinter',
|
|
195
|
+
) -> tuple:
|
|
196
|
+
try:
|
|
197
|
+
# Try to zip all documents as a single batch; ZipTooLargeError raised if it exceeds the scan type's limit
|
|
198
|
+
zip_documents(scan_type, documents_to_scan)
|
|
199
|
+
# It fits: skip batching and upload everything as one ZIP
|
|
200
|
+
return run_parallel_batched_scan(
|
|
201
|
+
scan_batch_thread_func,
|
|
202
|
+
scan_type,
|
|
203
|
+
documents_to_scan,
|
|
204
|
+
progress_bar=progress_bar,
|
|
205
|
+
skip_batching=True,
|
|
206
|
+
)
|
|
207
|
+
except custom_exceptions.ZipTooLargeError:
|
|
208
|
+
printer.print_warning(
|
|
209
|
+
'The scan is too large to upload as a single file. This may result in corrupted scan results.'
|
|
210
|
+
)
|
|
211
|
+
return run_parallel_batched_scan(
|
|
212
|
+
scan_batch_thread_func,
|
|
213
|
+
scan_type,
|
|
214
|
+
documents_to_scan,
|
|
215
|
+
progress_bar=progress_bar,
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
|
|
183
219
|
def scan_documents(
|
|
184
220
|
ctx: typer.Context,
|
|
185
221
|
documents_to_scan: list[Document],
|
|
@@ -203,9 +239,15 @@ def scan_documents(
|
|
|
203
239
|
return
|
|
204
240
|
|
|
205
241
|
scan_batch_thread_func = _get_scan_documents_thread_func(ctx, is_git_diff, is_commit_range, scan_parameters)
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
242
|
+
|
|
243
|
+
if should_use_presigned_upload(scan_type):
|
|
244
|
+
errors, local_scan_results = _run_presigned_upload_scan(
|
|
245
|
+
scan_batch_thread_func, scan_type, documents_to_scan, progress_bar, printer
|
|
246
|
+
)
|
|
247
|
+
else:
|
|
248
|
+
errors, local_scan_results = run_parallel_batched_scan(
|
|
249
|
+
scan_batch_thread_func, scan_type, documents_to_scan, progress_bar=progress_bar
|
|
250
|
+
)
|
|
209
251
|
|
|
210
252
|
try_set_aggregation_report_url_if_needed(ctx, scan_parameters, ctx.obj['client'], scan_type)
|
|
211
253
|
|
|
@@ -217,6 +259,31 @@ def scan_documents(
|
|
|
217
259
|
print_local_scan_results(ctx, local_scan_results, errors)
|
|
218
260
|
|
|
219
261
|
|
|
262
|
+
def _perform_scan_v4_async(
|
|
263
|
+
cycode_client: 'ScanClient',
|
|
264
|
+
zipped_documents: 'InMemoryZip',
|
|
265
|
+
scan_type: str,
|
|
266
|
+
scan_parameters: dict,
|
|
267
|
+
is_git_diff: bool,
|
|
268
|
+
is_commit_range: bool,
|
|
269
|
+
) -> ZippedFileScanResult:
|
|
270
|
+
upload_link = cycode_client.get_upload_link(scan_type)
|
|
271
|
+
logger.debug('Got upload link, %s', {'upload_id': upload_link.upload_id})
|
|
272
|
+
|
|
273
|
+
cycode_client.upload_to_presigned_post(upload_link.url, upload_link.presigned_post_fields, zipped_documents)
|
|
274
|
+
logger.debug('Uploaded zip to presigned URL')
|
|
275
|
+
|
|
276
|
+
scan_async_result = cycode_client.scan_repository_from_upload_id(
|
|
277
|
+
scan_type, upload_link.upload_id, scan_parameters, is_git_diff, is_commit_range
|
|
278
|
+
)
|
|
279
|
+
logger.debug(
|
|
280
|
+
'Presigned upload scan request triggered, %s',
|
|
281
|
+
{'scan_id': scan_async_result.scan_id, 'upload_id': upload_link.upload_id},
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
return poll_scan_results(cycode_client, scan_async_result.scan_id, scan_type, scan_parameters)
|
|
285
|
+
|
|
286
|
+
|
|
220
287
|
def _perform_scan_async(
|
|
221
288
|
cycode_client: 'ScanClient',
|
|
222
289
|
zipped_documents: 'InMemoryZip',
|
|
@@ -262,6 +329,11 @@ def _perform_scan(
|
|
|
262
329
|
# it does not support commit range scans; should_use_sync_flow handles it
|
|
263
330
|
return _perform_scan_sync(cycode_client, zipped_documents, scan_type, scan_parameters, is_git_diff)
|
|
264
331
|
|
|
332
|
+
if should_use_presigned_upload(scan_type):
|
|
333
|
+
return _perform_scan_v4_async(
|
|
334
|
+
cycode_client, zipped_documents, scan_type, scan_parameters, is_git_diff, is_commit_range
|
|
335
|
+
)
|
|
336
|
+
|
|
265
337
|
return _perform_scan_async(cycode_client, zipped_documents, scan_type, scan_parameters, is_commit_range)
|
|
266
338
|
|
|
267
339
|
|
|
@@ -44,6 +44,7 @@ from cycode.cli.utils.scan_utils import (
|
|
|
44
44
|
generate_unique_scan_id,
|
|
45
45
|
is_cycodeignore_allowed_by_scan_config,
|
|
46
46
|
set_issue_detected_by_scan_results,
|
|
47
|
+
should_use_presigned_upload,
|
|
47
48
|
)
|
|
48
49
|
from cycode.cyclient.models import ZippedFileScanResult
|
|
49
50
|
from cycode.logger import get_logger
|
|
@@ -86,6 +87,38 @@ def _perform_commit_range_scan_async(
|
|
|
86
87
|
return poll_scan_results(cycode_client, scan_async_result.scan_id, scan_type, scan_parameters, timeout)
|
|
87
88
|
|
|
88
89
|
|
|
90
|
+
def _perform_commit_range_scan_v4_async(
|
|
91
|
+
cycode_client: 'ScanClient',
|
|
92
|
+
from_commit_zipped_documents: 'InMemoryZip',
|
|
93
|
+
to_commit_zipped_documents: 'InMemoryZip',
|
|
94
|
+
scan_type: str,
|
|
95
|
+
scan_parameters: dict,
|
|
96
|
+
timeout: Optional[int] = None,
|
|
97
|
+
) -> ZippedFileScanResult:
|
|
98
|
+
from_upload_link = cycode_client.get_upload_link(scan_type)
|
|
99
|
+
logger.debug('Got from-commit upload link, %s', {'upload_id': from_upload_link.upload_id})
|
|
100
|
+
|
|
101
|
+
cycode_client.upload_to_presigned_post(
|
|
102
|
+
from_upload_link.url, from_upload_link.presigned_post_fields, from_commit_zipped_documents
|
|
103
|
+
)
|
|
104
|
+
logger.debug('Uploaded from-commit zip')
|
|
105
|
+
|
|
106
|
+
to_upload_link = cycode_client.get_upload_link(scan_type)
|
|
107
|
+
logger.debug('Got to-commit upload link, %s', {'upload_id': to_upload_link.upload_id})
|
|
108
|
+
|
|
109
|
+
cycode_client.upload_to_presigned_post(
|
|
110
|
+
to_upload_link.url, to_upload_link.presigned_post_fields, to_commit_zipped_documents
|
|
111
|
+
)
|
|
112
|
+
logger.debug('Uploaded to-commit zip')
|
|
113
|
+
|
|
114
|
+
scan_async_result = cycode_client.commit_range_scan_from_upload_ids(
|
|
115
|
+
scan_type, from_upload_link.upload_id, to_upload_link.upload_id, scan_parameters
|
|
116
|
+
)
|
|
117
|
+
logger.debug('V4 commit range scan request triggered, %s', {'scan_id': scan_async_result.scan_id})
|
|
118
|
+
|
|
119
|
+
return poll_scan_results(cycode_client, scan_async_result.scan_id, scan_type, scan_parameters, timeout)
|
|
120
|
+
|
|
121
|
+
|
|
89
122
|
def _scan_commit_range_documents(
|
|
90
123
|
ctx: typer.Context,
|
|
91
124
|
from_documents_to_scan: list[Document],
|
|
@@ -118,14 +151,24 @@ def _scan_commit_range_documents(
|
|
|
118
151
|
# for SAST it is files with diff between from_commit and to_commit
|
|
119
152
|
to_commit_zipped_documents = zip_documents(scan_type, to_documents_to_scan)
|
|
120
153
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
154
|
+
if should_use_presigned_upload(scan_type):
|
|
155
|
+
scan_result = _perform_commit_range_scan_v4_async(
|
|
156
|
+
cycode_client,
|
|
157
|
+
from_commit_zipped_documents,
|
|
158
|
+
to_commit_zipped_documents,
|
|
159
|
+
scan_type,
|
|
160
|
+
scan_parameters,
|
|
161
|
+
timeout,
|
|
162
|
+
)
|
|
163
|
+
else:
|
|
164
|
+
scan_result = _perform_commit_range_scan_async(
|
|
165
|
+
cycode_client,
|
|
166
|
+
from_commit_zipped_documents,
|
|
167
|
+
to_commit_zipped_documents,
|
|
168
|
+
scan_type,
|
|
169
|
+
scan_parameters,
|
|
170
|
+
timeout,
|
|
171
|
+
)
|
|
129
172
|
enrich_scan_result_with_data_from_detection_rules(cycode_client, scan_result)
|
|
130
173
|
|
|
131
174
|
progress_bar.update(ScanProgressBarSection.SCAN)
|
|
@@ -5,6 +5,12 @@ from typing import Annotated, Optional
|
|
|
5
5
|
import click
|
|
6
6
|
import typer
|
|
7
7
|
|
|
8
|
+
from cycode.cli.apps.sca_options import (
|
|
9
|
+
GradleAllSubProjectsOption,
|
|
10
|
+
MavenSettingsFileOption,
|
|
11
|
+
NoRestoreOption,
|
|
12
|
+
apply_sca_restore_options_to_context,
|
|
13
|
+
)
|
|
8
14
|
from cycode.cli.apps.scan.remote_url_resolver import _try_get_git_remote_url
|
|
9
15
|
from cycode.cli.cli_types import ExportTypeOption, ScanTypeOption, ScaScanTypeOption, SeverityOption
|
|
10
16
|
from cycode.cli.consts import (
|
|
@@ -72,33 +78,9 @@ def scan_command(
|
|
|
72
78
|
rich_help_panel=_SCA_RICH_HELP_PANEL,
|
|
73
79
|
),
|
|
74
80
|
] = False,
|
|
75
|
-
no_restore:
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
'--no-restore',
|
|
79
|
-
help='When specified, Cycode will not run restore command. Will scan direct dependencies [b]only[/]!',
|
|
80
|
-
rich_help_panel=_SCA_RICH_HELP_PANEL,
|
|
81
|
-
),
|
|
82
|
-
] = False,
|
|
83
|
-
gradle_all_sub_projects: Annotated[
|
|
84
|
-
bool,
|
|
85
|
-
typer.Option(
|
|
86
|
-
'--gradle-all-sub-projects',
|
|
87
|
-
help='When specified, Cycode will run gradle restore command for all sub projects. '
|
|
88
|
-
'Should run from root project directory [b]only[/]!',
|
|
89
|
-
rich_help_panel=_SCA_RICH_HELP_PANEL,
|
|
90
|
-
),
|
|
91
|
-
] = False,
|
|
92
|
-
maven_settings_file: Annotated[
|
|
93
|
-
Optional[Path],
|
|
94
|
-
typer.Option(
|
|
95
|
-
'--maven-settings-file',
|
|
96
|
-
show_default=False,
|
|
97
|
-
help='When specified, Cycode will use this settings.xml file when building the maven dependency tree.',
|
|
98
|
-
dir_okay=False,
|
|
99
|
-
rich_help_panel=_SCA_RICH_HELP_PANEL,
|
|
100
|
-
),
|
|
101
|
-
] = None,
|
|
81
|
+
no_restore: NoRestoreOption = False,
|
|
82
|
+
gradle_all_sub_projects: GradleAllSubProjectsOption = False,
|
|
83
|
+
maven_settings_file: MavenSettingsFileOption = None,
|
|
102
84
|
export_type: Annotated[
|
|
103
85
|
ExportTypeOption,
|
|
104
86
|
typer.Option(
|
|
@@ -152,10 +134,8 @@ def scan_command(
|
|
|
152
134
|
ctx.obj['sync'] = sync
|
|
153
135
|
ctx.obj['severity_threshold'] = severity_threshold
|
|
154
136
|
ctx.obj['monitor'] = monitor
|
|
155
|
-
ctx.obj['maven_settings_file'] = maven_settings_file
|
|
156
137
|
ctx.obj['report'] = report
|
|
157
|
-
ctx
|
|
158
|
-
ctx.obj['no_restore'] = no_restore
|
|
138
|
+
apply_sca_restore_options_to_context(ctx, no_restore, gradle_all_sub_projects, maven_settings_file)
|
|
159
139
|
|
|
160
140
|
scan_client = get_scan_cycode_client(ctx)
|
|
161
141
|
ctx.obj['client'] = scan_client
|
|
@@ -192,15 +192,18 @@ EXCLUSIONS_BY_CVE_SECTION_NAME = 'cves'
|
|
|
192
192
|
# 5MB in bytes (in decimal)
|
|
193
193
|
FILE_MAX_SIZE_LIMIT_IN_BYTES = 5000000
|
|
194
194
|
|
|
195
|
+
PRESIGNED_LINK_UPLOADED_ZIP_MAX_SIZE_LIMIT_IN_BYTES = 5 * 1024 * 1024 * 1024 # 5 GB (S3 presigned POST limit)
|
|
196
|
+
PRESIGNED_UPLOAD_SCAN_TYPES = {SAST_SCAN_TYPE}
|
|
197
|
+
|
|
195
198
|
DEFAULT_ZIP_MAX_SIZE_LIMIT_IN_BYTES = 20 * 1024 * 1024
|
|
196
199
|
ZIP_MAX_SIZE_LIMIT_IN_BYTES = {
|
|
197
200
|
SCA_SCAN_TYPE: 200 * 1024 * 1024,
|
|
198
|
-
SAST_SCAN_TYPE:
|
|
201
|
+
SAST_SCAN_TYPE: PRESIGNED_LINK_UPLOADED_ZIP_MAX_SIZE_LIMIT_IN_BYTES,
|
|
199
202
|
}
|
|
200
203
|
|
|
201
204
|
# scan in batches
|
|
202
205
|
DEFAULT_SCAN_BATCH_MAX_SIZE_IN_BYTES = 9 * 1024 * 1024
|
|
203
|
-
SCAN_BATCH_MAX_SIZE_IN_BYTES = {SAST_SCAN_TYPE:
|
|
206
|
+
SCAN_BATCH_MAX_SIZE_IN_BYTES = {SAST_SCAN_TYPE: PRESIGNED_LINK_UPLOADED_ZIP_MAX_SIZE_LIMIT_IN_BYTES}
|
|
204
207
|
SCAN_BATCH_MAX_SIZE_IN_BYTES_ENV_VAR_NAME = 'SCAN_BATCH_MAX_SIZE_IN_BYTES'
|
|
205
208
|
|
|
206
209
|
DEFAULT_SCAN_BATCH_MAX_FILES_COUNT = 1000
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import os
|
|
2
1
|
from abc import ABC, abstractmethod
|
|
2
|
+
from pathlib import Path
|
|
3
3
|
from typing import Optional
|
|
4
4
|
|
|
5
5
|
import typer
|
|
@@ -32,6 +32,9 @@ def execute_commands(
|
|
|
32
32
|
},
|
|
33
33
|
)
|
|
34
34
|
|
|
35
|
+
if not commands:
|
|
36
|
+
return None
|
|
37
|
+
|
|
35
38
|
try:
|
|
36
39
|
outputs = []
|
|
37
40
|
|
|
@@ -106,22 +109,43 @@ class BaseRestoreDependencies(ABC):
|
|
|
106
109
|
)
|
|
107
110
|
return Document(relative_restore_file_path, restore_file_content, self.is_git_diff)
|
|
108
111
|
|
|
112
|
+
def get_manifest_dir(self, document: Document) -> Optional[str]:
|
|
113
|
+
"""Return the directory containing the manifest file, resolving monitor-mode paths.
|
|
114
|
+
|
|
115
|
+
Uses the same path resolution as get_manifest_file_path() to ensure consistency.
|
|
116
|
+
Falls back to document.absolute_path when the resolved manifest path is ambiguous.
|
|
117
|
+
"""
|
|
118
|
+
manifest_file_path = self.get_manifest_file_path(document)
|
|
119
|
+
if manifest_file_path:
|
|
120
|
+
parent = Path(manifest_file_path).parent
|
|
121
|
+
# Skip '.' (no parent) and filesystem root (its own parent)
|
|
122
|
+
if parent != Path('.') and parent != parent.parent:
|
|
123
|
+
return str(parent)
|
|
124
|
+
|
|
125
|
+
base = document.absolute_path or document.path
|
|
126
|
+
if base:
|
|
127
|
+
parent = Path(base).parent
|
|
128
|
+
if parent != Path('.') and parent != parent.parent:
|
|
129
|
+
return str(parent)
|
|
130
|
+
|
|
131
|
+
return None
|
|
132
|
+
|
|
109
133
|
def get_working_directory(self, document: Document) -> Optional[str]:
|
|
110
|
-
return
|
|
134
|
+
return str(Path(document.absolute_path).parent)
|
|
111
135
|
|
|
112
136
|
def get_restored_lock_file_name(self, restore_file_path: str) -> str:
|
|
113
137
|
return self.get_lock_file_name()
|
|
114
138
|
|
|
115
139
|
def get_any_restore_file_already_exist(self, document: Document, restore_file_paths: list[str]) -> str:
|
|
116
140
|
for restore_file_path in restore_file_paths:
|
|
117
|
-
if
|
|
141
|
+
if Path(restore_file_path).is_file():
|
|
118
142
|
return restore_file_path
|
|
119
143
|
|
|
120
144
|
return build_dep_tree_path(document.absolute_path, self.get_lock_file_name())
|
|
121
145
|
|
|
122
146
|
@staticmethod
|
|
123
147
|
def verify_restore_file_already_exist(restore_file_path: str) -> bool:
|
|
124
|
-
return
|
|
148
|
+
return Path(restore_file_path).is_file()
|
|
125
149
|
|
|
126
150
|
@abstractmethod
|
|
127
151
|
def is_project(self, document: Document) -> bool:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
from pathlib import Path
|
|
2
2
|
from typing import Optional
|
|
3
3
|
|
|
4
4
|
import typer
|
|
@@ -20,13 +20,13 @@ class RestoreGoDependencies(BaseRestoreDependencies):
|
|
|
20
20
|
super().__init__(ctx, is_git_diff, command_timeout, create_output_file_manually=True)
|
|
21
21
|
|
|
22
22
|
def try_restore_dependencies(self, document: Document) -> Optional[Document]:
|
|
23
|
-
manifest_exists =
|
|
24
|
-
lock_exists =
|
|
23
|
+
manifest_exists = (Path(self.get_working_directory(document)) / BUILD_GO_FILE_NAME).is_file()
|
|
24
|
+
lock_exists = (Path(self.get_working_directory(document)) / BUILD_GO_LOCK_FILE_NAME).is_file()
|
|
25
25
|
|
|
26
26
|
if not manifest_exists or not lock_exists:
|
|
27
27
|
logger.info('No manifest go.mod file found' if not manifest_exists else 'No manifest go.sum file found')
|
|
28
28
|
|
|
29
|
-
manifest_files_exists = manifest_exists
|
|
29
|
+
manifest_files_exists = manifest_exists and lock_exists
|
|
30
30
|
|
|
31
31
|
if not manifest_files_exists:
|
|
32
32
|
return None
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
import typer
|
|
5
|
+
|
|
6
|
+
from cycode.cli.files_collector.sca.base_restore_dependencies import BaseRestoreDependencies, build_dep_tree_path
|
|
7
|
+
from cycode.cli.models import Document
|
|
8
|
+
from cycode.cli.utils.path_utils import get_file_content
|
|
9
|
+
from cycode.logger import get_logger
|
|
10
|
+
|
|
11
|
+
logger = get_logger('Deno Restore Dependencies')
|
|
12
|
+
|
|
13
|
+
DENO_MANIFEST_FILE_NAMES = ('deno.json', 'deno.jsonc')
|
|
14
|
+
DENO_LOCK_FILE_NAME = 'deno.lock'
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class RestoreDenoDependencies(BaseRestoreDependencies):
|
|
18
|
+
def __init__(self, ctx: typer.Context, is_git_diff: bool, command_timeout: int) -> None:
|
|
19
|
+
super().__init__(ctx, is_git_diff, command_timeout)
|
|
20
|
+
|
|
21
|
+
def is_project(self, document: Document) -> bool:
|
|
22
|
+
return Path(document.path).name in DENO_MANIFEST_FILE_NAMES
|
|
23
|
+
|
|
24
|
+
def try_restore_dependencies(self, document: Document) -> Optional[Document]:
|
|
25
|
+
manifest_dir = self.get_manifest_dir(document)
|
|
26
|
+
if not manifest_dir:
|
|
27
|
+
return None
|
|
28
|
+
|
|
29
|
+
lockfile_path = Path(manifest_dir) / DENO_LOCK_FILE_NAME
|
|
30
|
+
if not lockfile_path.is_file():
|
|
31
|
+
logger.debug('No deno.lock found alongside deno.json, skipping deno restore, %s', {'path': document.path})
|
|
32
|
+
return None
|
|
33
|
+
|
|
34
|
+
content = get_file_content(str(lockfile_path))
|
|
35
|
+
relative_path = build_dep_tree_path(document.path, DENO_LOCK_FILE_NAME)
|
|
36
|
+
logger.debug('Using existing deno.lock, %s', {'path': str(lockfile_path)})
|
|
37
|
+
return Document(relative_path, content, self.is_git_diff)
|
|
38
|
+
|
|
39
|
+
def get_commands(self, manifest_file_path: str) -> list[list[str]]:
|
|
40
|
+
return []
|
|
41
|
+
|
|
42
|
+
def get_lock_file_name(self) -> str:
|
|
43
|
+
return DENO_LOCK_FILE_NAME
|
|
44
|
+
|
|
45
|
+
def get_lock_file_names(self) -> list[str]:
|
|
46
|
+
return [DENO_LOCK_FILE_NAME]
|