cycode 3.11.6.dev1__tar.gz → 3.12.1__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.11.6.dev1 → cycode-3.12.1}/PKG-INFO +49 -5
- {cycode-3.11.6.dev1 → cycode-3.12.1}/README.md +48 -4
- cycode-3.12.1/cycode/__init__.py +1 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/mcp/mcp_command.py +134 -48
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report/sbom/path/path_command.py +4 -1
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/sca_options.py +11 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/code_scanner.py +1 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/scan_command.py +8 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/exceptions/custom_exceptions.py +9 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/exceptions/handle_scan_errors.py +6 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/path_documents.py +6 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/sca_file_collector.py +5 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/pyproject.toml +1 -1
- cycode-3.11.6.dev1/cycode/__init__.py +0 -1
- {cycode-3.11.6.dev1 → cycode-3.12.1}/LICENCE +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/__main__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/app.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/activation_manager.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/command_utils.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/consts.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/ensure_auth_command.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/hooks_manager.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/install_command.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/scan/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/scan/consts.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/scan/handlers.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/scan/payload.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/scan/policy.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/scan/response_builders.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/scan/scan_command.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/scan/types.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/scan/utils.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/status_command.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/uninstall_command.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_remediation/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_remediation/ai_remediation_command.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_remediation/apply_fix.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_remediation/print_remediation.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/auth/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/auth/auth_command.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/auth/auth_common.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/auth/auth_manager.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/auth/models.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/configure/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/configure/configure_command.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/configure/consts.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/configure/messages.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/configure/prompts.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ignore/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ignore/ignore_command.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/mcp/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report/report_command.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report/sbom/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report/sbom/common.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report/sbom/path/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report/sbom/repository_url/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report/sbom/repository_url/repository_url_command.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report/sbom/sbom_command.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report/sbom/sbom_report_file.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report_import/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report_import/report_import_command.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report_import/sbom/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report_import/sbom/sbom_command.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/aggregation_report.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/commit_history/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/commit_history/commit_history_command.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/commit_range_scanner.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/detection_excluder.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/path/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/path/path_command.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/pre_commit/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/pre_commit/pre_commit_command.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/pre_push/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/pre_push/pre_push_command.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/pre_receive/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/pre_receive/pre_receive_command.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/remote_url_resolver.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/repository/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/repository/repository_command.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/scan_ci/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/scan_ci/ci_integrations.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/scan_ci/scan_ci_command.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/scan_parameters.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/scan_result.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/status/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/status/get_cli_status.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/status/models.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/status/status_command.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/status/version_command.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/cli_types.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/config.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/console.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/consts.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/exceptions/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/exceptions/handle_ai_remediation_errors.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/exceptions/handle_auth_errors.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/exceptions/handle_errors.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/exceptions/handle_report_sbom_errors.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/commit_range_documents.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/documents_walk_ignore.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/file_excluder.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/iac/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/iac/tf_content_generator.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/models/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/models/in_memory_zip.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/repository_documents.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/base_restore_dependencies.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/go/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/go/restore_go_dependencies.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/maven/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/maven/restore_gradle_dependencies.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/maven/restore_maven_dependencies.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/npm/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/npm/restore_deno_dependencies.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/npm/restore_npm_dependencies.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/npm/restore_pnpm_dependencies.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/npm/restore_yarn_dependencies.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/nuget/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/nuget/restore_nuget_dependencies.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/php/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/php/restore_composer_dependencies.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/python/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/python/restore_pipenv_dependencies.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/python/restore_poetry_dependencies.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/ruby/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/ruby/restore_ruby_dependencies.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/sbt/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/sbt/restore_sbt_dependencies.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/walk_ignore.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/zip_documents.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/logger.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/main.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/models.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/console_printer.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/json_printer.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/printer_base.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/rich_printer.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/tables/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/tables/sca_table_printer.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/tables/table.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/tables/table_models.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/tables/table_printer.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/tables/table_printer_base.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/text_printer.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/utils/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/utils/code_snippet_syntax.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/utils/detection_data.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/utils/detection_ordering/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/utils/detection_ordering/common_ordering.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/utils/detection_ordering/sca_ordering.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/utils/rich_helpers.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/user_settings/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/user_settings/base_file_manager.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/user_settings/config_file_manager.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/user_settings/configuration_manager.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/user_settings/credentials_manager.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/user_settings/jwt_creator.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/binary_utils.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/enum_utils.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/get_api_client.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/git_proxy.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/ignore_utils.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/jwt_utils.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/path_utils.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/progress_bar.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/scan_batch.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/scan_utils.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/shell_executor.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/string_utils.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/task_timer.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/url_utils.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/version_checker.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/yaml_utils.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/config.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/__init__.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/ai_security_manager_client.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/ai_security_manager_service_config.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/auth_client.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/base_token_auth_client.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/cli_activation_client.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/client_creator.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/config.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/config_dev.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/cycode_client.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/cycode_client_base.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/cycode_dev_based_client.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/cycode_oidc_based_client.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/cycode_token_based_client.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/headers.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/import_sbom_client.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/logger.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/models.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/report_client.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/scan_client.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/scan_config_base.py +0 -0
- {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/logger.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cycode
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.12.1
|
|
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
|
|
@@ -71,6 +71,7 @@ This guide walks you through both installation and usage.
|
|
|
71
71
|
4. [Package Vulnerabilities](#package-vulnerabilities-option)
|
|
72
72
|
5. [License Compliance](#license-compliance-option)
|
|
73
73
|
6. [Lock Restore](#lock-restore-option)
|
|
74
|
+
7. [Stop on Error](#stop-on-error-option)
|
|
74
75
|
2. [Repository Scan](#repository-scan)
|
|
75
76
|
1. [Branch Option](#branch-option)
|
|
76
77
|
3. [Path Scan](#path-scan)
|
|
@@ -425,12 +426,22 @@ The MCP server provides the following tools that AI systems can use:
|
|
|
425
426
|
|
|
426
427
|
| Tool Name | Description |
|
|
427
428
|
|----------------------|---------------------------------------------------------------------------------------------|
|
|
428
|
-
| `cycode_secret_scan` | Scan
|
|
429
|
-
| `cycode_sca_scan` | Scan
|
|
430
|
-
| `cycode_iac_scan` | Scan
|
|
431
|
-
| `cycode_sast_scan` | Scan
|
|
429
|
+
| `cycode_secret_scan` | Scan for hardcoded secrets |
|
|
430
|
+
| `cycode_sca_scan` | Scan for Software Composition Analysis (SCA) - vulnerabilities and license issues |
|
|
431
|
+
| `cycode_iac_scan` | Scan for Infrastructure as Code (IaC) misconfigurations |
|
|
432
|
+
| `cycode_sast_scan` | Scan for Static Application Security Testing (SAST) - code quality and security flaws |
|
|
432
433
|
| `cycode_status` | Get Cycode CLI version, authentication status, and configuration information |
|
|
433
434
|
|
|
435
|
+
Each scan tool accepts two mutually exclusive input modes:
|
|
436
|
+
|
|
437
|
+
- **`paths`** *(preferred)* — one or more file or directory paths that exist on disk. Directories are scanned recursively. The Cycode engine handles file discovery and filtering, just as `cycode scan -t <type> path ./src` does from the CLI.
|
|
438
|
+
- **`files`** *(fallback)* — a dictionary mapping file paths to their full content as strings. Use this only when the files are not available on disk (e.g. in-memory edits not yet saved).
|
|
439
|
+
|
|
440
|
+
> [!TIP]
|
|
441
|
+
> Use `paths` whenever possible. Passing large files (like `package-lock.json`) as inline content can exceed token limits and slow down the AI client. With `paths`, the Cycode engine reads files directly from disk.
|
|
442
|
+
|
|
443
|
+
All scan tools return a JSON object that includes a `"summary"` field with a human-readable violation count (e.g. `"Cycode found 3 violations: 1 CRITICAL, 2 HIGH."`) in addition to the full `"detections"` array.
|
|
444
|
+
|
|
434
445
|
### Usage Examples
|
|
435
446
|
|
|
436
447
|
#### Basic Command Examples
|
|
@@ -588,6 +599,26 @@ cycode mcp -t streamable-http -H 127.0.0.2 -p 9000 &
|
|
|
588
599
|
> [!NOTE]
|
|
589
600
|
> The MCP server requires proper Cycode CLI authentication to function. Make sure you have authenticated using `cycode auth` or configured your credentials before starting the MCP server.
|
|
590
601
|
|
|
602
|
+
### Pre-authorizing Tools for Subagents (Claude Code)
|
|
603
|
+
|
|
604
|
+
When Claude Code delegates work to background subagents (e.g. to run scans in parallel), those subagents cannot display interactive permission prompts. If the Cycode tools have not been pre-approved, scans will fail silently in subagent contexts.
|
|
605
|
+
|
|
606
|
+
To pre-authorize the Cycode MCP tools so they work in all contexts including subagents, add them to the `allowedTools` list in your Claude Code settings (`~/.claude/settings.json`):
|
|
607
|
+
|
|
608
|
+
```json
|
|
609
|
+
{
|
|
610
|
+
"allowedTools": [
|
|
611
|
+
"mcp__cycode__cycode_secret_scan",
|
|
612
|
+
"mcp__cycode__cycode_sca_scan",
|
|
613
|
+
"mcp__cycode__cycode_iac_scan",
|
|
614
|
+
"mcp__cycode__cycode_sast_scan",
|
|
615
|
+
"mcp__cycode__cycode_status"
|
|
616
|
+
]
|
|
617
|
+
}
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
Once added, Claude Code will not prompt for approval when these tools are called, and they will work correctly inside subagents.
|
|
621
|
+
|
|
591
622
|
### Troubleshooting MCP
|
|
592
623
|
|
|
593
624
|
If you encounter issues with the MCP server, you can enable debug logging to get more detailed information about what's happening. There are two ways to enable debug logging:
|
|
@@ -631,6 +662,7 @@ The Cycode CLI application offers several types of scans so that you can choose
|
|
|
631
662
|
| `--monitor` | When specified, the scan results will be recorded in Cycode. |
|
|
632
663
|
| `--cycode-report` | Display a link to the scan report in the Cycode platform in the console output. |
|
|
633
664
|
| `--no-restore` | When specified, Cycode will not run the restore command. This will scan direct dependencies ONLY! |
|
|
665
|
+
| `--stop-on-error` | Abort the scan if any file collection or dependency restore failure occurs, instead of skipping the failed file and continuing. |
|
|
634
666
|
| `--gradle-all-sub-projects` | Run gradle restore command for all sub projects. This should be run from |
|
|
635
667
|
| `--maven-settings-file` | For Maven only, allows using a custom [settings.xml](https://maven.apache.org/settings.html) file when scanning for dependencies |
|
|
636
668
|
| `--help` | Show options for given command. |
|
|
@@ -737,6 +769,18 @@ If a lockfile already exists alongside the manifest, Cycode reads it directly wi
|
|
|
737
769
|
addSbtPlugin("software.purpledragon" % "sbt-dependency-lock" % "1.5.1")
|
|
738
770
|
```
|
|
739
771
|
|
|
772
|
+
#### Stop on Error Option
|
|
773
|
+
|
|
774
|
+
By default, Cycode continues scanning even if a file cannot be read (e.g. due to a permission error) or a dependency lockfile cannot be generated during an SCA scan. The failed item is skipped with a warning and the scan proceeds with the remaining files.
|
|
775
|
+
|
|
776
|
+
Use `--stop-on-error` to change this behaviour: the scan aborts immediately on the first such failure and reports the error.
|
|
777
|
+
|
|
778
|
+
```bash
|
|
779
|
+
cycode scan -t sca --stop-on-error path ~/home/git/codebase
|
|
780
|
+
```
|
|
781
|
+
|
|
782
|
+
This is useful in CI pipelines where a silent failure would produce an incomplete scan result. When `--stop-on-error` is triggered you can either fix the underlying issue or, for SCA restore failures specifically, add `--no-restore` to skip lockfile generation and scan direct dependencies only.
|
|
783
|
+
|
|
740
784
|
### Repository Scan
|
|
741
785
|
|
|
742
786
|
A repository scan examines an entire local repository for any exposed secrets or insecure misconfigurations. This more holistic scan type looks at everything: the current state of your repository and its commit history. It will look not only for secrets that are currently exposed within the repository but previously deleted secrets as well.
|
|
@@ -30,6 +30,7 @@ This guide walks you through both installation and usage.
|
|
|
30
30
|
4. [Package Vulnerabilities](#package-vulnerabilities-option)
|
|
31
31
|
5. [License Compliance](#license-compliance-option)
|
|
32
32
|
6. [Lock Restore](#lock-restore-option)
|
|
33
|
+
7. [Stop on Error](#stop-on-error-option)
|
|
33
34
|
2. [Repository Scan](#repository-scan)
|
|
34
35
|
1. [Branch Option](#branch-option)
|
|
35
36
|
3. [Path Scan](#path-scan)
|
|
@@ -384,12 +385,22 @@ The MCP server provides the following tools that AI systems can use:
|
|
|
384
385
|
|
|
385
386
|
| Tool Name | Description |
|
|
386
387
|
|----------------------|---------------------------------------------------------------------------------------------|
|
|
387
|
-
| `cycode_secret_scan` | Scan
|
|
388
|
-
| `cycode_sca_scan` | Scan
|
|
389
|
-
| `cycode_iac_scan` | Scan
|
|
390
|
-
| `cycode_sast_scan` | Scan
|
|
388
|
+
| `cycode_secret_scan` | Scan for hardcoded secrets |
|
|
389
|
+
| `cycode_sca_scan` | Scan for Software Composition Analysis (SCA) - vulnerabilities and license issues |
|
|
390
|
+
| `cycode_iac_scan` | Scan for Infrastructure as Code (IaC) misconfigurations |
|
|
391
|
+
| `cycode_sast_scan` | Scan for Static Application Security Testing (SAST) - code quality and security flaws |
|
|
391
392
|
| `cycode_status` | Get Cycode CLI version, authentication status, and configuration information |
|
|
392
393
|
|
|
394
|
+
Each scan tool accepts two mutually exclusive input modes:
|
|
395
|
+
|
|
396
|
+
- **`paths`** *(preferred)* — one or more file or directory paths that exist on disk. Directories are scanned recursively. The Cycode engine handles file discovery and filtering, just as `cycode scan -t <type> path ./src` does from the CLI.
|
|
397
|
+
- **`files`** *(fallback)* — a dictionary mapping file paths to their full content as strings. Use this only when the files are not available on disk (e.g. in-memory edits not yet saved).
|
|
398
|
+
|
|
399
|
+
> [!TIP]
|
|
400
|
+
> Use `paths` whenever possible. Passing large files (like `package-lock.json`) as inline content can exceed token limits and slow down the AI client. With `paths`, the Cycode engine reads files directly from disk.
|
|
401
|
+
|
|
402
|
+
All scan tools return a JSON object that includes a `"summary"` field with a human-readable violation count (e.g. `"Cycode found 3 violations: 1 CRITICAL, 2 HIGH."`) in addition to the full `"detections"` array.
|
|
403
|
+
|
|
393
404
|
### Usage Examples
|
|
394
405
|
|
|
395
406
|
#### Basic Command Examples
|
|
@@ -547,6 +558,26 @@ cycode mcp -t streamable-http -H 127.0.0.2 -p 9000 &
|
|
|
547
558
|
> [!NOTE]
|
|
548
559
|
> The MCP server requires proper Cycode CLI authentication to function. Make sure you have authenticated using `cycode auth` or configured your credentials before starting the MCP server.
|
|
549
560
|
|
|
561
|
+
### Pre-authorizing Tools for Subagents (Claude Code)
|
|
562
|
+
|
|
563
|
+
When Claude Code delegates work to background subagents (e.g. to run scans in parallel), those subagents cannot display interactive permission prompts. If the Cycode tools have not been pre-approved, scans will fail silently in subagent contexts.
|
|
564
|
+
|
|
565
|
+
To pre-authorize the Cycode MCP tools so they work in all contexts including subagents, add them to the `allowedTools` list in your Claude Code settings (`~/.claude/settings.json`):
|
|
566
|
+
|
|
567
|
+
```json
|
|
568
|
+
{
|
|
569
|
+
"allowedTools": [
|
|
570
|
+
"mcp__cycode__cycode_secret_scan",
|
|
571
|
+
"mcp__cycode__cycode_sca_scan",
|
|
572
|
+
"mcp__cycode__cycode_iac_scan",
|
|
573
|
+
"mcp__cycode__cycode_sast_scan",
|
|
574
|
+
"mcp__cycode__cycode_status"
|
|
575
|
+
]
|
|
576
|
+
}
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
Once added, Claude Code will not prompt for approval when these tools are called, and they will work correctly inside subagents.
|
|
580
|
+
|
|
550
581
|
### Troubleshooting MCP
|
|
551
582
|
|
|
552
583
|
If you encounter issues with the MCP server, you can enable debug logging to get more detailed information about what's happening. There are two ways to enable debug logging:
|
|
@@ -590,6 +621,7 @@ The Cycode CLI application offers several types of scans so that you can choose
|
|
|
590
621
|
| `--monitor` | When specified, the scan results will be recorded in Cycode. |
|
|
591
622
|
| `--cycode-report` | Display a link to the scan report in the Cycode platform in the console output. |
|
|
592
623
|
| `--no-restore` | When specified, Cycode will not run the restore command. This will scan direct dependencies ONLY! |
|
|
624
|
+
| `--stop-on-error` | Abort the scan if any file collection or dependency restore failure occurs, instead of skipping the failed file and continuing. |
|
|
593
625
|
| `--gradle-all-sub-projects` | Run gradle restore command for all sub projects. This should be run from |
|
|
594
626
|
| `--maven-settings-file` | For Maven only, allows using a custom [settings.xml](https://maven.apache.org/settings.html) file when scanning for dependencies |
|
|
595
627
|
| `--help` | Show options for given command. |
|
|
@@ -696,6 +728,18 @@ If a lockfile already exists alongside the manifest, Cycode reads it directly wi
|
|
|
696
728
|
addSbtPlugin("software.purpledragon" % "sbt-dependency-lock" % "1.5.1")
|
|
697
729
|
```
|
|
698
730
|
|
|
731
|
+
#### Stop on Error Option
|
|
732
|
+
|
|
733
|
+
By default, Cycode continues scanning even if a file cannot be read (e.g. due to a permission error) or a dependency lockfile cannot be generated during an SCA scan. The failed item is skipped with a warning and the scan proceeds with the remaining files.
|
|
734
|
+
|
|
735
|
+
Use `--stop-on-error` to change this behaviour: the scan aborts immediately on the first such failure and reports the error.
|
|
736
|
+
|
|
737
|
+
```bash
|
|
738
|
+
cycode scan -t sca --stop-on-error path ~/home/git/codebase
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
This is useful in CI pipelines where a silent failure would produce an incomplete scan result. When `--stop-on-error` is triggered you can either fix the underlying issue or, for SCA restore failures specifically, add `--no-restore` to skip lockfile generation and scan direct dependencies only.
|
|
742
|
+
|
|
699
743
|
### Repository Scan
|
|
700
744
|
|
|
701
745
|
A repository scan examines an entire local repository for any exposed secrets or insecure misconfigurations. This more holistic scan type looks at everything: the current state of your repository and its commit history. It will look not only for secrets that are currently exposed within the repository but previously deleted secrets as well.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '3.12.1' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
|
|
@@ -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, Optional
|
|
10
10
|
|
|
11
11
|
import typer
|
|
12
12
|
from pathvalidate import sanitize_filepath
|
|
@@ -28,7 +28,25 @@ _logger = get_logger('Cycode MCP')
|
|
|
28
28
|
|
|
29
29
|
_DEFAULT_RUN_COMMAND_TIMEOUT = 10 * 60
|
|
30
30
|
|
|
31
|
-
_FILES_TOOL_FIELD = Field(
|
|
31
|
+
_FILES_TOOL_FIELD = Field(
|
|
32
|
+
default=None,
|
|
33
|
+
description=(
|
|
34
|
+
'Files to scan, mapping file paths to their content. '
|
|
35
|
+
'Provide either this or "paths". '
|
|
36
|
+
'Note: for large codebases, prefer "paths" to avoid token overhead.'
|
|
37
|
+
),
|
|
38
|
+
)
|
|
39
|
+
_PATHS_TOOL_FIELD = Field(
|
|
40
|
+
default=None,
|
|
41
|
+
description=(
|
|
42
|
+
'Paths to scan — file paths or directory paths that exist on disk. '
|
|
43
|
+
'Directories are scanned recursively. '
|
|
44
|
+
'Provide either this or "files". '
|
|
45
|
+
'Preferred over "files" when the files already exist on disk.'
|
|
46
|
+
),
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
_SEVERITY_ORDER = ('CRITICAL', 'HIGH', 'MEDIUM', 'LOW')
|
|
32
50
|
|
|
33
51
|
|
|
34
52
|
def _is_debug_mode() -> bool:
|
|
@@ -163,9 +181,9 @@ class _TempFilesManager:
|
|
|
163
181
|
shutil.rmtree(self.temp_base_dir, ignore_errors=True)
|
|
164
182
|
|
|
165
183
|
|
|
166
|
-
async def _run_cycode_scan(scan_type: ScanTypeOption,
|
|
184
|
+
async def _run_cycode_scan(scan_type: ScanTypeOption, paths: list[str]) -> dict[str, Any]:
|
|
167
185
|
"""Run cycode scan command and return the result."""
|
|
168
|
-
return await _run_cycode_command(*['scan', '-t', str(scan_type), 'path', *
|
|
186
|
+
return await _run_cycode_command(*['scan', '-t', str(scan_type), 'path', *paths])
|
|
169
187
|
|
|
170
188
|
|
|
171
189
|
async def _run_cycode_status() -> dict[str, Any]:
|
|
@@ -173,38 +191,89 @@ async def _run_cycode_status() -> dict[str, Any]:
|
|
|
173
191
|
return await _run_cycode_command('status')
|
|
174
192
|
|
|
175
193
|
|
|
176
|
-
|
|
194
|
+
def _build_scan_summary(result: dict[str, Any]) -> str:
|
|
195
|
+
"""Build a human-readable summary line from a scan result dict.
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
result: Parsed JSON scan result from the CLI.
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
A one-line summary string describing what was found.
|
|
202
|
+
"""
|
|
203
|
+
detections = result.get('detections', [])
|
|
204
|
+
errors = result.get('errors', [])
|
|
205
|
+
|
|
206
|
+
if not detections:
|
|
207
|
+
if errors:
|
|
208
|
+
return f'Scan completed with {len(errors)} error(s) and no violations found.'
|
|
209
|
+
return 'No violations found.'
|
|
210
|
+
|
|
211
|
+
total = len(detections)
|
|
212
|
+
severity_counts: dict[str, int] = {}
|
|
213
|
+
for d in detections:
|
|
214
|
+
sev = (d.get('severity') or 'UNKNOWN').upper()
|
|
215
|
+
severity_counts[sev] = severity_counts.get(sev, 0) + 1
|
|
216
|
+
|
|
217
|
+
parts = [f'{severity_counts[s]} {s}' for s in _SEVERITY_ORDER if s in severity_counts]
|
|
218
|
+
other_keys = [k for k in severity_counts if k not in _SEVERITY_ORDER]
|
|
219
|
+
parts += [f'{severity_counts[k]} {k}' for k in other_keys]
|
|
220
|
+
|
|
221
|
+
label = 'violation' if total == 1 else 'violations'
|
|
222
|
+
return f'Cycode found {total} {label}: {", ".join(parts)}.'
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
async def _cycode_scan_tool(
|
|
226
|
+
scan_type: ScanTypeOption,
|
|
227
|
+
files: Optional[dict[str, str]] = None,
|
|
228
|
+
paths: Optional[list[str]] = None,
|
|
229
|
+
) -> str:
|
|
177
230
|
_tool_call_id = _gen_random_id()
|
|
178
231
|
_logger.info('Scan tool called, %s', {'scan_type': scan_type, 'call_id': _tool_call_id})
|
|
179
232
|
|
|
180
|
-
if not files:
|
|
181
|
-
_logger.error('No files provided for scan')
|
|
182
|
-
return json.dumps(
|
|
233
|
+
if not files and not paths:
|
|
234
|
+
_logger.error('No files or paths provided for scan')
|
|
235
|
+
return json.dumps(
|
|
236
|
+
{'error': 'No files or paths provided. Pass file contents via "files" or disk paths via "paths".'}
|
|
237
|
+
)
|
|
183
238
|
|
|
184
239
|
try:
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
if processed_count < original_count:
|
|
190
|
-
_logger.warning(
|
|
191
|
-
'Some files were rejected during sanitization, %s',
|
|
192
|
-
{
|
|
193
|
-
'scan_type': scan_type,
|
|
194
|
-
'original_count': original_count,
|
|
195
|
-
'processed_count': processed_count,
|
|
196
|
-
'call_id': _tool_call_id,
|
|
197
|
-
},
|
|
198
|
-
)
|
|
240
|
+
if paths:
|
|
241
|
+
missing = [p for p in paths if not os.path.exists(p)]
|
|
242
|
+
if missing:
|
|
243
|
+
return json.dumps({'error': f'Paths not found on disk: {missing}'}, indent=2)
|
|
199
244
|
|
|
200
245
|
_logger.info(
|
|
201
|
-
'Running Cycode scan, %s',
|
|
202
|
-
{'scan_type': scan_type, '
|
|
246
|
+
'Running Cycode scan (path-based), %s',
|
|
247
|
+
{'scan_type': scan_type, 'paths': paths, 'call_id': _tool_call_id},
|
|
203
248
|
)
|
|
204
|
-
result = await _run_cycode_scan(scan_type,
|
|
249
|
+
result = await _run_cycode_scan(scan_type, paths)
|
|
250
|
+
else:
|
|
251
|
+
with _TempFilesManager(files, _tool_call_id) as temp_files:
|
|
252
|
+
original_count = len(files)
|
|
253
|
+
processed_count = len(temp_files)
|
|
254
|
+
|
|
255
|
+
if processed_count < original_count:
|
|
256
|
+
_logger.warning(
|
|
257
|
+
'Some files were rejected during sanitization, %s',
|
|
258
|
+
{
|
|
259
|
+
'scan_type': scan_type,
|
|
260
|
+
'original_count': original_count,
|
|
261
|
+
'processed_count': processed_count,
|
|
262
|
+
'call_id': _tool_call_id,
|
|
263
|
+
},
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
_logger.info(
|
|
267
|
+
'Running Cycode scan (files-based), %s',
|
|
268
|
+
{'scan_type': scan_type, 'files_count': processed_count, 'call_id': _tool_call_id},
|
|
269
|
+
)
|
|
270
|
+
result = await _run_cycode_scan(scan_type, temp_files)
|
|
205
271
|
|
|
206
|
-
|
|
207
|
-
|
|
272
|
+
if 'error' not in result:
|
|
273
|
+
result['summary'] = _build_scan_summary(result)
|
|
274
|
+
|
|
275
|
+
_logger.info('Scan completed, %s', {'scan_type': scan_type, 'call_id': _tool_call_id})
|
|
276
|
+
return json.dumps(result, indent=2)
|
|
208
277
|
except ValueError as e:
|
|
209
278
|
_logger.error('Invalid input files, %s', {'scan_type': scan_type, 'call_id': _tool_call_id, 'error': str(e)})
|
|
210
279
|
return json.dumps({'error': f'Invalid input files: {e!s}'}, indent=2)
|
|
@@ -213,8 +282,11 @@ async def _cycode_scan_tool(scan_type: ScanTypeOption, files: dict[str, str] = _
|
|
|
213
282
|
return json.dumps({'error': f'Scan failed: {e!s}'}, indent=2)
|
|
214
283
|
|
|
215
284
|
|
|
216
|
-
async def cycode_secret_scan(
|
|
217
|
-
|
|
285
|
+
async def cycode_secret_scan(
|
|
286
|
+
paths: Optional[list[str]] = _PATHS_TOOL_FIELD,
|
|
287
|
+
files: Optional[dict[str, str]] = _FILES_TOOL_FIELD,
|
|
288
|
+
) -> str:
|
|
289
|
+
"""Scan for hardcoded secrets.
|
|
218
290
|
|
|
219
291
|
Use this tool when you need to:
|
|
220
292
|
- scan code for hardcoded secrets, API keys, passwords, tokens
|
|
@@ -222,16 +294,20 @@ async def cycode_secret_scan(files: dict[str, str] = _FILES_TOOL_FIELD) -> str:
|
|
|
222
294
|
- detect potential security vulnerabilities from secret exposure
|
|
223
295
|
|
|
224
296
|
Args:
|
|
225
|
-
|
|
297
|
+
paths: File or directory paths on disk to scan (preferred). Directories are scanned recursively.
|
|
298
|
+
files: Dictionary mapping file paths to their content (fallback when files are not on disk).
|
|
226
299
|
|
|
227
300
|
Returns:
|
|
228
|
-
JSON string
|
|
301
|
+
JSON string with a "summary" field (human-readable violation count) plus full scan results.
|
|
229
302
|
"""
|
|
230
|
-
return await _cycode_scan_tool(ScanTypeOption.SECRET, files)
|
|
303
|
+
return await _cycode_scan_tool(ScanTypeOption.SECRET, files=files, paths=paths)
|
|
231
304
|
|
|
232
305
|
|
|
233
|
-
async def cycode_sca_scan(
|
|
234
|
-
|
|
306
|
+
async def cycode_sca_scan(
|
|
307
|
+
paths: Optional[list[str]] = _PATHS_TOOL_FIELD,
|
|
308
|
+
files: Optional[dict[str, str]] = _FILES_TOOL_FIELD,
|
|
309
|
+
) -> str:
|
|
310
|
+
"""Scan for Software Composition Analysis (SCA) - vulnerabilities and license issues.
|
|
235
311
|
|
|
236
312
|
Use this tool when you need to:
|
|
237
313
|
- scan dependencies for known security vulnerabilities
|
|
@@ -242,19 +318,24 @@ async def cycode_sca_scan(files: dict[str, str] = _FILES_TOOL_FIELD) -> str:
|
|
|
242
318
|
|
|
243
319
|
Important:
|
|
244
320
|
You must also include lock files (like package-lock.json, Pipfile.lock, etc.) to get accurate results.
|
|
245
|
-
|
|
321
|
+
When using "paths", pass the directory containing both manifest and lock files.
|
|
322
|
+
When using "files", provide both manifest and lock files together.
|
|
246
323
|
|
|
247
324
|
Args:
|
|
248
|
-
|
|
325
|
+
paths: File or directory paths on disk to scan (preferred). Directories are scanned recursively.
|
|
326
|
+
files: Dictionary mapping file paths to their content (fallback when files are not on disk).
|
|
249
327
|
|
|
250
328
|
Returns:
|
|
251
|
-
JSON string
|
|
329
|
+
JSON string with a "summary" field (human-readable violation count) plus full scan results.
|
|
252
330
|
"""
|
|
253
|
-
return await _cycode_scan_tool(ScanTypeOption.SCA, files)
|
|
331
|
+
return await _cycode_scan_tool(ScanTypeOption.SCA, files=files, paths=paths)
|
|
254
332
|
|
|
255
333
|
|
|
256
|
-
async def cycode_iac_scan(
|
|
257
|
-
|
|
334
|
+
async def cycode_iac_scan(
|
|
335
|
+
paths: Optional[list[str]] = _PATHS_TOOL_FIELD,
|
|
336
|
+
files: Optional[dict[str, str]] = _FILES_TOOL_FIELD,
|
|
337
|
+
) -> str:
|
|
338
|
+
"""Scan for Infrastructure as Code (IaC) misconfigurations.
|
|
258
339
|
|
|
259
340
|
Use this tool when you need to:
|
|
260
341
|
- scan Terraform, CloudFormation, Kubernetes YAML files
|
|
@@ -264,16 +345,20 @@ async def cycode_iac_scan(files: dict[str, str] = _FILES_TOOL_FIELD) -> str:
|
|
|
264
345
|
- review Docker files for security issues
|
|
265
346
|
|
|
266
347
|
Args:
|
|
267
|
-
|
|
348
|
+
paths: File or directory paths on disk to scan (preferred). Directories are scanned recursively.
|
|
349
|
+
files: Dictionary mapping file paths to their content (fallback when files are not on disk).
|
|
268
350
|
|
|
269
351
|
Returns:
|
|
270
|
-
JSON string
|
|
352
|
+
JSON string with a "summary" field (human-readable violation count) plus full scan results.
|
|
271
353
|
"""
|
|
272
|
-
return await _cycode_scan_tool(ScanTypeOption.IAC, files)
|
|
354
|
+
return await _cycode_scan_tool(ScanTypeOption.IAC, files=files, paths=paths)
|
|
273
355
|
|
|
274
356
|
|
|
275
|
-
async def cycode_sast_scan(
|
|
276
|
-
|
|
357
|
+
async def cycode_sast_scan(
|
|
358
|
+
paths: Optional[list[str]] = _PATHS_TOOL_FIELD,
|
|
359
|
+
files: Optional[dict[str, str]] = _FILES_TOOL_FIELD,
|
|
360
|
+
) -> str:
|
|
361
|
+
"""Scan for Static Application Security Testing (SAST) - code quality and security flaws.
|
|
277
362
|
|
|
278
363
|
Use this tool when you need to:
|
|
279
364
|
- scan source code for security vulnerabilities
|
|
@@ -283,12 +368,13 @@ async def cycode_sast_scan(files: dict[str, str] = _FILES_TOOL_FIELD) -> str:
|
|
|
283
368
|
- find SQL injection, XSS, and other application security issues
|
|
284
369
|
|
|
285
370
|
Args:
|
|
286
|
-
|
|
371
|
+
paths: File or directory paths on disk to scan (preferred). Directories are scanned recursively.
|
|
372
|
+
files: Dictionary mapping file paths to their content (fallback when files are not on disk).
|
|
287
373
|
|
|
288
374
|
Returns:
|
|
289
|
-
JSON string
|
|
375
|
+
JSON string with a "summary" field (human-readable violation count) plus full scan results.
|
|
290
376
|
"""
|
|
291
|
-
return await _cycode_scan_tool(ScanTypeOption.SAST, files)
|
|
377
|
+
return await _cycode_scan_tool(ScanTypeOption.SAST, files=files, paths=paths)
|
|
292
378
|
|
|
293
379
|
|
|
294
380
|
async def cycode_status() -> str:
|
|
@@ -10,6 +10,7 @@ from cycode.cli.apps.sca_options import (
|
|
|
10
10
|
GradleAllSubProjectsOption,
|
|
11
11
|
MavenSettingsFileOption,
|
|
12
12
|
NoRestoreOption,
|
|
13
|
+
StopOnErrorOption,
|
|
13
14
|
apply_sca_restore_options_to_context,
|
|
14
15
|
)
|
|
15
16
|
from cycode.cli.exceptions.handle_report_sbom_errors import handle_report_exception
|
|
@@ -30,8 +31,9 @@ def path_command(
|
|
|
30
31
|
no_restore: NoRestoreOption = False,
|
|
31
32
|
gradle_all_sub_projects: GradleAllSubProjectsOption = False,
|
|
32
33
|
maven_settings_file: MavenSettingsFileOption = None,
|
|
34
|
+
stop_on_error: StopOnErrorOption = False,
|
|
33
35
|
) -> None:
|
|
34
|
-
apply_sca_restore_options_to_context(ctx, no_restore, gradle_all_sub_projects, maven_settings_file)
|
|
36
|
+
apply_sca_restore_options_to_context(ctx, no_restore, gradle_all_sub_projects, maven_settings_file, stop_on_error)
|
|
35
37
|
|
|
36
38
|
client = get_report_cycode_client(ctx)
|
|
37
39
|
report_parameters = ctx.obj['report_parameters']
|
|
@@ -51,6 +53,7 @@ def path_command(
|
|
|
51
53
|
consts.SCA_SCAN_TYPE,
|
|
52
54
|
(str(path),),
|
|
53
55
|
is_cycodeignore_allowed=is_cycodeignore_allowed_by_scan_config(ctx),
|
|
56
|
+
stop_on_error=stop_on_error,
|
|
54
57
|
)
|
|
55
58
|
# TODO(MarshalX): combine perform_pre_scan_documents_actions with get_relevant_document.
|
|
56
59
|
# unhardcode usage of context in perform_pre_scan_documents_actions
|
|
@@ -35,13 +35,24 @@ MavenSettingsFileOption = Annotated[
|
|
|
35
35
|
),
|
|
36
36
|
]
|
|
37
37
|
|
|
38
|
+
StopOnErrorOption = Annotated[
|
|
39
|
+
bool,
|
|
40
|
+
typer.Option(
|
|
41
|
+
'--stop-on-error',
|
|
42
|
+
help='When specified, stops the process if any file collection or restore failure occurs.',
|
|
43
|
+
rich_help_panel=_SCA_RICH_HELP_PANEL,
|
|
44
|
+
),
|
|
45
|
+
]
|
|
46
|
+
|
|
38
47
|
|
|
39
48
|
def apply_sca_restore_options_to_context(
|
|
40
49
|
ctx: typer.Context,
|
|
41
50
|
no_restore: bool,
|
|
42
51
|
gradle_all_sub_projects: bool,
|
|
43
52
|
maven_settings_file: Optional[Path],
|
|
53
|
+
stop_on_error: bool = False,
|
|
44
54
|
) -> None:
|
|
45
55
|
ctx.obj['no_restore'] = no_restore
|
|
46
56
|
ctx.obj['gradle_all_sub_projects'] = gradle_all_sub_projects
|
|
47
57
|
ctx.obj['maven_settings_file'] = maven_settings_file
|
|
58
|
+
ctx.obj['stop_on_error'] = stop_on_error
|
|
@@ -58,6 +58,7 @@ def scan_disk_files(ctx: typer.Context, paths: tuple[str, ...]) -> None:
|
|
|
58
58
|
scan_type,
|
|
59
59
|
paths,
|
|
60
60
|
is_cycodeignore_allowed=is_cycodeignore_allowed_by_scan_config(ctx),
|
|
61
|
+
stop_on_error=ctx.obj.get('stop_on_error', False),
|
|
61
62
|
)
|
|
62
63
|
|
|
63
64
|
# Add entrypoint.cycode file at root path to mark the scan root (only for single path that is a directory)
|
|
@@ -41,6 +41,13 @@ def scan_command(
|
|
|
41
41
|
soft_fail: Annotated[
|
|
42
42
|
bool, typer.Option('--soft-fail', help='Run the scan without failing; always return a non-error status code.')
|
|
43
43
|
] = False,
|
|
44
|
+
stop_on_error: Annotated[
|
|
45
|
+
bool,
|
|
46
|
+
typer.Option(
|
|
47
|
+
'--stop-on-error',
|
|
48
|
+
help='When specified, stops the scan if any file collection or restore failure occurs.',
|
|
49
|
+
),
|
|
50
|
+
] = False,
|
|
44
51
|
severity_threshold: Annotated[
|
|
45
52
|
SeverityOption,
|
|
46
53
|
typer.Option(
|
|
@@ -131,6 +138,7 @@ def scan_command(
|
|
|
131
138
|
|
|
132
139
|
ctx.obj['show_secret'] = show_secret
|
|
133
140
|
ctx.obj['soft_fail'] = soft_fail
|
|
141
|
+
ctx.obj['stop_on_error'] = stop_on_error
|
|
134
142
|
ctx.obj['scan_type'] = scan_type
|
|
135
143
|
ctx.obj['sync'] = sync
|
|
136
144
|
ctx.obj['severity_threshold'] = severity_threshold
|
|
@@ -64,6 +64,15 @@ class ZipTooLargeError(CycodeError):
|
|
|
64
64
|
return f'The size of zip to scan is too large, size limit: {self.size_limit}'
|
|
65
65
|
|
|
66
66
|
|
|
67
|
+
class FileCollectionError(CycodeError):
|
|
68
|
+
def __init__(self, error_message: str) -> None:
|
|
69
|
+
self.error_message = error_message
|
|
70
|
+
super().__init__(self.error_message)
|
|
71
|
+
|
|
72
|
+
def __str__(self) -> str:
|
|
73
|
+
return self.error_message
|
|
74
|
+
|
|
75
|
+
|
|
67
76
|
class AuthProcessError(CycodeError):
|
|
68
77
|
def __init__(self, error_message: str) -> None:
|
|
69
78
|
self.error_message = error_message
|
|
@@ -26,6 +26,12 @@ def handle_scan_exception(ctx: typer.Context, err: Exception, *, return_exceptio
|
|
|
26
26
|
'Please try ignoring irrelevant paths using the `cycode ignore --by-path` command '
|
|
27
27
|
'and execute the scan again',
|
|
28
28
|
),
|
|
29
|
+
custom_exceptions.FileCollectionError: CliError(
|
|
30
|
+
soft_fail=False,
|
|
31
|
+
code='file_collection_error',
|
|
32
|
+
message='File collection failed. '
|
|
33
|
+
'Use --no-restore to skip dependency restoration, or fix the underlying issue.',
|
|
34
|
+
),
|
|
29
35
|
custom_exceptions.TfplanKeyError: CliError(
|
|
30
36
|
soft_fail=True,
|
|
31
37
|
code='key_error',
|
|
@@ -2,6 +2,7 @@ import os
|
|
|
2
2
|
from collections.abc import Generator
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
|
+
from cycode.cli.exceptions.custom_exceptions import FileCollectionError
|
|
5
6
|
from cycode.cli.files_collector.file_excluder import excluder
|
|
6
7
|
from cycode.cli.files_collector.iac.tf_content_generator import (
|
|
7
8
|
generate_tf_content_from_tfplan,
|
|
@@ -109,6 +110,7 @@ def get_relevant_documents(
|
|
|
109
110
|
*,
|
|
110
111
|
is_git_diff: bool = False,
|
|
111
112
|
is_cycodeignore_allowed: bool = True,
|
|
113
|
+
stop_on_error: bool = False,
|
|
112
114
|
) -> list[Document]:
|
|
113
115
|
relevant_files = _get_relevant_files(
|
|
114
116
|
progress_bar, progress_bar_section, scan_type, paths, is_cycodeignore_allowed=is_cycodeignore_allowed
|
|
@@ -119,6 +121,10 @@ def get_relevant_documents(
|
|
|
119
121
|
progress_bar.update(progress_bar_section)
|
|
120
122
|
|
|
121
123
|
content = get_file_content(file)
|
|
124
|
+
if content is None:
|
|
125
|
+
if stop_on_error:
|
|
126
|
+
raise FileCollectionError(f'Failed to read file: {file}')
|
|
127
|
+
continue
|
|
122
128
|
if not content:
|
|
123
129
|
continue
|
|
124
130
|
|
|
@@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional
|
|
|
4
4
|
import typer
|
|
5
5
|
|
|
6
6
|
from cycode.cli import consts
|
|
7
|
+
from cycode.cli.exceptions.custom_exceptions import FileCollectionError
|
|
7
8
|
from cycode.cli.files_collector.repository_documents import get_file_content_from_commit_path
|
|
8
9
|
from cycode.cli.files_collector.sca.base_restore_dependencies import BaseRestoreDependencies
|
|
9
10
|
from cycode.cli.files_collector.sca.go.restore_go_dependencies import RestoreGoDependencies
|
|
@@ -116,6 +117,10 @@ def _try_restore_dependencies(
|
|
|
116
117
|
'Error occurred while trying to generate dependencies tree, %s',
|
|
117
118
|
{'filename': document.path, 'handler': type(restore_dependencies).__name__},
|
|
118
119
|
)
|
|
120
|
+
if ctx.obj.get('stop_on_error', False):
|
|
121
|
+
raise FileCollectionError(
|
|
122
|
+
f'Failed to generate dependencies tree for {document.path} using {type(restore_dependencies).__name__}'
|
|
123
|
+
)
|
|
119
124
|
return None
|
|
120
125
|
|
|
121
126
|
if restore_dependencies_document.content is None:
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '3.11.6.dev1' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|