socketsecurity 2.10.12__tar.gz → 2.11.2__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 (177) hide show
  1. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/.github/actions/setup-sfw/action.yml +1 -1
  2. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/.github/workflows/dependency-review.yml +84 -8
  3. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/.github/workflows/e2e-test.yml +3 -3
  4. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/.github/workflows/package-check.yml +1 -1
  5. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/.github/workflows/pr-preview.yml +3 -3
  6. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/.github/workflows/python-tests.yml +1 -0
  7. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/CHANGELOG.md +38 -0
  8. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/Dockerfile +28 -5
  9. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/PKG-INFO +8 -8
  10. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/docs/cli-reference.md +3 -10
  11. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/pyproject.toml +8 -8
  12. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/__init__.py +1 -1
  13. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/config.py +1 -1
  14. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/cli_client.py +15 -2
  15. socketsecurity-2.11.2/socketsecurity/core/tools/coana-cache.mjs +203 -0
  16. socketsecurity-2.11.2/socketsecurity/core/tools/reachability.py +440 -0
  17. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/socketcli.py +2 -3
  18. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_client.py +19 -0
  19. socketsecurity-2.11.2/tests/unit/test_reachability.py +162 -0
  20. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/uv.lock +77 -76
  21. socketsecurity-2.10.12/socketsecurity/core/tools/reachability.py +0 -493
  22. socketsecurity-2.10.12/tests/unit/test_reachability.py +0 -447
  23. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/.github/CODEOWNERS +0 -0
  24. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/.github/PULL_REQUEST_TEMPLATE/bug-fix.md +0 -0
  25. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/.github/PULL_REQUEST_TEMPLATE/feature.md +0 -0
  26. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/.github/PULL_REQUEST_TEMPLATE/improvement.md +0 -0
  27. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  28. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/.github/actions/setup-docker/action.yml +0 -0
  29. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/.github/actions/setup-hatch/action.yml +0 -0
  30. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/.github/dependabot.yml +0 -0
  31. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/.github/workflows/dependency-audit.yml +0 -0
  32. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/.github/workflows/docker-stable.yml +0 -0
  33. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/.github/workflows/release.yml +0 -0
  34. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/.github/workflows/version-check.yml +0 -0
  35. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/.github/zizmor.yml +0 -0
  36. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/.gitignore +0 -0
  37. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/.hooks/sync_version.py +0 -0
  38. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/.pre-commit-config.yaml +0 -0
  39. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/.python-version +0 -0
  40. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/CONTRIBUTING.md +0 -0
  41. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/Dockerfile.preview +0 -0
  42. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/LICENSE +0 -0
  43. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/Makefile +0 -0
  44. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/README.md +0 -0
  45. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/benchmarks/manifest_discovery.py +0 -0
  46. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/docs/ci-cd.md +0 -0
  47. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/docs/development.md +0 -0
  48. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/docs/troubleshooting.md +0 -0
  49. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/examples/config/sarif-dashboard-parity.json +0 -0
  50. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/examples/config/sarif-dashboard-parity.toml +0 -0
  51. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/examples/config/sarif-diff-ci-cd.json +0 -0
  52. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/examples/config/sarif-diff-ci-cd.toml +0 -0
  53. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/examples/config/sarif-instance-detail.json +0 -0
  54. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/examples/config/sarif-instance-detail.toml +0 -0
  55. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/instructions/gitlab-commit-status/uat.md +0 -0
  56. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/pytest.ini +0 -0
  57. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/scripts/build_container.sh +0 -0
  58. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/scripts/build_container_flexible.sh +0 -0
  59. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/scripts/deploy-test-docker.sh +0 -0
  60. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/scripts/deploy-test-pypi.sh +0 -0
  61. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/scripts/docker-entrypoint.sh +0 -0
  62. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/scripts/run.sh +0 -0
  63. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/session.md +0 -0
  64. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socket.yml +0 -0
  65. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/__init__.py +0 -0
  66. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/alert_selection.py +0 -0
  67. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/classes.py +0 -0
  68. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/cli_run.py +0 -0
  69. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/exceptions.py +0 -0
  70. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/git_interface.py +0 -0
  71. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/git_remote.py +0 -0
  72. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/helper/__init__.py +0 -0
  73. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/helper/socket_facts_loader.py +0 -0
  74. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/lazy_file_loader.py +0 -0
  75. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/log_uploader.py +0 -0
  76. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/logging.py +0 -0
  77. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/messages.py +0 -0
  78. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/pull_request.py +0 -0
  79. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/resource_utils.py +0 -0
  80. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/scm/__init__.py +0 -0
  81. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/scm/base.py +0 -0
  82. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/scm/client.py +0 -0
  83. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/scm/github.py +0 -0
  84. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/scm/gitlab.py +0 -0
  85. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/scm_comments.py +0 -0
  86. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/socket_config.py +0 -0
  87. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/streaming.py +0 -0
  88. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/core/utils.py +0 -0
  89. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/fossa_compat.py +0 -0
  90. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/output.py +0 -0
  91. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/plugins/__init__.py +0 -0
  92. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/plugins/base.py +0 -0
  93. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/plugins/formatters/__init__.py +0 -0
  94. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/plugins/formatters/slack.py +0 -0
  95. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/plugins/jira.py +0 -0
  96. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/plugins/manager.py +0 -0
  97. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/plugins/slack.py +0 -0
  98. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/plugins/teams.py +0 -0
  99. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/socketsecurity/plugins/webhook.py +0 -0
  100. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/__init__.py +0 -0
  101. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/core/conftest.py +0 -0
  102. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/core/create_diff_input.json +0 -0
  103. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/core/test_diff_alerts.py +0 -0
  104. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/core/test_diff_generation.py +0 -0
  105. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/core/test_diff_scan_polling.py +0 -0
  106. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/core/test_facts_compression.py +0 -0
  107. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/core/test_full_scan_outputs.py +0 -0
  108. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/core/test_has_manifest_files.py +0 -0
  109. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/core/test_invalid_facts_marker.py +0 -0
  110. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/core/test_package_and_alerts.py +0 -0
  111. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/core/test_sdk_methods.py +0 -0
  112. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/core/test_supporting_methods.py +0 -0
  113. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/data/fullscans/create_response.json +0 -0
  114. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/data/fullscans/diff/stream_diff.json +0 -0
  115. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/data/fullscans/diff/stream_diff_full.json +0 -0
  116. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/data/fullscans/head_scan/metadata.json +0 -0
  117. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/data/fullscans/head_scan/stream_scan.json +0 -0
  118. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/data/fullscans/head_scan/stream_scan_full.json +0 -0
  119. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/data/fullscans/new_scan/metadata.json +0 -0
  120. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/data/fullscans/new_scan/stream_scan.json +0 -0
  121. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/data/repos/repo_info_error.json +0 -0
  122. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/data/repos/repo_info_no_head.json +0 -0
  123. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/data/repos/repo_info_success.json +0 -0
  124. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/data/settings/security-policy.json +0 -0
  125. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/e2e/fixtures/simple-npm/index.js +0 -0
  126. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/e2e/fixtures/simple-npm/package.json +0 -0
  127. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/e2e/fixtures/simple-pypi/requirements.txt +0 -0
  128. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/e2e/reach-facts-probe.sh +0 -0
  129. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/e2e/validate-gitlab.sh +0 -0
  130. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/e2e/validate-json.sh +0 -0
  131. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/e2e/validate-reachability.sh +0 -0
  132. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/e2e/validate-sarif.sh +0 -0
  133. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/e2e/validate-scan.sh +0 -0
  134. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/fixtures/fossa/README.md +0 -0
  135. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/fixtures/fossa/fossa-analyze-empty.json +0 -0
  136. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/fixtures/fossa/fossa-analyze-populated.json +0 -0
  137. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/fixtures/fossa/fossa-sbom-empty-deep.json +0 -0
  138. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/fixtures/fossa/fossa-sbom-populated.json +0 -0
  139. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/__init__.py +0 -0
  140. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_alert_selection.py +0 -0
  141. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_cli_config.py +0 -0
  142. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_cli_run.py +0 -0
  143. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_commit_message_truncation.py +0 -0
  144. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_config.py +0 -0
  145. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_dependency_overview.py +0 -0
  146. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_disable_ignore.py +0 -0
  147. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_exclude_paths.py +0 -0
  148. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_fossa_compat.py +0 -0
  149. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_fossa_parity.py +0 -0
  150. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_full_scan_retry.py +0 -0
  151. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_git_interface.py +0 -0
  152. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_git_remote.py +0 -0
  153. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_github_buildkite_config.py +0 -0
  154. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_gitlab_auth.py +0 -0
  155. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_gitlab_auth_fallback.py +0 -0
  156. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_gitlab_commit_status.py +0 -0
  157. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_gitlab_format.py +0 -0
  158. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_ignore_authorization.py +0 -0
  159. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_ignore_telemetry_filtering.py +0 -0
  160. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_include_dirs.py +0 -0
  161. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_log_uploader.py +0 -0
  162. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_manifest_discovery.py +0 -0
  163. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_messages.py +0 -0
  164. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_output.py +0 -0
  165. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_pr_comment_rendering.py +0 -0
  166. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_pull_request_context.py +0 -0
  167. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_scan_scope.py +0 -0
  168. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_slack_plugin.py +0 -0
  169. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_slack_severity_normalization.py +0 -0
  170. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_socketcli.py +0 -0
  171. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_streaming.py +0 -0
  172. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_summary_text.py +0 -0
  173. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/tests/unit/test_tier1_finalize.py +0 -0
  174. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/workflows/bitbucket-pipelines.yml +0 -0
  175. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/workflows/buildkite.yml +0 -0
  176. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/workflows/github-actions.yml +0 -0
  177. {socketsecurity-2.10.12 → socketsecurity-2.11.2}/workflows/gitlab-ci.yml +0 -0
