cycode 3.1.1.dev6__tar.gz → 3.2.1.dev1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/PKG-INFO +2 -1
  2. cycode-3.2.1.dev1/cycode/__init__.py +1 -0
  3. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/mcp/mcp_command.py +94 -46
  4. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/pyproject.toml +2 -1
  5. cycode-3.1.1.dev6/cycode/__init__.py +0 -1
  6. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/LICENCE +0 -0
  7. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/README.md +0 -0
  8. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/__main__.py +0 -0
  9. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/__init__.py +0 -0
  10. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/app.py +0 -0
  11. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/__init__.py +0 -0
  12. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/ai_remediation/__init__.py +0 -0
  13. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/ai_remediation/ai_remediation_command.py +0 -0
  14. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/ai_remediation/apply_fix.py +0 -0
  15. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/ai_remediation/print_remediation.py +0 -0
  16. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/auth/__init__.py +0 -0
  17. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/auth/auth_command.py +0 -0
  18. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/auth/auth_common.py +0 -0
  19. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/auth/auth_manager.py +0 -0
  20. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/auth/models.py +0 -0
  21. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/configure/__init__.py +0 -0
  22. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/configure/configure_command.py +0 -0
  23. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/configure/consts.py +0 -0
  24. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/configure/messages.py +0 -0
  25. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/configure/prompts.py +0 -0
  26. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/ignore/__init__.py +0 -0
  27. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/ignore/ignore_command.py +0 -0
  28. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/mcp/__init__.py +0 -0
  29. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/report/__init__.py +0 -0
  30. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/report/report_command.py +0 -0
  31. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/report/sbom/__init__.py +0 -0
  32. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/report/sbom/common.py +0 -0
  33. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/report/sbom/path/__init__.py +0 -0
  34. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/report/sbom/path/path_command.py +0 -0
  35. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/report/sbom/repository_url/__init__.py +0 -0
  36. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/report/sbom/repository_url/repository_url_command.py +0 -0
  37. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/report/sbom/sbom_command.py +0 -0
  38. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/report/sbom/sbom_report_file.py +0 -0
  39. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/scan/__init__.py +0 -0
  40. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/scan/aggregation_report.py +0 -0
  41. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/scan/code_scanner.py +0 -0
  42. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/scan/commit_history/__init__.py +0 -0
  43. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/scan/commit_history/commit_history_command.py +0 -0
  44. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/scan/commit_range_scanner.py +0 -0
  45. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/scan/detection_excluder.py +0 -0
  46. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/scan/path/__init__.py +0 -0
  47. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/scan/path/path_command.py +0 -0
  48. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/scan/pre_commit/__init__.py +0 -0
  49. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/scan/pre_commit/pre_commit_command.py +0 -0
  50. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/scan/pre_receive/__init__.py +0 -0
  51. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/scan/pre_receive/pre_receive_command.py +0 -0
  52. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/scan/remote_url_resolver.py +0 -0
  53. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/scan/repository/__init__.py +0 -0
  54. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/scan/repository/repository_command.py +0 -0
  55. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/scan/scan_ci/__init__.py +0 -0
  56. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/scan/scan_ci/ci_integrations.py +0 -0
  57. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/scan/scan_ci/scan_ci_command.py +0 -0
  58. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/scan/scan_command.py +0 -0
  59. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/scan/scan_parameters.py +0 -0
  60. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/scan/scan_result.py +0 -0
  61. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/status/__init__.py +0 -0
  62. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/status/get_cli_status.py +0 -0
  63. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/status/models.py +0 -0
  64. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/status/status_command.py +0 -0
  65. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/apps/status/version_command.py +0 -0
  66. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/cli_types.py +0 -0
  67. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/config.py +0 -0
  68. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/console.py +0 -0
  69. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/consts.py +0 -0
  70. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/exceptions/__init__.py +0 -0
  71. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/exceptions/custom_exceptions.py +0 -0
  72. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/exceptions/handle_ai_remediation_errors.py +0 -0
  73. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/exceptions/handle_auth_errors.py +0 -0
  74. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/exceptions/handle_errors.py +0 -0
  75. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/exceptions/handle_report_sbom_errors.py +0 -0
  76. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/exceptions/handle_scan_errors.py +0 -0
  77. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/__init__.py +0 -0
  78. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/commit_range_documents.py +0 -0
  79. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/file_excluder.py +0 -0
  80. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/iac/__init__.py +0 -0
  81. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/iac/tf_content_generator.py +0 -0
  82. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/models/__init__.py +0 -0
  83. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/models/in_memory_zip.py +0 -0
  84. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/path_documents.py +0 -0
  85. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/repository_documents.py +0 -0
  86. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/sca/__init__.py +0 -0
  87. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/sca/base_restore_dependencies.py +0 -0
  88. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/sca/go/__init__.py +0 -0
  89. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/sca/go/restore_go_dependencies.py +0 -0
  90. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/sca/maven/__init__.py +0 -0
  91. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/sca/maven/restore_gradle_dependencies.py +0 -0
  92. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/sca/maven/restore_maven_dependencies.py +0 -0
  93. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/sca/npm/__init__.py +0 -0
  94. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/sca/npm/restore_npm_dependencies.py +0 -0
  95. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/sca/nuget/__init__.py +0 -0
  96. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/sca/nuget/restore_nuget_dependencies.py +0 -0
  97. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/sca/ruby/__init__.py +0 -0
  98. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/sca/ruby/restore_ruby_dependencies.py +0 -0
  99. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/sca/sbt/__init__.py +0 -0
  100. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/sca/sbt/restore_sbt_dependencies.py +0 -0
  101. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/sca/sca_file_collector.py +0 -0
  102. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/walk_ignore.py +0 -0
  103. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/files_collector/zip_documents.py +0 -0
  104. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/logger.py +0 -0
  105. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/main.py +0 -0
  106. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/models.py +0 -0
  107. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/printers/__init__.py +0 -0
  108. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/printers/console_printer.py +0 -0
  109. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/printers/json_printer.py +0 -0
  110. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/printers/printer_base.py +0 -0
  111. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/printers/rich_printer.py +0 -0
  112. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/printers/tables/__init__.py +0 -0
  113. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/printers/tables/sca_table_printer.py +0 -0
  114. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/printers/tables/table.py +0 -0
  115. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/printers/tables/table_models.py +0 -0
  116. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/printers/tables/table_printer.py +0 -0
  117. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/printers/tables/table_printer_base.py +0 -0
  118. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/printers/text_printer.py +0 -0
  119. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/printers/utils/__init__.py +0 -0
  120. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/printers/utils/code_snippet_syntax.py +0 -0
  121. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/printers/utils/detection_data.py +0 -0
  122. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/printers/utils/detection_ordering/__init__.py +0 -0
  123. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/printers/utils/detection_ordering/common_ordering.py +0 -0
  124. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/printers/utils/detection_ordering/sca_ordering.py +0 -0
  125. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/printers/utils/rich_helpers.py +0 -0
  126. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/user_settings/__init__.py +0 -0
  127. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/user_settings/base_file_manager.py +0 -0
  128. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/user_settings/config_file_manager.py +0 -0
  129. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/user_settings/configuration_manager.py +0 -0
  130. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/user_settings/credentials_manager.py +0 -0
  131. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/user_settings/jwt_creator.py +0 -0
  132. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/utils/__init__.py +0 -0
  133. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/utils/enum_utils.py +0 -0
  134. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/utils/get_api_client.py +0 -0
  135. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/utils/git_proxy.py +0 -0
  136. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/utils/ignore_utils.py +0 -0
  137. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/utils/jwt_utils.py +0 -0
  138. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/utils/path_utils.py +0 -0
  139. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/utils/progress_bar.py +0 -0
  140. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/utils/scan_batch.py +0 -0
  141. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/utils/scan_utils.py +0 -0
  142. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/utils/sentry.py +0 -0
  143. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/utils/shell_executor.py +0 -0
  144. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/utils/string_utils.py +0 -0
  145. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/utils/task_timer.py +0 -0
  146. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/utils/version_checker.py +0 -0
  147. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cli/utils/yaml_utils.py +0 -0
  148. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/config.py +0 -0
  149. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cyclient/__init__.py +0 -0
  150. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cyclient/auth_client.py +0 -0
  151. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cyclient/client_creator.py +0 -0
  152. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cyclient/config.py +0 -0
  153. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cyclient/config_dev.py +0 -0
  154. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cyclient/cycode_client.py +0 -0
  155. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cyclient/cycode_client_base.py +0 -0
  156. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cyclient/cycode_dev_based_client.py +0 -0
  157. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cyclient/cycode_token_based_client.py +0 -0
  158. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cyclient/headers.py +0 -0
  159. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cyclient/logger.py +0 -0
  160. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cyclient/models.py +0 -0
  161. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cyclient/report_client.py +0 -0
  162. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cyclient/scan_client.py +0 -0
  163. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/cyclient/scan_config_base.py +0 -0
  164. {cycode-3.1.1.dev6 → cycode-3.2.1.dev1}/cycode/logger.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cycode
