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.
Files changed (205) hide show
  1. {cycode-3.11.6.dev1 → cycode-3.12.1}/PKG-INFO +49 -5
  2. {cycode-3.11.6.dev1 → cycode-3.12.1}/README.md +48 -4
  3. cycode-3.12.1/cycode/__init__.py +1 -0
  4. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/mcp/mcp_command.py +134 -48
  5. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report/sbom/path/path_command.py +4 -1
  6. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/sca_options.py +11 -0
  7. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/code_scanner.py +1 -0
  8. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/scan_command.py +8 -0
  9. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/exceptions/custom_exceptions.py +9 -0
  10. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/exceptions/handle_scan_errors.py +6 -0
  11. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/path_documents.py +6 -0
  12. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/sca_file_collector.py +5 -0
  13. {cycode-3.11.6.dev1 → cycode-3.12.1}/pyproject.toml +1 -1
  14. cycode-3.11.6.dev1/cycode/__init__.py +0 -1
  15. {cycode-3.11.6.dev1 → cycode-3.12.1}/LICENCE +0 -0
  16. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/__main__.py +0 -0
  17. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/__init__.py +0 -0
  18. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/app.py +0 -0
  19. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/__init__.py +0 -0
  20. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/activation_manager.py +0 -0
  21. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/__init__.py +0 -0
  22. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/command_utils.py +0 -0
  23. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/consts.py +0 -0
  24. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/ensure_auth_command.py +0 -0
  25. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/hooks_manager.py +0 -0
  26. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/install_command.py +0 -0
  27. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/scan/__init__.py +0 -0
  28. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/scan/consts.py +0 -0
  29. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/scan/handlers.py +0 -0
  30. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/scan/payload.py +0 -0
  31. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/scan/policy.py +0 -0
  32. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/scan/response_builders.py +0 -0
  33. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/scan/scan_command.py +0 -0
  34. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/scan/types.py +0 -0
  35. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/scan/utils.py +0 -0
  36. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/status_command.py +0 -0
  37. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_guardrails/uninstall_command.py +0 -0
  38. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_remediation/__init__.py +0 -0
  39. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_remediation/ai_remediation_command.py +0 -0
  40. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_remediation/apply_fix.py +0 -0
  41. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ai_remediation/print_remediation.py +0 -0
  42. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/auth/__init__.py +0 -0
  43. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/auth/auth_command.py +0 -0
  44. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/auth/auth_common.py +0 -0
  45. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/auth/auth_manager.py +0 -0
  46. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/auth/models.py +0 -0
  47. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/configure/__init__.py +0 -0
  48. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/configure/configure_command.py +0 -0
  49. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/configure/consts.py +0 -0
  50. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/configure/messages.py +0 -0
  51. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/configure/prompts.py +0 -0
  52. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ignore/__init__.py +0 -0
  53. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/ignore/ignore_command.py +0 -0
  54. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/mcp/__init__.py +0 -0
  55. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report/__init__.py +0 -0
  56. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report/report_command.py +0 -0
  57. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report/sbom/__init__.py +0 -0
  58. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report/sbom/common.py +0 -0
  59. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report/sbom/path/__init__.py +0 -0
  60. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report/sbom/repository_url/__init__.py +0 -0
  61. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report/sbom/repository_url/repository_url_command.py +0 -0
  62. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report/sbom/sbom_command.py +0 -0
  63. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report/sbom/sbom_report_file.py +0 -0
  64. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report_import/__init__.py +0 -0
  65. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report_import/report_import_command.py +0 -0
  66. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report_import/sbom/__init__.py +0 -0
  67. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/report_import/sbom/sbom_command.py +0 -0
  68. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/__init__.py +0 -0
  69. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/aggregation_report.py +0 -0
  70. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/commit_history/__init__.py +0 -0
  71. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/commit_history/commit_history_command.py +0 -0
  72. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/commit_range_scanner.py +0 -0
  73. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/detection_excluder.py +0 -0
  74. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/path/__init__.py +0 -0
  75. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/path/path_command.py +0 -0
  76. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/pre_commit/__init__.py +0 -0
  77. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/pre_commit/pre_commit_command.py +0 -0
  78. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/pre_push/__init__.py +0 -0
  79. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/pre_push/pre_push_command.py +0 -0
  80. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/pre_receive/__init__.py +0 -0
  81. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/pre_receive/pre_receive_command.py +0 -0
  82. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/remote_url_resolver.py +0 -0
  83. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/repository/__init__.py +0 -0
  84. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/repository/repository_command.py +0 -0
  85. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/scan_ci/__init__.py +0 -0
  86. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/scan_ci/ci_integrations.py +0 -0
  87. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/scan_ci/scan_ci_command.py +0 -0
  88. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/scan_parameters.py +0 -0
  89. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/scan/scan_result.py +0 -0
  90. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/status/__init__.py +0 -0
  91. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/status/get_cli_status.py +0 -0
  92. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/status/models.py +0 -0
  93. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/status/status_command.py +0 -0
  94. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/apps/status/version_command.py +0 -0
  95. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/cli_types.py +0 -0
  96. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/config.py +0 -0
  97. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/console.py +0 -0
  98. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/consts.py +0 -0
  99. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/exceptions/__init__.py +0 -0
  100. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/exceptions/handle_ai_remediation_errors.py +0 -0
  101. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/exceptions/handle_auth_errors.py +0 -0
  102. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/exceptions/handle_errors.py +0 -0
  103. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/exceptions/handle_report_sbom_errors.py +0 -0
  104. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/__init__.py +0 -0
  105. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/commit_range_documents.py +0 -0
  106. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/documents_walk_ignore.py +0 -0
  107. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/file_excluder.py +0 -0
  108. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/iac/__init__.py +0 -0
  109. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/iac/tf_content_generator.py +0 -0
  110. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/models/__init__.py +0 -0
  111. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/models/in_memory_zip.py +0 -0
  112. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/repository_documents.py +0 -0
  113. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/__init__.py +0 -0
  114. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/base_restore_dependencies.py +0 -0
  115. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/go/__init__.py +0 -0
  116. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/go/restore_go_dependencies.py +0 -0
  117. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/maven/__init__.py +0 -0
  118. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/maven/restore_gradle_dependencies.py +0 -0
  119. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/maven/restore_maven_dependencies.py +0 -0
  120. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/npm/__init__.py +0 -0
  121. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/npm/restore_deno_dependencies.py +0 -0
  122. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/npm/restore_npm_dependencies.py +0 -0
  123. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/npm/restore_pnpm_dependencies.py +0 -0
  124. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/npm/restore_yarn_dependencies.py +0 -0
  125. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/nuget/__init__.py +0 -0
  126. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/nuget/restore_nuget_dependencies.py +0 -0
  127. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/php/__init__.py +0 -0
  128. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/php/restore_composer_dependencies.py +0 -0
  129. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/python/__init__.py +0 -0
  130. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/python/restore_pipenv_dependencies.py +0 -0
  131. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/python/restore_poetry_dependencies.py +0 -0
  132. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/ruby/__init__.py +0 -0
  133. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/ruby/restore_ruby_dependencies.py +0 -0
  134. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/sbt/__init__.py +0 -0
  135. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/sca/sbt/restore_sbt_dependencies.py +0 -0
  136. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/walk_ignore.py +0 -0
  137. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/files_collector/zip_documents.py +0 -0
  138. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/logger.py +0 -0
  139. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/main.py +0 -0
  140. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/models.py +0 -0
  141. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/__init__.py +0 -0
  142. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/console_printer.py +0 -0
  143. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/json_printer.py +0 -0
  144. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/printer_base.py +0 -0
  145. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/rich_printer.py +0 -0
  146. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/tables/__init__.py +0 -0
  147. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/tables/sca_table_printer.py +0 -0
  148. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/tables/table.py +0 -0
  149. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/tables/table_models.py +0 -0
  150. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/tables/table_printer.py +0 -0
  151. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/tables/table_printer_base.py +0 -0
  152. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/text_printer.py +0 -0
  153. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/utils/__init__.py +0 -0
  154. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/utils/code_snippet_syntax.py +0 -0
  155. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/utils/detection_data.py +0 -0
  156. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/utils/detection_ordering/__init__.py +0 -0
  157. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/utils/detection_ordering/common_ordering.py +0 -0
  158. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/utils/detection_ordering/sca_ordering.py +0 -0
  159. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/printers/utils/rich_helpers.py +0 -0
  160. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/user_settings/__init__.py +0 -0
  161. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/user_settings/base_file_manager.py +0 -0
  162. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/user_settings/config_file_manager.py +0 -0
  163. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/user_settings/configuration_manager.py +0 -0
  164. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/user_settings/credentials_manager.py +0 -0
  165. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/user_settings/jwt_creator.py +0 -0
  166. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/__init__.py +0 -0
  167. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/binary_utils.py +0 -0
  168. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/enum_utils.py +0 -0
  169. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/get_api_client.py +0 -0
  170. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/git_proxy.py +0 -0
  171. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/ignore_utils.py +0 -0
  172. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/jwt_utils.py +0 -0
  173. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/path_utils.py +0 -0
  174. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/progress_bar.py +0 -0
  175. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/scan_batch.py +0 -0
  176. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/scan_utils.py +0 -0
  177. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/shell_executor.py +0 -0
  178. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/string_utils.py +0 -0
  179. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/task_timer.py +0 -0
  180. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/url_utils.py +0 -0
  181. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/version_checker.py +0 -0
  182. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cli/utils/yaml_utils.py +0 -0
  183. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/config.py +0 -0
  184. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/__init__.py +0 -0
  185. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/ai_security_manager_client.py +0 -0
  186. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/ai_security_manager_service_config.py +0 -0
  187. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/auth_client.py +0 -0
  188. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/base_token_auth_client.py +0 -0
  189. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/cli_activation_client.py +0 -0
  190. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/client_creator.py +0 -0
  191. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/config.py +0 -0
  192. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/config_dev.py +0 -0
  193. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/cycode_client.py +0 -0
  194. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/cycode_client_base.py +0 -0
  195. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/cycode_dev_based_client.py +0 -0
  196. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/cycode_oidc_based_client.py +0 -0
  197. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/cycode_token_based_client.py +0 -0
  198. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/headers.py +0 -0
  199. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/import_sbom_client.py +0 -0
  200. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/logger.py +0 -0
  201. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/models.py +0 -0
  202. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/report_client.py +0 -0
  203. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/scan_client.py +0 -0
  204. {cycode-3.11.6.dev1 → cycode-3.12.1}/cycode/cyclient/scan_config_base.py +0 -0
  205. {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.11.6.dev1
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 files for hardcoded secrets |
429
- | `cycode_sca_scan` | Scan files for Software Composition Analysis (SCA) - vulnerabilities and license issues |
430
- | `cycode_iac_scan` | Scan files for Infrastructure as Code (IaC) misconfigurations |
431
- | `cycode_sast_scan` | Scan files for Static Application Security Testing (SAST) - code quality and security flaws |
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 files for hardcoded secrets |
388
- | `cycode_sca_scan` | Scan files for Software Composition Analysis (SCA) - vulnerabilities and license issues |
389
- | `cycode_iac_scan` | Scan files for Infrastructure as Code (IaC) misconfigurations |
390
- | `cycode_sast_scan` | Scan files for Static Application Security Testing (SAST) - code quality and security flaws |
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(description='Files to scan, mapping file paths to their content')
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, temp_files: list[str]) -> dict[str, Any]:
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', *temp_files])
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
- async def _cycode_scan_tool(scan_type: ScanTypeOption, files: dict[str, str] = _FILES_TOOL_FIELD) -> str:
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({'error': 'No files provided'})
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
- with _TempFilesManager(files, _tool_call_id) as temp_files:
186
- original_count = len(files)
187
- processed_count = len(temp_files)
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, 'files_count': processed_count, 'call_id': _tool_call_id},
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, temp_files)
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
- _logger.info('Scan completed, %s', {'scan_type': scan_type, 'call_id': _tool_call_id})
207
- return json.dumps(result, indent=2)
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(files: dict[str, str] = _FILES_TOOL_FIELD) -> str:
217
- """Scan files for hardcoded secrets.
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
- files: Dictionary mapping file paths to their content
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 containing scan results and any secrets found
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(files: dict[str, str] = _FILES_TOOL_FIELD) -> str:
234
- """Scan files for Software Composition Analysis (SCA) - vulnerabilities and license issues.
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
- You must provide manifest and lock files together.
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
- files: Dictionary mapping file paths to their content
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 containing scan results, vulnerabilities, and license issues found
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(files: dict[str, str] = _FILES_TOOL_FIELD) -> str:
257
- """Scan files for Infrastructure as Code (IaC) misconfigurations.
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
- files: Dictionary mapping file paths to their content
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 containing scan results and any misconfigurations found
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(files: dict[str, str] = _FILES_TOOL_FIELD) -> str:
276
- """Scan files for Static Application Security Testing (SAST) - code quality and security flaws.
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
- files: Dictionary mapping file paths to their content
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 containing scan results and any security flaws found
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:
@@ -21,7 +21,7 @@ classifiers = [
21
21
  "Programming Language :: Python :: 3.14",
22
22
  ]
23
23
  dynamic = ["dependencies"]
24
- version = "3.11.6.dev1"
24
+ version = "3.12.1"
25
25
 
26
26
  [project.scripts]
27
27
  cycode = "cycode.cli.app:app"
@@ -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