cycode 3.25.2.dev4__tar.gz → 3.26.1.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.25.2.dev4 → cycode-3.26.1.dev1}/PKG-INFO +1 -1
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/__init__.py +1 -1
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/ides/base.py +10 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/ides/claude_code.py +8 -3
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/ides/codex.py +1 -1
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/ides/copilot.py +2 -1
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/ides/cursor.py +5 -2
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/scan/handlers.py +62 -10
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/scan/utils.py +35 -17
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/pyproject.toml +1 -1
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/LICENCE +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/README.md +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/__main__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/app.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/activation_manager.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/command_utils.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/consts.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/hooks_manager.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/ides/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/ides/_plugin_utils.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/ides/_skill_utils.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/install_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/scan/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/scan/consts.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/scan/detach.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/scan/guardrail_config.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/scan/mcp_server_status.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/scan/payload.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/scan/policy.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/scan/scan_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/scan/types.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/session_start_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/status_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/uninstall_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_remediation/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_remediation/ai_remediation_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_remediation/apply_fix.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_remediation/print_remediation.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/api/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/api/api_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/api/openapi_spec.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/auth/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/auth/auth_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/auth/auth_common.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/auth/auth_manager.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/auth/models.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/configure/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/configure/configure_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/configure/consts.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/configure/messages.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/configure/prompts.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ignore/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ignore/ignore_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/mcp/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/mcp/mcp_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/report/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/report/report_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/report/sbom/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/report/sbom/common.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/report/sbom/path/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/report/sbom/path/path_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/report/sbom/repository_url/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/report/sbom/repository_url/repository_url_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/report/sbom/sbom_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/report/sbom/sbom_report_file.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/report_import/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/report_import/report_import_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/report_import/sbom/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/report_import/sbom/sbom_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/sca_options.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/aggregation_report.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/code_scanner.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/commit_history/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/commit_history/commit_history_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/commit_range_scanner.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/detection_excluder.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/path/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/path/path_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/pre_commit/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/pre_commit/pre_commit_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/pre_push/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/pre_push/pre_push_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/pre_receive/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/pre_receive/pre_receive_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/remote_url_resolver.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/repository/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/repository/repository_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/scan_ci/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/scan_ci/ci_integrations.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/scan_ci/scan_ci_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/scan_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/scan_parameters.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/scan_result.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/status/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/status/get_cli_status.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/status/models.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/status/status_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/status/version_command.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/cli_types.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/config.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/console.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/consts.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/exceptions/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/exceptions/custom_exceptions.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/exceptions/handle_ai_remediation_errors.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/exceptions/handle_auth_errors.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/exceptions/handle_errors.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/exceptions/handle_report_sbom_errors.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/exceptions/handle_scan_errors.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/commit_range_documents.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/documents_walk_ignore.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/file_excluder.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/iac/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/iac/tf_content_generator.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/models/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/models/in_memory_zip.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/path_documents.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/repository_documents.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/base_restore_dependencies.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/go/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/go/restore_go_dependencies.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/maven/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/maven/restore_gradle_dependencies.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/maven/restore_maven_dependencies.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/npm/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/npm/restore_bun_dependencies.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/npm/restore_deno_dependencies.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/npm/restore_npm_dependencies.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/npm/restore_pnpm_dependencies.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/npm/restore_yarn_dependencies.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/npm/workspace/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/npm/workspace/coverage.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/npm/workspace/files.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/npm/workspace/globs.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/npm/workspace/names.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/npm/workspace/resolvers.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/nuget/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/nuget/restore_nuget_dependencies.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/php/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/php/restore_composer_dependencies.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/python/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/python/restore_pip_dependencies.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/python/restore_pipenv_dependencies.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/python/restore_poetry_dependencies.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/python/restore_uv_dependencies.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/ruby/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/ruby/restore_ruby_dependencies.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/sbt/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/sbt/restore_sbt_dependencies.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/sca/sca_file_collector.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/walk_ignore.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/zip_documents.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/logger.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/main.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/models.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/printers/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/printers/console_printer.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/printers/json_printer.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/printers/printer_base.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/printers/rich_printer.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/printers/tables/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/printers/tables/sca_table_printer.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/printers/tables/table.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/printers/tables/table_models.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/printers/tables/table_printer.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/printers/tables/table_printer_base.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/printers/text_printer.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/printers/utils/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/printers/utils/code_snippet_syntax.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/printers/utils/detection_data.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/printers/utils/detection_ordering/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/printers/utils/detection_ordering/common_ordering.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/printers/utils/detection_ordering/sca_ordering.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/printers/utils/rich_helpers.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/printers/utils/sca_ossf.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/printers/utils/sca_policy_details.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/user_settings/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/user_settings/base_file_manager.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/user_settings/config_file_manager.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/user_settings/configuration_manager.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/user_settings/credentials_manager.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/user_settings/jwt_creator.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/utils/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/utils/binary_utils.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/utils/enum_utils.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/utils/get_api_client.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/utils/git_proxy.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/utils/host_info.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/utils/ignore_utils.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/utils/jwt_utils.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/utils/path_utils.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/utils/progress_bar.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/utils/scan_batch.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/utils/scan_utils.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/utils/shell_executor.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/utils/string_utils.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/utils/task_timer.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/utils/trust_store.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/utils/url_utils.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/utils/version_checker.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/utils/yaml_utils.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/config.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cyclient/__init__.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cyclient/ai_security_manager_client.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cyclient/ai_security_manager_service_config.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cyclient/auth_client.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cyclient/base_token_auth_client.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cyclient/cli_activation_client.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cyclient/client_creator.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cyclient/config.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cyclient/config_dev.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cyclient/cycode_client.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cyclient/cycode_client_base.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cyclient/cycode_dev_based_client.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cyclient/cycode_oidc_based_client.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cyclient/cycode_token_based_client.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cyclient/headers.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cyclient/import_sbom_client.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cyclient/logger.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cyclient/models.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cyclient/report_client.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cyclient/scan_client.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cyclient/scan_config_base.py +0 -0
- {cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/logger.py +0 -0
|
@@ -5,4 +5,4 @@ import time as _time
|
|
|
5
5
|
# end-to-end scan duration from the moment the user actually triggered it.
|
|
6
6
|
_BOOT_WALL: float = _time.time()
|
|
7
7
|
|
|
8
|
-
__version__ = '3.
|
|
8
|
+
__version__ = '3.26.1.dev1' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
|
|
@@ -47,6 +47,16 @@ class HookDecision:
|
|
|
47
47
|
user_message: str | None = None
|
|
48
48
|
agent_message: str | None = None
|
|
49
49
|
|
|
50
|
+
@property
|
|
51
|
+
def model_message(self) -> str:
|
|
52
|
+
"""What a tool deny tells the model: the findings the user sees, then the agent's instructions."""
|
|
53
|
+
return '\n'.join(message for message in (self.user_message, self.agent_message) if message)
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def permission_reason(self) -> str:
|
|
57
|
+
"""A PreToolUse permissionDecisionReason: a deny reason goes to the model, an ask reason to the user."""
|
|
58
|
+
return self.model_message if self.action == DecisionAction.DENY else self.user_message or ''
|
|
59
|
+
|
|
50
60
|
@classmethod
|
|
51
61
|
def allow(cls, event_type: AiHookEventType) -> 'HookDecision':
|
|
52
62
|
return cls(action=DecisionAction.ALLOW, event_type=event_type)
|
|
@@ -397,8 +397,13 @@ class ClaudeCode(IDE):
|
|
|
397
397
|
if decision.event_type == AiHookEventType.PROMPT:
|
|
398
398
|
if decision.action == DecisionAction.ALLOW:
|
|
399
399
|
return {}
|
|
400
|
-
# Both DENY and (unexpected) ASK on prompts collapse to a block.
|
|
401
|
-
|
|
400
|
+
# Both DENY and (unexpected) ASK on prompts collapse to a block. Claude Code echoes the blocked
|
|
401
|
+
# prompt (secret included) under the reason unless suppressed; the reason already locates the finding.
|
|
402
|
+
return {
|
|
403
|
+
'decision': 'block',
|
|
404
|
+
'reason': decision.user_message or '',
|
|
405
|
+
'hookSpecificOutput': {'hookEventName': 'UserPromptSubmit', 'suppressOriginalPrompt': True},
|
|
406
|
+
}
|
|
402
407
|
|
|
403
408
|
# FILE_READ / MCP_EXECUTION → hookSpecificOutput shape.
|
|
404
409
|
if decision.action == DecisionAction.ALLOW:
|
|
@@ -412,7 +417,7 @@ class ClaudeCode(IDE):
|
|
|
412
417
|
'hookSpecificOutput': {
|
|
413
418
|
'hookEventName': 'PreToolUse',
|
|
414
419
|
'permissionDecision': decision.action.value, # 'deny' or 'ask'
|
|
415
|
-
'permissionDecisionReason': decision.
|
|
420
|
+
'permissionDecisionReason': decision.permission_reason,
|
|
416
421
|
}
|
|
417
422
|
}
|
|
418
423
|
|
|
@@ -319,7 +319,7 @@ class Codex(IDE):
|
|
|
319
319
|
'hookSpecificOutput': {
|
|
320
320
|
'hookEventName': 'PreToolUse',
|
|
321
321
|
'permissionDecision': decision.action.value, # 'deny' or 'ask'
|
|
322
|
-
'permissionDecisionReason': decision.
|
|
322
|
+
'permissionDecisionReason': decision.permission_reason,
|
|
323
323
|
}
|
|
324
324
|
}
|
|
325
325
|
|
|
@@ -474,7 +474,8 @@ class Copilot(IDE):
|
|
|
474
474
|
'hookSpecificOutput': {
|
|
475
475
|
'hookEventName': 'PreToolUse',
|
|
476
476
|
'permissionDecision': decision.action.value, # 'deny' or 'ask'
|
|
477
|
-
|
|
477
|
+
# Copilot VS Code shows a deny reason to the user rather than the model, which is harmless
|
|
478
|
+
'permissionDecisionReason': decision.permission_reason,
|
|
478
479
|
}
|
|
479
480
|
}
|
|
480
481
|
|
|
@@ -149,10 +149,13 @@ class Cursor(IDE):
|
|
|
149
149
|
# FILE_READ / MCP_EXECUTION → permission shape
|
|
150
150
|
if decision.action == DecisionAction.ALLOW:
|
|
151
151
|
return {'permission': 'allow'}
|
|
152
|
+
# beforeReadFile has no agent_message; its deny user_message is what reaches the model
|
|
153
|
+
file_read_deny = decision.event_type == AiHookEventType.FILE_READ and decision.action == DecisionAction.DENY
|
|
152
154
|
return {
|
|
153
155
|
'permission': decision.action.value, # 'deny' or 'ask'
|
|
154
|
-
'user_message': decision.user_message or '',
|
|
155
|
-
|
|
156
|
+
'user_message': decision.model_message if file_read_deny else decision.user_message or '',
|
|
157
|
+
# The agent does not see user_message, and needs the findings (their sha) to act on its instructions
|
|
158
|
+
'agent_message': decision.model_message,
|
|
156
159
|
}
|
|
157
160
|
|
|
158
161
|
def build_session_payload(self, raw_payload: dict) -> AIHookPayload:
|
|
@@ -10,9 +10,11 @@ touching any handler in this module.
|
|
|
10
10
|
|
|
11
11
|
import json
|
|
12
12
|
import os
|
|
13
|
+
import sys
|
|
13
14
|
import threading
|
|
14
15
|
from collections.abc import Callable
|
|
15
16
|
from dataclasses import dataclass
|
|
17
|
+
from gettext import ngettext
|
|
16
18
|
from typing import TYPE_CHECKING, Any, NamedTuple
|
|
17
19
|
|
|
18
20
|
import typer
|
|
@@ -46,12 +48,53 @@ logger = get_logger('AI Guardrails')
|
|
|
46
48
|
HandlerFn = Callable[[typer.Context, AIHookPayload, dict], HookDecision]
|
|
47
49
|
|
|
48
50
|
|
|
51
|
+
def _ignore_commands(shas: tuple[str, ...]) -> list[str]:
|
|
52
|
+
"""Ready-to-run ignore commands, one per finding, in the order the findings are listed.
|
|
53
|
+
|
|
54
|
+
Names the binary running this hook, which may not be on PATH (e.g. MDM installs). Repo scope: it lands in
|
|
55
|
+
the cwd's .cycode/config.yaml, which matches where the hook reads it as long as the agent runs it.
|
|
56
|
+
"""
|
|
57
|
+
executable = sys.executable if getattr(sys, 'frozen', False) else sys.argv[0]
|
|
58
|
+
if ' ' in executable:
|
|
59
|
+
executable = f'"{executable}"'
|
|
60
|
+
return [f'`{executable} ignore --by-sha {sha}`' for sha in shas]
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _with_ignore_commands(shas: tuple[str, ...], one: str, many: str) -> str:
|
|
64
|
+
"""`one` formatted with the single command, or `many` followed by the commands as a list; '' without shas."""
|
|
65
|
+
commands = _ignore_commands(shas)
|
|
66
|
+
if len(commands) == 1:
|
|
67
|
+
return one.format(command=commands[0])
|
|
68
|
+
if commands:
|
|
69
|
+
return many + ''.join(f'\n {command}' for command in commands)
|
|
70
|
+
return ''
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _false_positive_user_hint(shas: tuple[str, ...]) -> str:
|
|
74
|
+
# The agent never saw the blocked prompt, so the command has to be complete for the developer to pass on
|
|
75
|
+
return _with_ignore_commands(
|
|
76
|
+
shas,
|
|
77
|
+
one='Not a real secret? Ask your code agent to run {command}, then resend.',
|
|
78
|
+
many='Not real secrets? Ask your code agent to run the command for each one, then resend:',
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _false_positive_agent_hint(shas: tuple[str, ...]) -> str:
|
|
83
|
+
# Ignoring is the developer's call; the agent may run it for them, but only once they confirm
|
|
84
|
+
return 'Tell the user what was blocked.' + _with_ignore_commands(
|
|
85
|
+
shas,
|
|
86
|
+
one=' Only if the user confirms it is a false positive, run {command} and retry.',
|
|
87
|
+
many=' Only for a finding the user confirms is a false positive, run its command and retry:',
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
|
|
49
91
|
class ScanOutcome(NamedTuple):
|
|
50
92
|
"""What one guardrail scan came back with; the verdict is the server's, which applied the tenant's floors."""
|
|
51
93
|
|
|
52
94
|
violation_summary: str | None = None
|
|
53
95
|
scan_id: str | None = None
|
|
54
96
|
verdict: GuardrailsMode | None = None
|
|
97
|
+
shas: tuple[str, ...] = ()
|
|
55
98
|
|
|
56
99
|
|
|
57
100
|
NO_SCAN = ScanOutcome()
|
|
@@ -96,7 +139,10 @@ def handle_before_submit_prompt(ctx: typer.Context, payload: AIHookPayload, poli
|
|
|
96
139
|
block_reason = SECRETS_BLOCK_REASON_BY_EVENT_TYPE[AiHookEventType.PROMPT]
|
|
97
140
|
if scan_outcome.verdict == GuardrailsMode.BLOCK:
|
|
98
141
|
outcome = AIHookOutcome.BLOCKED
|
|
99
|
-
|
|
142
|
+
secrets = ngettext('secret', 'secrets', len(scan_outcome.shas))
|
|
143
|
+
user_message = f'{scan_outcome.violation_summary}\nRemove the {secrets} and resend.'
|
|
144
|
+
if scan_outcome.shas:
|
|
145
|
+
user_message += f'\n{_false_positive_user_hint(scan_outcome.shas)}'
|
|
100
146
|
return HookDecision.deny(AiHookEventType.PROMPT, user_message)
|
|
101
147
|
outcome = AIHookOutcome.WARNED
|
|
102
148
|
return HookDecision.allow(AiHookEventType.PROMPT)
|
|
@@ -164,14 +210,15 @@ def handle_before_read_file(ctx: typer.Context, payload: AIHookPayload, policy:
|
|
|
164
210
|
block_reason = SECRETS_BLOCK_REASON_BY_EVENT_TYPE[AiHookEventType.FILE_READ]
|
|
165
211
|
if scan_outcome.verdict == GuardrailsMode.BLOCK:
|
|
166
212
|
outcome = AIHookOutcome.BLOCKED
|
|
167
|
-
user_message =
|
|
213
|
+
user_message = (
|
|
214
|
+
f'Cycode blocked reading {file_path} because it contains a secret.\n'
|
|
215
|
+
f'{scan_outcome.violation_summary}'
|
|
216
|
+
)
|
|
168
217
|
return HookDecision.deny(
|
|
169
|
-
AiHookEventType.FILE_READ,
|
|
170
|
-
user_message,
|
|
171
|
-
'Secrets detected; do not send this file to the model.',
|
|
218
|
+
AiHookEventType.FILE_READ, user_message, _false_positive_agent_hint(scan_outcome.shas)
|
|
172
219
|
)
|
|
173
220
|
outcome = AIHookOutcome.WARNED
|
|
174
|
-
user_message = f'Cycode detected secrets in {file_path}
|
|
221
|
+
user_message = f'Cycode detected secrets in {file_path}.\n{scan_outcome.violation_summary}'
|
|
175
222
|
return HookDecision.ask(
|
|
176
223
|
AiHookEventType.FILE_READ,
|
|
177
224
|
user_message,
|
|
@@ -282,7 +329,7 @@ def _handle_arg_scan(
|
|
|
282
329
|
return HookDecision.deny(
|
|
283
330
|
feature.event_type,
|
|
284
331
|
feature.deny_message(scan_outcome.violation_summary),
|
|
285
|
-
feature.deny_agent_message,
|
|
332
|
+
f'{feature.deny_agent_message} {_false_positive_agent_hint(scan_outcome.shas)}',
|
|
286
333
|
)
|
|
287
334
|
outcome = AIHookOutcome.WARNED
|
|
288
335
|
return HookDecision.ask(
|
|
@@ -360,9 +407,11 @@ def handle_before_mcp_execution(ctx: typer.Context, payload: AIHookPayload, poli
|
|
|
360
407
|
policy,
|
|
361
408
|
_ArgScanFeature(
|
|
362
409
|
event_type=AiHookEventType.MCP_EXECUTION,
|
|
363
|
-
deny_message=lambda v:
|
|
410
|
+
deny_message=lambda v: (
|
|
411
|
+
f'Cycode blocked MCP tool call "{tool}" because its arguments contain a secret.\n{v}'
|
|
412
|
+
),
|
|
364
413
|
deny_agent_message='Do not pass secrets to tools. Use secret references (name/id) instead.',
|
|
365
|
-
ask_message=lambda v: f'Allow MCP tool call "{tool}"
|
|
414
|
+
ask_message=lambda v: f'Allow MCP tool call "{tool}"?\n{v}',
|
|
366
415
|
ask_agent_message='Possible secrets detected in tool arguments; proceed with caution.',
|
|
367
416
|
scan_enabled=get_policy_value(policy, 'mcp', 'scan_args', default=True),
|
|
368
417
|
),
|
|
@@ -478,11 +527,14 @@ def _perform_scan(
|
|
|
478
527
|
if not local_scan_result:
|
|
479
528
|
return NO_SCAN
|
|
480
529
|
|
|
481
|
-
violation_summary =
|
|
530
|
+
violation_summary, shas = (
|
|
531
|
+
build_violation_summary([local_scan_result]) if local_scan_result.issue_detected else (None, ())
|
|
532
|
+
)
|
|
482
533
|
return ScanOutcome(
|
|
483
534
|
violation_summary=violation_summary,
|
|
484
535
|
scan_id=local_scan_result.scan_id,
|
|
485
536
|
verdict=_parse_verdict(local_scan_result.verdict),
|
|
537
|
+
shas=shas,
|
|
486
538
|
)
|
|
487
539
|
|
|
488
540
|
|
|
@@ -8,14 +8,17 @@ import json
|
|
|
8
8
|
import os
|
|
9
9
|
import sys
|
|
10
10
|
from collections import defaultdict
|
|
11
|
+
from gettext import ngettext
|
|
11
12
|
from pathlib import Path
|
|
12
13
|
from typing import TYPE_CHECKING
|
|
13
14
|
|
|
14
15
|
from cycode.cli.apps.ai_guardrails.scan.policy import get_policy_value
|
|
15
16
|
from cycode.cli.cli_types import SeverityOption
|
|
17
|
+
from cycode.cli.utils.string_utils import obfuscate_text
|
|
16
18
|
|
|
17
19
|
if TYPE_CHECKING:
|
|
18
20
|
from cycode.cli.models import LocalScanResult
|
|
21
|
+
from cycode.cyclient.models import Detection
|
|
19
22
|
|
|
20
23
|
# Keeps the hook message readable when a single file trips dozens of detections
|
|
21
24
|
MAX_VIOLATION_DETAIL_LINES = 5
|
|
@@ -98,35 +101,50 @@ def output_json(obj: dict) -> None:
|
|
|
98
101
|
print(json.dumps(obj), end='') # noqa: T201
|
|
99
102
|
|
|
100
103
|
|
|
101
|
-
def
|
|
104
|
+
def _describe_detection(detection: 'Detection', content: str) -> str:
|
|
105
|
+
details = detection.detection_details
|
|
106
|
+
description = detection.type or detection.message
|
|
107
|
+
|
|
108
|
+
line = details.get('line')
|
|
109
|
+
if isinstance(line, int) and line >= 0:
|
|
110
|
+
description += f' (line {line + 1})' # the scanner reports 0-based lines
|
|
111
|
+
|
|
112
|
+
start, length = details.get('start_position'), details.get('length')
|
|
113
|
+
if isinstance(start, int) and isinstance(length, int) and start >= 0 and length > 0:
|
|
114
|
+
value = content[start : start + length]
|
|
115
|
+
if value:
|
|
116
|
+
description += f': {obfuscate_text(value)}'
|
|
117
|
+
|
|
118
|
+
return description
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def build_violation_summary(
|
|
102
122
|
local_scan_results: list['LocalScanResult'], max_lines: int = MAX_VIOLATION_DETAIL_LINES
|
|
103
|
-
) -> str:
|
|
104
|
-
"""One line per distinct finding
|
|
123
|
+
) -> tuple[str, tuple[str, ...]]:
|
|
124
|
+
"""One line per distinct finding (what it is, where, the masked value), and the value hashes to ignore them by.
|
|
105
125
|
|
|
106
|
-
The value hash
|
|
126
|
+
The masked value and hash are safe to display; the value itself is not. Detections excluded by an existing
|
|
107
127
|
ignore rule are already gone from `document_detections`, so only what actually blocked is listed.
|
|
108
128
|
"""
|
|
109
|
-
|
|
129
|
+
# Keyed by value hash so a repeated value is listed once; detections without one key by their description
|
|
130
|
+
finding_by_key = {}
|
|
110
131
|
for local_scan_result in local_scan_results:
|
|
111
132
|
for document_detections in local_scan_result.document_detections:
|
|
112
133
|
for detection in document_detections.detections:
|
|
134
|
+
description = _describe_detection(detection, document_detections.document.content)
|
|
113
135
|
sha = detection.detection_details.get('sha512')
|
|
114
|
-
|
|
115
|
-
type_by_sha[sha] = detection.type or detection.message
|
|
116
|
-
|
|
117
|
-
if not type_by_sha:
|
|
118
|
-
return ''
|
|
136
|
+
finding_by_key.setdefault(sha or description, (sha, description))
|
|
119
137
|
|
|
120
|
-
|
|
121
|
-
|
|
138
|
+
listed = list(finding_by_key.values())[:max_lines]
|
|
139
|
+
lines = [_build_severity_line(local_scan_results)] + [f' - {description}' for _, description in listed]
|
|
140
|
+
remaining = len(finding_by_key) - len(listed)
|
|
122
141
|
if remaining:
|
|
123
142
|
lines.append(f' - ...and {remaining} more')
|
|
124
143
|
|
|
125
|
-
return '\n'
|
|
144
|
+
return '\n'.join(lines), tuple(sha for sha, _ in listed if sha)
|
|
126
145
|
|
|
127
146
|
|
|
128
|
-
def
|
|
129
|
-
"""Build violation summary string with severity breakdown and emojis."""
|
|
147
|
+
def _build_severity_line(local_scan_results: list['LocalScanResult']) -> str:
|
|
130
148
|
detections_count = 0
|
|
131
149
|
severity_counts = defaultdict(int)
|
|
132
150
|
|
|
@@ -143,5 +161,5 @@ def build_violation_summary(local_scan_results: list['LocalScanResult']) -> str:
|
|
|
143
161
|
count = severity_counts[severity]
|
|
144
162
|
severity_parts.append(f'{emoji} {severity.upper()} - {count}')
|
|
145
163
|
|
|
146
|
-
|
|
147
|
-
return
|
|
164
|
+
violations = ngettext('violation', 'violations', detections_count)
|
|
165
|
+
return f'Cycode found {detections_count} {violations}: {" | ".join(severity_parts)}'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/ides/_plugin_utils.py
RENAMED
|
File without changes
|
{cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/ides/_skill_utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/scan/guardrail_config.py
RENAMED
|
File without changes
|
{cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/scan/mcp_server_status.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/scan/scan_command.py
RENAMED
|
File without changes
|
|
File without changes
|
{cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/session_start_command.py
RENAMED
|
File without changes
|
|
File without changes
|
{cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_guardrails/uninstall_command.py
RENAMED
|
File without changes
|
|
File without changes
|
{cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_remediation/ai_remediation_command.py
RENAMED
|
File without changes
|
|
File without changes
|
{cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/ai_remediation/print_remediation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/report/sbom/repository_url/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/report_import/report_import_command.py
RENAMED
|
File without changes
|
|
File without changes
|
{cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/report_import/sbom/sbom_command.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/pre_commit/pre_commit_command.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/pre_receive/pre_receive_command.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/apps/scan/repository/repository_command.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/exceptions/handle_ai_remediation_errors.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/exceptions/handle_report_sbom_errors.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/commit_range_documents.py
RENAMED
|
File without changes
|
{cycode-3.25.2.dev4 → cycode-3.26.1.dev1}/cycode/cli/files_collector/documents_walk_ignore.py
RENAMED
|
File without changes
|