@@ -32,7 +32,7 @@ runs:
32
32
  python-version: "3.12"
33
33
 
34
34
  - if: ${{ inputs.node == 'true' }}
35
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
35
+ uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
36
36
  with:
37
37
  node-version: "20"
38
38
 
@@ -81,7 +81,7 @@ jobs:
81
81
  echo "python_deps_changed=$(has_file '^(pyproject\.toml|uv\.lock)$')"
82
82
  echo "fixture_npm_changed=$(has_file '^tests/e2e/fixtures/simple-npm/')"
83
83
  echo "fixture_pypi_changed=$(has_file '^tests/e2e/fixtures/simple-pypi/')"
84
- echo "dockerfile_changed=$(has_file '^Dockerfile$')"
84
+ echo "dockerfile_changed=$(has_file '^(Dockerfile|scripts/docker-entrypoint\.sh)$')"
85
85
  echo "workflow_or_action_changed=$(has_file '^\.github/workflows/|^\.github/actions/|^\.github/dependabot\.yml$')"
86
86
  } >> "$GITHUB_OUTPUT"
87
87
 
@@ -210,7 +210,7 @@ jobs:
210
210
 
211
211
  - name: Upload SFW report artifact
212
212
  if: always()
213
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
213
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
214
214
  with:
215
215
  name: socket-firewall-free-python-${{ github.event.pull_request.number }}