3
- Version: 3.1.1.dev6
3
+ Version: 3.2.1.dev1
4
4
  Summary: Boost security in your dev lifecycle via SAST, SCA, Secrets & IaC scanning.
5
5
  Home-page: https://github.com/cycodehq/cycode-cli
6
6
  License: MIT
@@ -29,6 +29,7 @@ Requires-Dist: gitpython (>=3.1.30,<3.2.0)
29
29
  Requires-Dist: marshmallow (>=3.15.0,<3.23.0)
30
30
  Requires-Dist: mcp (>=1.9.3,<2.0.0) ; python_version >= "3.10"
31
31
  Requires-Dist: patch-ng (==1.18.1)
32
+ Requires-Dist: pathvalidate (>=3.3.1,<4.0.0)
32
33
  Requires-Dist: pydantic (>=2.11.5,<3.0.0)
33
34
  Requires-Dist: pyjwt (>=2.8.0,<3.0)
34
35
  Requires-Dist: pyyaml (>=6.0,<7.0)
@@ -0,0 +1 @@
1
+ __version__ = '3.2.1.dev1' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
@@ -2,13 +2,14 @@ import asyncio
2
2
  import json
3
3
  import logging
4
4
  import os
5
+ import shutil
5
6
  import sys
6
7
  import tempfile
