cycode 3.10.3.dev1__tar.gz → 3.10.4.dev1__tar.gz

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