216
216
  path: sfw-artifacts/
@@ -302,7 +302,7 @@ jobs:
302
302
 
303
303
  - name: Upload SFW report artifact
304
304
  if: always()
305
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
305
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
306
306
  with:
307
307
  name: socket-firewall-enterprise-python-${{ github.event.pull_request.number }}
308
308
  path: sfw-artifacts/
@@ -362,7 +362,7 @@ jobs:
362
362
 
363
363
  - name: Upload SFW report artifact
364
364
  if: always()
365
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
365
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
366
366
  with:
367
367
  name: socket-firewall-free-npm-${{ github.event.pull_request.number }}
368
368
  path: sfw-artifacts/
@@ -424,7 +424,7 @@ jobs:
424
424
 
425
425
  - name: Upload SFW report artifact
426
426
  if: always()
427
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
427
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
428
428
  with:
429
429
  name: socket-firewall-enterprise-npm-${{ github.event.pull_request.number }}
430
430
  path: sfw-artifacts/
@@ -487,7 +487,7 @@ jobs:
487
487
 
488
488
  - name: Upload SFW report artifact
489
489
  if: always()
490
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
490
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
491
491
  with:
492
492
  name: socket-firewall-free-pypi-${{ github.event.pull_request.number }}
493
493
  path: sfw-artifacts/
@@ -552,7 +552,7 @@ jobs:
552
552
 
553
553
  - name: Upload SFW report artifact
554
554
  if: always()
555
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
555
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
556
556
  with:
557
557
  name: socket-firewall-enterprise-pypi-${{ github.event.pull_request.number }}
558
558
  path: sfw-artifacts/
@@ -562,7 +562,18 @@ jobs:
562
562
  dockerfile-smoke:
563
563
  needs: inspect
564
564
  if: needs.inspect.outputs.dockerfile_changed == 'true'
565
- runs-on: ubuntu-latest
565
+ # Build every architecture the release publishes, each on a native runner,
566
+ # so an arm64-only break shows up here rather than in release.yml.
567
+ strategy:
568
+ fail-fast: false
569
+ matrix:
570
+ include:
571
+ - arch: amd64
572
+ runner: ubuntu-24.04
573
+ - arch: arm64
574
+ runner: ubuntu-24.04-arm
575
+ name: dockerfile-smoke (${{ matrix.arch }})
576
+ runs-on: ${{ matrix.runner }}
566
577
  timeout-minutes: 20
567
578
  steps:
568
579
  - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