7
8
  import uuid
8
- from pathlib import Path
9
9
  from typing import Annotated, Any
10
10
 
11
11
  import typer
12
+ from pathvalidate import sanitize_filepath
12
13
  from pydantic import Field
13
14
 
14
15
  from cycode.cli.cli_types import McpTransportOption, ScanTypeOption
@@ -26,7 +27,7 @@ except ImportError:
26
27
 
27
28
  _logger = get_logger('Cycode MCP')
28
29
 
29
- _DEFAULT_RUN_COMMAND_TIMEOUT = 5 * 60
30
+ _DEFAULT_RUN_COMMAND_TIMEOUT = 10 * 60
30
31
 
31
32
  _FILES_TOOL_FIELD = Field(description='Files to scan, mapping file paths to their content')
32
33
 
@@ -91,48 +92,76 @@ async def _run_cycode_command(*args: str, timeout: int = _DEFAULT_RUN_COMMAND_TI
91
92
  return {'error': f'Failed to run command: {e!s}'}
92
93
 
93
94
 
94
- def _create_temp_files(files_content: dict[str, str]) -> list[str]:
95
- """Create temporary files from content and return their paths."""
96
- temp_dir = tempfile.mkdtemp(prefix='cycode_mcp_')
97
- temp_files = []
95
+ def _sanitize_file_path(file_path: str) -> str:
96
+ """Sanitize file path to prevent path traversal and other security issues.
98
97
 
99
- _logger.debug('Creating temporary files in directory: %s', temp_dir)
98
+ Args:
99
+ file_path: The file path to sanitize
100
100
 
101
- for file_path, content in files_content.items():
102
- safe_filename = f'{_gen_random_id()}_{Path(file_path).name}'
103
- temp_file_path = os.path.join(temp_dir, safe_filename)
101
+ Returns:
102
+ Sanitized file path safe for use in temporary directory
104
103
 
105
- os.makedirs(os.path.dirname(temp_file_path), exist_ok=True)
104
+ Raises:
105
+ ValueError: If the path is invalid or potentially dangerous
106
+ """
107
+ if not file_path or not isinstance(file_path, str):
108
+ raise ValueError('File path must be a non-empty string')
106
109
 
107
- _logger.debug('Creating temp file: %s', temp_file_path)
108
- with open(temp_file_path, 'w', encoding='UTF-8') as f:
109
- f.write(content)
110
+ return sanitize_filepath(file_path, platform='auto', validate_after_sanitize=True)
110
111
 
111
- temp_files.append(temp_file_path)
112
112
 
113
- return temp_files
113
+ class _TempFilesManager:
114
+ """Context manager for creating and cleaning up temporary files.
114
115
 
116
+ Creates a temporary directory structure that preserves original file paths
117
+ inside a call_id as a suffix. Automatically cleans up all files and directories
118
+ when exiting the context.
119
+ """
115
120
 
116
- def _cleanup_temp_files(temp_files: list[str]) -> None:
117
- """Clean up temporary files and directories."""
121
+ def __init__(self, files_content: dict[str, str], call_id: str) -> None:
122
+ self.files_content = files_content
123
+ self.call_id = call_id
124
+ self.temp_base_dir = None
125
+ self.temp_files = []
118
126
 
119
- temp_dirs = set()
120
- for temp_file in temp_files:
121
- try:
122
- if os.path.exists(temp_file):
123
- _logger.debug('Removing temp file: %s', temp_file)
124
- os.remove(temp_file)
125
- temp_dirs.add(os.path.dirname(temp_file))
126
- except OSError as e:
127
- _logger.warning('Failed to remove temp file %s: %s', temp_file, e)
128
-
129
- for temp_dir in temp_dirs:
130
- try:
131
- if os.path.exists(temp_dir) and not os.listdir(temp_dir):
132
- _logger.debug('Removing temp directory: %s', temp_dir)
133
- os.rmdir(temp_dir)
134
- except OSError as e:
135
- _logger.warning('Failed to remove temp directory %s: %s', temp_dir, e)
127
+ def __enter__(self) -> list[str]:
128
+ self.temp_base_dir = tempfile.mkdtemp(prefix='cycode_mcp_', suffix=self.call_id)
129
+ _logger.debug('Creating temporary files in directory: %s', self.temp_base_dir)
130
+
131
+ for file_path, content in self.files_content.items():
132
+ try:
133
+ sanitized_path = _sanitize_file_path(file_path)
134
+ temp_file_path = os.path.join(self.temp_base_dir, sanitized_path)
135
+
136
+ # Ensure the normalized path is still within our temp directory
137
+ normalized_temp_path = os.path.normpath(temp_file_path)
138
+ normalized_base_path = os.path.normpath(self.temp_base_dir)
139
+ if not normalized_temp_path.startswith(normalized_base_path + os.sep):
140
+ raise ValueError(f'Path escapes temporary directory: {file_path}')
141
+
142
+ os.makedirs(os.path.dirname(temp_file_path), exist_ok=True)
143
+
144
+ _logger.debug('Creating temp file: %s (from: %s)', temp_file_path, file_path)
145
+ with open(temp_file_path, 'w', encoding='UTF-8') as f:
146
+ f.write(content)
147
+
148
+ self.temp_files.append(temp_file_path)
149
+ except ValueError as e:
150
+ _logger.error('Invalid file path rejected: %s - %s', file_path, str(e))
151
+ continue
152
+ except Exception as e:
153
+ _logger.error('Failed to create temp file for %s: %s', file_path, str(e))
154
+ continue
155
+
156
+ if not self.temp_files:
157
+ raise ValueError('No valid files provided after sanitization')
158
+
159
+ return self.temp_files
160
+
161
+ def __exit__(self, *_) -> None:
162
+ if self.temp_base_dir and os.path.exists(self.temp_base_dir):
163
+ _logger.debug('Removing temp directory recursively: %s', self.temp_base_dir)
164
+ shutil.rmtree(self.temp_base_dir, ignore_errors=True)
136
165
 
137
166
 
138
167
  async def _run_cycode_scan(scan_type: ScanTypeOption, temp_files: list[str]) -> dict[str, Any]:
@@ -153,21 +182,36 @@ async def _cycode_scan_tool(scan_type: ScanTypeOption, files: dict[str, str] = _
153
182
  _logger.error('No files provided for scan')
154
183
  return json.dumps({'error': 'No files provided'})
155
184
 
156
- temp_files = _create_temp_files(files)
157
-
158
185
  try:
159
- _logger.info(
160
- 'Running Cycode scan, %s',
161
- {'scan_type': scan_type, 'files_count': len(temp_files), 'call_id': _tool_call_id},
162
- )
163
- result = await _run_cycode_scan(scan_type, temp_files)
164
- _logger.info('Scan completed, %s', {'scan_type': scan_type, 'call_id': _tool_call_id})
165
- return json.dumps(result, indent=2)
186
+ with _TempFilesManager(files, _tool_call_id) as temp_files:
187
+ original_count = len(files)
188
+ processed_count = len(temp_files)
189
+
190
+ if processed_count < original_count:
191
+ _logger.warning(
192
+ 'Some files were rejected during sanitization, %s',
193
+ {
194
+ 'scan_type': scan_type,
195
+ 'original_count': original_count,
196
+ 'processed_count': processed_count,
197
+ 'call_id': _tool_call_id,
198
+ },
199
+ )
200
+
201
+ _logger.info(
202
+ 'Running Cycode scan, %s',
203
+ {'scan_type': scan_type, 'files_count': processed_count, 'call_id': _tool_call_id},
204
+ )
205
+ result = await _run_cycode_scan(scan_type, temp_files)
206
+
207
+ _logger.info('Scan completed, %s', {'scan_type': scan_type, 'call_id': _tool_call_id})
208
+ return json.dumps(result, indent=2)
209
+ except ValueError as e:
210
+ _logger.error('Invalid input files, %s', {'scan_type': scan_type, 'call_id': _tool_call_id, 'error': str(e)})
211
+ return json.dumps({'error': f'Invalid input files: {e!s}'}, indent=2)
166
212
  except Exception as e:
167
213
  _logger.error('Scan failed, %s', {'scan_type': scan_type, 'call_id': _tool_call_id, 'error': str(e)})
168
214
  return json.dumps({'error': f'Scan failed: {e!s}'}, indent=2)
169
- finally:
170
- _cleanup_temp_files(temp_files)
171
215
 
172
216
 
173
217
  async def cycode_secret_scan(files: dict[str, str] = _FILES_TOOL_FIELD) -> str:
@@ -197,6 +241,10 @@ async def cycode_sca_scan(files: dict[str, str] = _FILES_TOOL_FIELD) -> str:
197
241
  - verify software supply chain security
198
242
  - review package.json, requirements.txt, pom.xml and other dependency files
199
243
 
244
+ Important:
245
+ You must also include lock files (like package-lock.json, Pipfile.lock, etc.) to get accurate results.
246
+ You must provide manifest and lock files together.
247
+
200
248
  Args:
201
249
  files: Dictionary mapping file paths to their content
202
250
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "cycode"
3
- version = "3.1.1.dev6" # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
3
+ version = "3.2.1.dev1" # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
4
4
  description = "Boost security in your dev lifecycle via SAST, SCA, Secrets & IaC scanning."
5
5
  keywords=["secret-scan", "cycode", "devops", "token", "secret", "security", "cycode", "code"]
6
6
  authors = ["Cycode <support@cycode.com>"]
@@ -44,6 +44,7 @@ typer = "^0.15.3"
44
44
  tenacity = ">=9.0.0,<9.1.0"
45
45
  mcp = { version = ">=1.9.3,<2.0.0", markers = "python_version >= '3.10'" }
46
46
  pydantic = ">=2.11.5,<3.0.0"
47
+ pathvalidate = ">=3.3.1,<4.0.0"
47
48
 
48
49
  [tool.poetry.group.test.dependencies]
49
50
  mock = ">=4.0.3,<4.1.0"
@@ -1 +0,0 @@
1
- __version__ = '3.1.1.dev6' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
File without changes
File without changes