@@ -576,6 +587,71 @@ jobs:
576
587
  --build-arg USE_LOCAL_INSTALL=true
577
588
  -t socket-python-cli:dependabot-smoke .
578
589
 
590
+ - name: Check the tools in the image
591
+ run: |
592
+ docker run --rm --entrypoint sh socket-python-cli:dependabot-smoke -c '
593
+ set -eu
594
+ echo "node $(node -v), npm $(npm -v), yarn $(yarn -v)"
595
+ socket --version
596
+ socketcli --version
597
+ '
598
+
599
+ # The eMudhra test hosts serve certificates from the compromised
600
+ # intermediates. Require the specific rejection, not just any failure, so
601
+ # a DNS or network error cannot pass as "rejected".
602
+ - name: Check TLS clients reject the compromised eMudhra intermediates
603
+ run: |
604
+ docker run --rm --entrypoint sh socket-python-cli:dependabot-smoke -c '
605
+ set -u
606
+ status=0
607
+ for host in dv-g3b-emudhra.we-have-a-problem.com dv-g3b-aaa-emudhra.we-have-a-problem.com; do
608
+ code=0
609
+ curl -sS -m 30 -o /dev/null "https://$host/" 2>/dev/null || code=$?
610
+ if [ "$code" = 60 ]; then
611
+ echo "curl rejects $host"
612
+ else
613
+ echo "::error::curl on $host exited $code, expected 60 (certificate verification failed)"
614
+ status=1
615
+ fi
616
+ result=$(node -e "
617
+ const req = require(\"https\").get(process.argv[1], { timeout: 30000 }, (res) => {
618
+ console.log(\"ACCEPTED\"); process.exit(0);
619
+ });
620
+ req.on(\"timeout\", () => { console.log(\"TIMEOUT\"); process.exit(0); });
621
+ req.on(\"error\", (e) => { console.log(e.code || e.message); process.exit(0); });
622
+ " "https://$host/")
623
+ case "$result" in
624
+ CERT_REVOKED|UNABLE_TO_GET_ISSUER_CERT_LOCALLY|UNABLE_TO_VERIFY_LEAF_SIGNATURE) echo "node rejects $host ($result)" ;;
625
+ *) echo "::error::node on $host: $result"; status=1 ;;
626
+ esac
627
+ result=$(python -c "
628
+ import sys, requests
629
+ try:
630
+ requests.get(sys.argv[1], timeout=30)
631
+ print(\"ACCEPTED\")
632
+ except requests.exceptions.SSLError:
633
+ print(\"SSLError\")
634
+ except Exception as e:
635
+ print(type(e).__name__)
636
+ " "https://$host/")
637
+ if [ "$result" = SSLError ]; then
638
+ echo "python rejects $host"
639
+ else
640
+ echo "::error::python requests on $host: $result"
641
+ status=1
642
+ fi
643
+ done
644
+ for url in https://api.socket.dev/v0/ https://registry.npmjs.org/ https://pypi.org/simple/; do
645
+ if curl -sS -m 30 -o /dev/null "$url"; then
646
+ echo "curl connects to $url"
647
+ else
648
+ echo "::error::curl cannot connect to $url"
649
+ status=1
650
+ fi
651
+ done
652
+ exit $status
653
+ '
654
+
579
655
  workflow-notice:
580
656
  needs: inspect
581
657
  if: needs.inspect.outputs.workflow_or_action_changed == 'true'
@@ -84,10 +84,10 @@ jobs:
84
84
  with:
85
85
  python-version: '3.12'
86
86
 
87
- - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
87
+ - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
88
88
  if: matrix.setup-node == 'true'
89
89
  with:
90
- node-version: '20'
90
+ node-version: '22'
91
91
 
92
92
  - name: Install CLI from local repo
93
93
  run: |
@@ -138,7 +138,7 @@ jobs:
138
138
 
139
139
  - name: Upload diagnostics on failure
140
140
  if: failure() || steps.run-cli.outputs.diagnostics == 'true'
141
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
141
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
142
142
  with:
143
143
  name: e2e-${{ matrix.name }}-diagnostics-attempt${{ github.run_attempt }}
144
144
  path: |
@@ -58,7 +58,7 @@ jobs:
58
58
  PY
59
59
 
60
60
  - name: Upload distributions
61
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
61
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
62
62
  with:
63
63
  name: socketsecurity-${{ github.sha }}
64
64
  path: dist/*
@@ -153,7 +153,7 @@ jobs:
153
153
  PY
154
154
 
155
155
  - name: Upload preview distributions
156
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
156
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
157
157
  with:
158
158
  name: socketsecurity-preview-${{ github.run_id }}-${{ github.run_attempt }}
159
159
  path: dist/*
@@ -173,7 +173,7 @@ jobs:
173
173
  pull-requests: write
174
174
  steps:
175
175
  - name: Download preview distributions
176
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
176
+ uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
177
177
  with:
178
178
  name: socketsecurity-preview-${{ github.run_id }}-${{ github.run_attempt }}
179
179
  path: dist
@@ -246,7 +246,7 @@ jobs:
246
246
  persist-credentials: false
247
247
 
248
248
  - name: Download preview distributions
249
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
249
+ uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
250
250
  with:
251
251
  name: socketsecurity-preview-${{ github.run_id }}-${{ github.run_attempt }}
252
252
  path: dist
@@ -8,6 +8,7 @@ on:
8
8
  branches: [main]
9
9
  paths:
10
10
  - "socketsecurity/**/*.py"
11
+ - "socketsecurity/**/*.mjs"
11
12
  - "tests/unit/**/*.py"
12
13
  - "tests/core/**/*.py"
13
14
  - "pyproject.toml"
@@ -1,5 +1,43 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.11.2
4
+
5
+ ### Fixed: stop trusting the compromised eMudhra intermediate CAs
6
+
7
+ - The CLI and every tool in the Docker image now reject certificates issued
8
+ from the compromised eMudhra intermediate CAs.
9
+ - Bumped `certifi` to `2026.10.19` and the image's bundled `uv` to `0.13.4`.
10
+ - The image now takes Node.js from the official `node:24-alpine` image (`24.22.1`)
11
+ instead of Alpine's `nodejs` package, which hasn't shipped Node's fix.
12
+
13
+ ### Changed: bump pinned Coana CLI to 15.12.11
14
+
15
+ - Bumped the pinned reachability engine (the Coana CLI) from `15.12.10` to
16
+ `15.12.11`. See the
17
+ [reachability analysis changelog](https://docs.socket.dev/docs/reachability-analysis-changelog)
18
+ for engine changes.
19
+ - Coana CLI `15.12.11` requires Node.js 22.13 or later (previously 20). On an older Node,
20
+ `--reach` fails with exit code 3 (with `--disable-blocking`, the scan continues without
21
+ reachability results). The Docker image already ships a newer Node, but if you run the CLI
22
+ directly (for example in CI), upgrade Node before upgrading the Socket CLI.
23
+
24
+ ## 2.11.1
25
+
26
+ ### Changed: bump pinned Coana CLI to 15.12.10
27
+
28
+ - Bumped the pinned reachability engine (the Coana CLI) from `15.12.8` to
29
+ `15.12.10`. See the
30
+ [reachability analysis changelog](https://docs.socket.dev/docs/reachability-analysis-changelog)
31
+ for engine changes.
32
+
33
+ ## 2.11.0
34
+
35
+ ### Changed: download the Coana CLI from Socket instead of npm
36
+
37
+ - The Coana CLI is now downloaded from Socket's servers instead of npm, and is now cached in
38
+ `$XDG_CACHE_HOME/socket/coana` (`~/.cache/socket/coana` by default).
39
+ - The `SOCKET_CLI_COANA_LAUNCHER` environment variable no longer has an effect.
40
+
3
41
  ## 2.10.12
4
42
 
5
43
  ### Changed: bump pinned @coana-tech/cli to 15.12.8
@@ -1,3 +1,8 @@
1
+ # Node.js from the official Alpine image instead of Alpine's nodejs package, which
2
+ # lags Node's security releases. Match the major version to what reachability needs
3
+ # and the Alpine release to the python:3-alpine base below.
4
+ FROM node:24-alpine3.24 AS node
5
+
1
6
  FROM python:3-alpine
2
7
  LABEL org.opencontainers.image.authors="socket.dev"
3
8
 
@@ -14,9 +19,27 @@ ARG PIP_EXTRA_INDEX_URL=https://pypi.org/simple
14
19
  ARG USE_LOCAL_INSTALL=false
15
20
 
16
21
  # Install base packages first
22
+ # ca-certificates must be 20261020-r0 or newer, which drops the roots the
23
+ # compromised eMudhra intermediates chain to. The base image ships an older
24
+ # one, and `apk add` does not upgrade installed packages, so upgrade it here.
17
25
  RUN apk update && apk add --no-cache \
18
- git nodejs npm yarn curl wget \
19
- ruby ruby-dev build-base strace
26
+ git curl wget \
27
+ ruby ruby-dev build-base strace && \
28
+ apk upgrade --no-cache ca-certificates && \
29
+ [ "$(apk version -t "$(apk list -I ca-certificates | awk '{print $1}' | sed 's/^ca-certificates-//')" 20261020-r0)" != "<" ]
30
+
31
+ # npm, npx and yarn are symlinks in the node image. COPY would dereference them
32
+ # into flat files and break their relative requires, so recreate the links.
33
+ COPY --from=node /usr/local/bin/node /usr/local/bin/node
34
+ COPY --from=node /usr/local/lib/node_modules /usr/local/lib/node_modules
35
+ COPY --from=node /opt /opt
36
+ # Node rejects the compromised eMudhra intermediates from 24.22.1.
37
+ RUN ln -s ../lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm && \
38
+ ln -s ../lib/node_modules/npm/bin/npx-cli.js /usr/local/bin/npx && \
39
+ ln -s ../lib/node_modules/corepack/dist/corepack.js /usr/local/bin/corepack && \
40
+ ln -s /opt/yarn-v*/bin/yarn /usr/local/bin/yarn && \
41
+ ln -s /opt/yarn-v*/bin/yarnpkg /usr/local/bin/yarnpkg && \
42
+ node -e 'const [a,b,c]=process.versions.node.split(".").map(Number); process.exit(a>24||(a===24&&(b>22||(b===22&&c>=1)))?0:1)'
20
43
 
21
44
  # Install Go with version control
22
45
  RUN if [ "$GO_VERSION" = "system" ]; then \
@@ -75,7 +98,7 @@ RUN if [ "$TARGETARCH" = "amd64" ]; then \
75
98
  fi
76
99
 
77
100
  # Install additional tools
78
- RUN npm install @coana-tech/cli socket -g && \
101
+ RUN npm install socket -g && \
79
102
  gem install bundler && \
80
103
  curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && \
81
104
  . ~/.cargo/env && \
@@ -85,8 +108,8 @@ RUN npm install @coana-tech/cli socket -g && \
85
108
  ENV PATH="/usr/local/go/bin:/usr/lib/go/bin:/root/.cargo/bin:${PATH}"
86
109
  ENV GOPATH="/go"
87
110
 
88
- # Install uv
89
- COPY --from=ghcr.io/astral-sh/uv:0.10.4 /uv /usr/local/bin/uv
111
+ # Install uv (0.13.4+ ships the patched webpki-roots)
112
+ COPY --from=ghcr.io/astral-sh/uv:0.13.4 /uv /usr/local/bin/uv
90
113
 
91
114
  # Install pyenv
92
115
  # pyenv lets us build/install arbitrary Python versions on demand. We install
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: socketsecurity
3
- Version: 2.10.12
3
+ Version: 2.11.2
4
4
  Summary: Socket Security CLI for CI/CD
5
5
  Project-URL: Homepage, https://socket.dev
6
6
  Author-email: Douglas Coburn <douglas@socket.dev>
@@ -36,24 +36,24 @@ Requires-Python: >=3.11
36
36
  Requires-Dist: beautifulsoup4==4.15.0
37
37
  Requires-Dist: brotli==1.2.0; platform_python_implementation == 'CPython'
38
38
  Requires-Dist: brotlicffi==1.2.0.2; platform_python_implementation != 'CPython'
39
- Requires-Dist: gitpython==3.1.62
40
- Requires-Dist: markdown==3.10.3
39
+ Requires-Dist: gitpython==3.2.0
40
+ Requires-Dist: markdown==3.11.1
41
41
  Requires-Dist: mdutils==1.8.1
42
42
  Requires-Dist: packaging==26.3
43
43
  Requires-Dist: prettytable==3.18.0
44
- Requires-Dist: python-dotenv==1.2.3
44
+ Requires-Dist: python-dotenv==1.2.4
45
45
  Requires-Dist: requests==2.34.2
46
46
  Requires-Dist: socketdev==3.6.0
47
47
  Provides-Extra: dev
48
48
  Requires-Dist: hatch==1.18.1; extra == 'dev'
49
- Requires-Dist: pre-commit==4.6.2; extra == 'dev'
50
- Requires-Dist: ruff==0.16.9; extra == 'dev'
49
+ Requires-Dist: pre-commit==4.7.0; extra == 'dev'
50
+ Requires-Dist: ruff==0.17.0; extra == 'dev'
51
51
  Requires-Dist: twine==7.0.0; extra == 'dev'
52
- Requires-Dist: uv==0.12.18; extra == 'dev'
52
+ Requires-Dist: uv==0.13.4; extra == 'dev'
53
53
  Provides-Extra: test
54
54
  Requires-Dist: pytest-asyncio==1.4.0; extra == 'test'
55
55
  Requires-Dist: pytest-cov==7.1.0; extra == 'test'
56
- Requires-Dist: pytest-mock==3.15.1; extra == 'test'
56
+ Requires-Dist: pytest-mock==3.16.0; extra == 'test'
57
57
  Requires-Dist: pytest-watch==4.2.0; extra == 'test'
58
58
  Requires-Dist: pytest==9.1.1; extra == 'test'
59
59
  Description-Content-Type: text/markdown
@@ -338,7 +338,7 @@ If you don't want to provide the Socket API Token every time then you can use th
338
338
  | Parameter | Required | Default | Description |
339
339
  |:---------------------------------|:---------|:--------|:---------------------------------------------------------------------------------------------------------------------------|
340
340
  | `--reach` | False | False | Enable reachability analysis to identify which vulnerable functions are actually called by your code. Creates a full application reachability scan (`scan_type=socket_tier1`). |
341
- | `--reach-version` | False | 15.12.8 | Version of @coana-tech/cli to use. Defaults to the pinned version that ships with this CLI release, so the engine only changes when you upgrade the Socket CLI. Pass `latest` to always use the newest published version (opt-in auto-update), or an explicit version (e.g. `1.2.3`) to pin it. |
341
+ | `--reach-version` | False | 15.12.11 | Version of the Coana CLI to use. Defaults to the pinned version that ships with this CLI release, so the engine only changes when you upgrade the Socket CLI. Pass `latest` to always use the newest published version (opt-in auto-update), or an explicit version (e.g. `1.2.3`) to pin it. |
342
342
  | `--reach-analysis-timeout` | False | 10m | Timeout for each reachability analysis run, e.g. `90s`, `10m` or `1h`. Omitted by default, so coana applies its own default (`10m`). Alias: `--reach-timeout` |
343
343
  | `--reach-analysis-memory-limit` | False | 8GB | Memory limit for each reachability analysis run, e.g. `512MB` or `8GB`. Omitted by default, so coana applies its own default (`8GB`). Alias: `--reach-memory-limit` |
344
344
  | `--reach-concurrency` | False | 1 | Control parallel analysis execution (must be >= 1). Omitted by default, so coana applies its own default. |
@@ -359,9 +359,7 @@ If you don't want to provide the Socket API Token every time then you can use th
359
359
  **Reachability Analysis Requirements:**
360
360
 
361
361
  The Python CLI verifies the following **up front** (before invoking the analysis engine) and exits with code **3** if any are unmet:
362
- - `npm` - Required (verified up front; ships alongside `npx`)
363
- - `npx` - Required to fetch (on first use) and run `@coana-tech/cli` (the analysis engine)
364
- - `node` - Required to run the engine (used directly by the `npm install` fallback)
362
+ - `node` - Required to run the analysis engine (the Coana CLI). The engine needs Node.js 22.13 or later.
365
363
  - `uv` - Required by the analysis engine
366
364
  - An **Enterprise** Socket organization plan (any `enterprise*` plan, including Enterprise trials)
367
365
 
@@ -419,12 +417,7 @@ Sample config files:
419
417
 
420
418
  For CI-specific examples and guidance, see [`ci-cd.md`](ci-cd.md).
421
419
 
422
- The CLI runs a pinned `@coana-tech/cli` version via `npx --yes --force` (the same flags the Socket Node CLI passes for coana); it does **not** auto-update the engine or install it globally. `--yes` skips npx's interactive install prompt so non-interactive/CI runs don't hang. If the `npx` launcher is unavailable or fails before the engine starts, the CLI falls back to `npm install`-ing the pinned version into a temp directory and running it via `node`. Pass `--reach-version latest` to opt into the newest published version. Use `--reach` to enable reachability analysis during a full scan, or add `--only-facts-file` (with `--reach`) to submit only the reachability facts file (`.socket.facts.json`) when creating the full scan.
423
-
424
- The launcher can be tuned via the `SOCKET_CLI_COANA_LAUNCHER` environment variable:
425
- - `auto` (default when unset) — try `npx` first; fall back to `npm install` + `node` if the launcher fails before the engine starts.
426
- - `npm-install` — skip `npx` entirely and always use the `npm install` + `node` path (useful where `npx` is known-broken).
427
- - `npx` — never fall back; surface the `npx` failure directly.
420
+ The CLI runs a pinned version of the Coana CLI, the analysis engine; it does **not** auto-update the engine. It downloads the engine from the Socket API on first use and keeps it in `$XDG_CACHE_HOME/socket/coana/v1` (`~/.cache/socket/coana/v1` when `XDG_CACHE_HOME` is unset). Pass `--reach-version latest` to opt into the newest published version. Use `--reach` to enable reachability analysis during a full scan, or add `--only-facts-file` (with `--reach`) to submit only the reachability facts file (`.socket.facts.json`) when creating the full scan.
428
421
 
429
422
  #### Advanced Configuration
430
423
  | Parameter | Required | Default | Description |
@@ -6,19 +6,19 @@ build-backend = "hatchling.build"
6
6
 
7
7
  [project]
8
8
  name = "socketsecurity"
9
- version = "2.10.12"
9
+ version = "2.11.2"
10
10
  requires-python = ">= 3.11"
11
11
  license = {"file" = "LICENSE"}
12
12
  dependencies = [
13
13
  "requests==2.34.2",
14
14
  "mdutils==1.8.1",
15
15
  "prettytable==3.18.0",
16
- "gitpython==3.1.62",
16
+ "gitpython==3.2.0",
17
17
  "packaging==26.3",
18
- "python-dotenv==1.2.3",
18
+ "python-dotenv==1.2.4",
19
19
  "socketdev==3.6.0",
20
20
  "beautifulsoup4==4.15.0",
21
- "markdown==3.10.3",
21
+ "markdown==3.11.1",
22
22
  "brotli==1.2.0; platform_python_implementation == 'CPython'",
23
23
  "brotlicffi==1.2.0.2; platform_python_implementation != 'CPython'",
24
24
  ]
@@ -42,15 +42,15 @@ classifiers = [
42
42
  test = [
43
43
  "pytest==9.1.1",
44
44
  "pytest-cov==7.1.0",
45
- "pytest-mock==3.15.1",
45
+ "pytest-mock==3.16.0",
46
46
  "pytest-asyncio==1.4.0",
47
47
  "pytest-watch==4.2.0"
48
48
  ]
49
49
  dev = [
50
- "ruff==0.16.9",
50
+ "ruff==0.17.0",
51
51
  "twine==7.0.0", # for building
52
- "uv==0.12.18", # for dependency management
53
- "pre-commit==4.6.2",
52
+ "uv==0.13.4", # for dependency management
53
+ "pre-commit==4.7.0",
54
54
  "hatch==1.18.1"
55
55
  ]
56
56
 
@@ -1,3 +1,3 @@
1
1
  __author__ = 'socket.dev'
2
- __version__ = '2.10.12'
2
+ __version__ = '2.11.2'
3
3
  USER_AGENT = f'SocketPythonCLI/{__version__}'
@@ -1069,7 +1069,7 @@ def create_argument_parser() -> argparse.ArgumentParser:
1069
1069
  "--reach-version",
1070
1070
  dest="reach_version",
1071
1071
  metavar="<version|latest>",
1072
- help="Version of @coana-tech/cli to use. Defaults to the version pinned to this CLI "
1072
+ help="Version of the Coana CLI to use. Defaults to the version pinned to this CLI "
1073
1073
  "release; pass 'latest' to always use the newest published version (opt-in "
1074
1074
  "auto-update), or an explicit version (e.g. '1.2.3') to pin it."
1075
1075
  )
@@ -55,13 +55,26 @@ class CliClient:
55
55
  return response
56
56
 
57
57
  except requests.exceptions.RequestException as e:
58
- logger.error(f"API request failed: {str(e)}")
58
+ server_message = self._server_error_message(e.response)
59
+ detail = f"{e}: {server_message}" if server_message else str(e)
60
+ logger.error(f"API request failed: {detail}")
59
61
  # Carry the status forward. Callers that need to react to a specific
60
62
  # code -- the GitLab auth fallback to the other token scheme, and
61
63
  # APIFailure.is_transient_error -- have no other way to recover it
62
64
  # once the requests exception has been translated.
63
65
  status_code = e.response.status_code if e.response is not None else None
64
- raise APIFailure(f"Request failed: {str(e)}", status_code=status_code) from e
66
+ raise APIFailure(f"Request failed: {detail}", status_code=status_code) from e
67
+
68
+ @staticmethod
69
+ def _server_error_message(response: Optional[requests.Response]) -> Optional[str]:
70
+ """The explanation the Socket API gives in its ``{"error": {"message": ...}}`` body."""
71
+ if response is None:
72
+ return None
73
+ try:
74
+ message = response.json()["error"]["message"]
75
+ except (ValueError, KeyError, TypeError):
76
+ return None
77
+ return message if isinstance(message, str) and message else None
65
78
 
66
79
  def post_telemetry_events(self, org_slug: str, events: List[Dict]) -> None:
67
80
  """Post telemetry events one at a time to the v0 telemetry API. Fire-and-forget — logs errors but never raises."""