socketsecurity 2.4.2__tar.gz → 2.4.4__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.
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/CHANGELOG.md +23 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/PKG-INFO +2 -2
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/docs/cli-reference.md +12 -9
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/pyproject.toml +2 -2
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/__init__.py +1 -1
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/config.py +67 -1
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/core/__init__.py +81 -2
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/socketcli.py +9 -1
- socketsecurity-2.4.4/tests/unit/test_exclude_paths.py +177 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/uv.lock +5 -5
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/.github/CODEOWNERS +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/.github/PULL_REQUEST_TEMPLATE/bug-fix.md +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/.github/PULL_REQUEST_TEMPLATE/feature.md +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/.github/PULL_REQUEST_TEMPLATE/improvement.md +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/.github/actions/setup-docker/action.yml +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/.github/actions/setup-hatch/action.yml +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/.github/actions/setup-sfw/action.yml +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/.github/dependabot.yml +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/.github/workflows/dependency-review.yml +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/.github/workflows/docker-stable.yml +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/.github/workflows/e2e-test.yml +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/.github/workflows/pr-preview.yml +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/.github/workflows/python-tests.yml +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/.github/workflows/release.yml +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/.github/workflows/version-check.yml +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/.github/zizmor.yml +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/.gitignore +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/.hooks/sync_version.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/.pre-commit-config.yaml +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/.python-version +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/Dockerfile +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/LICENSE +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/Makefile +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/README.md +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/docs/ci-cd.md +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/docs/development.md +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/docs/troubleshooting.md +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/examples/config/sarif-dashboard-parity.json +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/examples/config/sarif-dashboard-parity.toml +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/examples/config/sarif-diff-ci-cd.json +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/examples/config/sarif-diff-ci-cd.toml +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/examples/config/sarif-instance-detail.json +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/examples/config/sarif-instance-detail.toml +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/instructions/gitlab-commit-status/uat.md +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/pytest.ini +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/scripts/build_container.sh +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/scripts/build_container_flexible.sh +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/scripts/deploy-test-docker.sh +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/scripts/deploy-test-pypi.sh +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/scripts/docker-entrypoint.sh +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/scripts/run.sh +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/session.md +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socket.yml +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/core/alert_selection.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/core/classes.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/core/cli_client.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/core/exceptions.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/core/git_interface.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/core/helper/__init__.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/core/helper/socket_facts_loader.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/core/lazy_file_loader.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/core/logging.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/core/messages.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/core/resource_utils.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/core/scm/__init__.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/core/scm/base.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/core/scm/client.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/core/scm/github.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/core/scm/gitlab.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/core/scm_comments.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/core/socket_config.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/core/tools/reachability.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/core/utils.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/fossa_compat.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/output.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/plugins/__init__.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/plugins/base.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/plugins/formatters/__init__.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/plugins/formatters/slack.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/plugins/jira.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/plugins/manager.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/plugins/slack.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/plugins/teams.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/plugins/webhook.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/__init__.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/core/conftest.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/core/create_diff_input.json +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/core/test_diff_alerts.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/core/test_diff_generation.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/core/test_facts_compression.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/core/test_has_manifest_files.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/core/test_package_and_alerts.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/core/test_sdk_methods.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/core/test_supporting_methods.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/data/fullscans/create_response.json +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/data/fullscans/diff/stream_diff.json +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/data/fullscans/diff/stream_diff_full.json +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/data/fullscans/head_scan/metadata.json +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/data/fullscans/head_scan/stream_scan.json +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/data/fullscans/head_scan/stream_scan_full.json +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/data/fullscans/new_scan/metadata.json +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/data/fullscans/new_scan/stream_scan.json +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/data/repos/repo_info_error.json +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/data/repos/repo_info_no_head.json +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/data/repos/repo_info_success.json +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/data/settings/security-policy.json +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/e2e/fixtures/simple-npm/index.js +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/e2e/fixtures/simple-npm/package.json +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/e2e/fixtures/simple-pypi/requirements.txt +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/e2e/validate-gitlab.sh +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/e2e/validate-json.sh +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/e2e/validate-reachability.sh +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/e2e/validate-sarif.sh +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/e2e/validate-scan.sh +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/fixtures/fossa/README.md +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/fixtures/fossa/fossa-analyze-empty.json +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/fixtures/fossa/fossa-analyze-populated.json +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/fixtures/fossa/fossa-sbom-empty-deep.json +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/fixtures/fossa/fossa-sbom-populated.json +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/unit/__init__.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/unit/test_alert_selection.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/unit/test_cli_config.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/unit/test_client.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/unit/test_config.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/unit/test_dependency_overview.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/unit/test_disable_ignore.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/unit/test_fossa_compat.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/unit/test_fossa_parity.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/unit/test_gitlab_auth.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/unit/test_gitlab_auth_fallback.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/unit/test_gitlab_commit_status.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/unit/test_gitlab_format.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/unit/test_ignore_telemetry_filtering.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/unit/test_output.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/unit/test_reachability.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/unit/test_slack_plugin.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/unit/test_socketcli.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/unit/test_tier1_finalize.py +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/workflows/bitbucket-pipelines.yml +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/workflows/buildkite.yml +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/workflows/github-actions.yml +0 -0
- {socketsecurity-2.4.2 → socketsecurity-2.4.4}/workflows/gitlab-ci.yml +0 -0
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.4.4
|
|
4
|
+
|
|
5
|
+
### Changed: Bump required SDK version to `>=3.2.0`
|
|
6
|
+
|
|
7
|
+
- Picks up `socketdev 3.2.0`, which adds `OTHER = "other"` to `SocketCategory`
|
|
8
|
+
so the backend's `other` alert category no longer trips the
|
|
9
|
+
"Unknown SocketCategory" warning fallback (SDK PR #85).
|
|
10
|
+
- No CLI logic changes.
|
|
11
|
+
|
|
12
|
+
## 2.4.3
|
|
13
|
+
|
|
14
|
+
### Added: unified `--exclude-paths` for manifest discovery and reachability
|
|
15
|
+
|
|
16
|
+
- New `--exclude-paths` flag (comma-separated globs) that excludes matching paths from
|
|
17
|
+
BOTH SCA manifest discovery and reachability analysis. Patterns are scan-root-relative
|
|
18
|
+
anchored globs (`*` does not cross `/`, `**` does), matching the Node CLI's behavior.
|
|
19
|
+
- Pattern validation rejects unsupported forms (negation, absolute paths, `..` traversal,
|
|
20
|
+
and match-everything patterns). Patterns may be supplied on the CLI as a comma-separated
|
|
21
|
+
string or via a `--config` file list.
|
|
22
|
+
- `--reach-exclude-paths` is now deprecated in favor of `--exclude-paths`. It still works
|
|
23
|
+
(and is unioned into the Coana `--exclude-dirs` argument) but is marked deprecated in
|
|
24
|
+
`--help` and warns at runtime.
|
|
25
|
+
|
|
3
26
|
## 2.4.2
|
|
4
27
|
|
|
5
28
|
### Added: reachability flag and Coana environment alignment with the Node CLI
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: socketsecurity
|
|
3
|
-
Version: 2.4.
|
|
3
|
+
Version: 2.4.4
|
|
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>
|
|
@@ -43,7 +43,7 @@ Requires-Dist: packaging
|
|
|
43
43
|
Requires-Dist: prettytable
|
|
44
44
|
Requires-Dist: python-dotenv
|
|
45
45
|
Requires-Dist: requests
|
|
46
|
-
Requires-Dist: socketdev<4.0.0,>=3.
|
|
46
|
+
Requires-Dist: socketdev<4.0.0,>=3.2.0
|
|
47
47
|
Provides-Extra: dev
|
|
48
48
|
Requires-Dist: hatch; extra == 'dev'
|
|
49
49
|
Requires-Dist: pre-commit; extra == 'dev'
|
|
@@ -148,14 +148,14 @@ socketcli [-h] [--api-token API_TOKEN] [--repo REPO] [--workspace WORKSPACE] [--
|
|
|
148
148
|
[--owner OWNER] [--pr-number PR_NUMBER] [--commit-message COMMIT_MESSAGE] [--commit-sha COMMIT_SHA] [--committers [COMMITTERS ...]]
|
|
149
149
|
[--target-path TARGET_PATH] [--sbom-file SBOM_FILE] [--license-file-name LICENSE_FILE_NAME] [--save-submitted-files-list SAVE_SUBMITTED_FILES_LIST]
|
|
150
150
|
[--save-manifest-tar SAVE_MANIFEST_TAR] [--files FILES] [--sub-path SUB_PATH] [--workspace-name WORKSPACE_NAME]
|
|
151
|
-
[--excluded-ecosystems EXCLUDED_ECOSYSTEMS] [--default-branch] [--pending-head] [--generate-license] [--enable-debug]
|
|
151
|
+
[--excluded-ecosystems EXCLUDED_ECOSYSTEMS] [--exclude-paths EXCLUDE_PATHS] [--default-branch] [--pending-head] [--generate-license] [--enable-debug]
|
|
152
152
|
[--enable-json] [--enable-sarif] [--sarif-file <path>] [--sarif-scope {diff,full}] [--sarif-grouping {instance,alert}] [--sarif-reachability {all,reachable,potentially,reachable-or-potentially}] [--enable-gitlab-security] [--gitlab-security-file <path>]
|
|
153
153
|
[--disable-overview] [--exclude-license-details] [--allow-unverified] [--disable-security-issue]
|
|
154
154
|
[--ignore-commit-files] [--disable-blocking] [--disable-ignore] [--enable-diff] [--scm SCM] [--timeout TIMEOUT] [--include-module-folders]
|
|
155
|
-
[--reach] [--reach-version REACH_VERSION] [--reach-timeout REACH_ANALYSIS_TIMEOUT]
|
|
156
|
-
[--reach-memory-limit REACH_ANALYSIS_MEMORY_LIMIT] [--reach-
|
|
157
|
-
[--reach-min-severity {low,medium,high,critical}] [--reach-skip-cache] [--reach-disable-analytics] [--reach-
|
|
158
|
-
[--only-facts-file] [--version]
|
|
155
|
+
[--reach] [--reach-version REACH_VERSION] [--reach-analysis-timeout REACH_ANALYSIS_TIMEOUT]
|
|
156
|
+
[--reach-analysis-memory-limit REACH_ANALYSIS_MEMORY_LIMIT] [--reach-concurrency REACH_CONCURRENCY] [--reach-ecosystems REACH_ECOSYSTEMS]
|
|
157
|
+
[--reach-min-severity {low,medium,high,critical}] [--reach-skip-cache] [--reach-disable-analytics] [--reach-debug] [--reach-disable-external-tool-checks]
|
|
158
|
+
[--reach-output-file REACH_OUTPUT_FILE] [--only-facts-file] [--version]
|
|
159
159
|
````
|
|
160
160
|
|
|
161
161
|
If you don't want to provide the Socket API Token every time then you can use the environment variable `SOCKET_SECURITY_API_TOKEN`
|
|
@@ -203,6 +203,7 @@ If you don't want to provide the Socket API Token every time then you can use th
|
|
|
203
203
|
| `--sub-path` | False | | Sub-path within target-path for manifest file scanning (can be specified multiple times). All sub-paths are combined into a single workspace scan while preserving git context from target-path. Must be used with `--workspace-name` |
|
|
204
204
|
| `--workspace-name` | False | | Workspace name suffix to append to repository name (repo-name-workspace_name). Must be used with `--sub-path` |
|
|
205
205
|
| `--excluded-ecosystems` | False | [] | List of ecosystems to exclude from analysis (JSON array string). You can get supported files from the [Supported Files API](https://docs.socket.dev/reference/getsupportedfiles) |
|
|
206
|
+
| `--exclude-paths` | False | | Comma-separated paths/globs to exclude from **both** manifest discovery (every scan) **and** reachability analysis (e.g. `tests/**,packages/legacy,*.spec.ts`). Patterns are scan-root-relative, case-sensitive globs where `*` does not cross `/` and `**` does. Supersedes `--reach-exclude-paths`. |
|
|
206
207
|
|
|
207
208
|
#### Branch and Scan Configuration
|
|
208
209
|
| Parameter | Required | Default | Description |
|
|
@@ -239,16 +240,18 @@ If you don't want to provide the Socket API Token every time then you can use th
|
|
|
239
240
|
|:---------------------------------|:---------|:--------|:---------------------------------------------------------------------------------------------------------------------------|
|
|
240
241
|
| `--reach` | False | False | Enable reachability analysis to identify which vulnerable functions are actually called by your code |
|
|
241
242
|
| `--reach-version` | False | latest | Version of @coana-tech/cli to use for analysis |
|
|
242
|
-
| `--reach-timeout`
|
|
243
|
-
| `--reach-memory-limit`
|
|
244
|
-
| `--reach-concurrency` | False |
|
|
243
|
+
| `--reach-analysis-timeout` | False | *coana* | Timeout in seconds for the reachability analysis. Omitted by default, so coana applies its own (currently 600s). Alias: `--reach-timeout` |
|
|
244
|
+
| `--reach-analysis-memory-limit` | False | *coana* | Memory limit in MB for the reachability analysis. Omitted by default, so coana applies its own (currently 8192). Alias: `--reach-memory-limit` |
|
|
245
|
+
| `--reach-concurrency` | False | *coana* | Control parallel analysis execution (must be >= 1). Omitted by default, so coana applies its own (currently 1) |
|
|
245
246
|
| `--reach-additional-params` | False | | Pass custom parameters to the coana CLI tool |
|
|
246
247
|
| `--reach-ecosystems` | False | | Comma-separated list of ecosystems to analyze (e.g., "npm,pypi"). If not specified, all supported ecosystems are analyzed |
|
|
247
|
-
| `--reach-exclude-paths` | False | | Comma-separated list of file paths or patterns to exclude from reachability analysis |
|
|
248
248
|
| `--reach-min-severity` | False | | Minimum severity level for reporting reachability results (low, medium, high, critical) |
|
|
249
249
|
| `--reach-skip-cache` | False | False | Skip cache and force fresh reachability analysis |
|
|
250
250
|
| `--reach-disable-analytics` | False | False | Disable analytics collection during reachability analysis |
|
|
251
|
+
| `--reach-debug` | False | False | Enable coana debug output (`--debug`) for the analysis, independent of the global `--enable-debug` |
|
|
252
|
+
| `--reach-disable-external-tool-checks` | False | False | Disable coana's external tool availability checks (passes `--disable-external-tool-checks`) |
|
|
251
253
|
| `--reach-output-file` | False | .socket.facts.json | Path where reachability analysis results should be saved |
|
|
254
|
+
| `--reach-exclude-paths` | False | | **[DEPRECATED — use `--exclude-paths`]** Comma-separated paths to exclude from reachability analysis. Still honored (unioned with `--exclude-paths`) but will be hidden in a future release |
|
|
252
255
|
| `--only-facts-file` | False | False | Submit only the .socket.facts.json file to an existing scan (requires --reach and a prior scan) |
|
|
253
256
|
|
|
254
257
|
**Reachability Analysis Requirements:**
|
|
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "socketsecurity"
|
|
9
|
-
version = "2.4.
|
|
9
|
+
version = "2.4.4"
|
|
10
10
|
requires-python = ">= 3.11"
|
|
11
11
|
license = {"file" = "LICENSE"}
|
|
12
12
|
dependencies = [
|
|
@@ -16,7 +16,7 @@ dependencies = [
|
|
|
16
16
|
'GitPython',
|
|
17
17
|
'packaging',
|
|
18
18
|
'python-dotenv',
|
|
19
|
-
"socketdev>=3.
|
|
19
|
+
"socketdev>=3.2.0,<4.0.0",
|
|
20
20
|
"bs4>=0.0.2",
|
|
21
21
|
"markdown>=3.10",
|
|
22
22
|
"brotli>=1.0.9; platform_python_implementation == 'CPython'",
|
|
@@ -55,6 +55,50 @@ def load_cli_config_file(config_path: str) -> dict:
|
|
|
55
55
|
return scoped
|
|
56
56
|
return data
|
|
57
57
|
|
|
58
|
+
def normalize_exclude_paths(value) -> Optional[List[str]]:
|
|
59
|
+
"""Normalize a --exclude-paths value into a clean list of patterns.
|
|
60
|
+
|
|
61
|
+
Accepts a comma-separated string (CLI) or a list/tuple (e.g. a JSON/TOML --config file
|
|
62
|
+
value), so config-file-supplied patterns flow through the same validation as CLI ones.
|
|
63
|
+
"""
|
|
64
|
+
if not value:
|
|
65
|
+
return None
|
|
66
|
+
if isinstance(value, str):
|
|
67
|
+
items = value.split(",")
|
|
68
|
+
elif isinstance(value, (list, tuple)):
|
|
69
|
+
items = value
|
|
70
|
+
else:
|
|
71
|
+
return None
|
|
72
|
+
cleaned = [str(p).strip() for p in items if str(p).strip()]
|
|
73
|
+
return cleaned or None
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def validate_exclude_paths(patterns: List[str]) -> None:
|
|
77
|
+
"""Validate --exclude-paths patterns (mirrors Node's assertValidExcludePaths).
|
|
78
|
+
|
|
79
|
+
Patterns are scan-root-relative globs. Reject the cases coana's --exclude-dirs / fast-glob
|
|
80
|
+
cannot honor: negation, absolute paths, ``..`` traversal, and degenerate match-everything.
|
|
81
|
+
Exits with code 1 on the first invalid pattern.
|
|
82
|
+
"""
|
|
83
|
+
# Degenerate match-everything forms, compared against the trailing-slash-stripped pattern
|
|
84
|
+
# (so "**/" reduces to "**" and is rejected, matching Node's stripTrailingSlash + check).
|
|
85
|
+
degenerate = {"", ".", "**", "./**", "/**"}
|
|
86
|
+
for p in patterns:
|
|
87
|
+
norm = (p or "").strip().replace("\\", "/")
|
|
88
|
+
if norm.startswith("!"):
|
|
89
|
+
logging.error(f"--exclude-paths: negation patterns are not supported: {p!r}")
|
|
90
|
+
exit(1)
|
|
91
|
+
if norm.startswith("/"):
|
|
92
|
+
logging.error(f"--exclude-paths: patterns must be scan-root relative (no leading '/'): {p!r}")
|
|
93
|
+
exit(1)
|
|
94
|
+
if norm == ".." or norm.startswith("../") or "/../" in norm or norm.endswith("/.."):
|
|
95
|
+
logging.error(f"--exclude-paths: '..' path traversal is not allowed: {p!r}")
|
|
96
|
+
exit(1)
|
|
97
|
+
if norm.rstrip("/") in degenerate:
|
|
98
|
+
logging.error(f"--exclude-paths: pattern would exclude everything: {p!r}")
|
|
99
|
+
exit(1)
|
|
100
|
+
|
|
101
|
+
|
|
58
102
|
@dataclass
|
|
59
103
|
class PluginConfig:
|
|
60
104
|
enabled: bool = False
|
|
@@ -106,6 +150,7 @@ class CliConfig:
|
|
|
106
150
|
include_module_folders: bool = False
|
|
107
151
|
repo_is_public: bool = False
|
|
108
152
|
excluded_ecosystems: list[str] = field(default_factory=lambda: [])
|
|
153
|
+
exclude_paths: Optional[List[str]] = None
|
|
109
154
|
version: str = __version__
|
|
110
155
|
jira_plugin: PluginConfig = field(default_factory=PluginConfig)
|
|
111
156
|
slack_plugin: PluginConfig = field(default_factory=PluginConfig)
|
|
@@ -167,6 +212,12 @@ class CliConfig:
|
|
|
167
212
|
|
|
168
213
|
args = parser.parse_args(args_list)
|
|
169
214
|
|
|
215
|
+
if args.reach_exclude_paths:
|
|
216
|
+
logging.warning(
|
|
217
|
+
"--reach-exclude-paths is deprecated; use --exclude-paths instead. "
|
|
218
|
+
"It is still honored and unioned with --exclude-paths."
|
|
219
|
+
)
|
|
220
|
+
|
|
170
221
|
# Get API token from env or args (check multiple env var names)
|
|
171
222
|
api_token = (
|
|
172
223
|
os.getenv("SOCKET_SECURITY_API_KEY") or
|
|
@@ -258,6 +309,7 @@ class CliConfig:
|
|
|
258
309
|
'reach_lazy_mode': args.reach_lazy_mode,
|
|
259
310
|
'reach_ecosystems': args.reach_ecosystems.split(',') if args.reach_ecosystems else None,
|
|
260
311
|
'reach_exclude_paths': args.reach_exclude_paths.split(',') if args.reach_exclude_paths else None,
|
|
312
|
+
'exclude_paths': normalize_exclude_paths(args.exclude_paths),
|
|
261
313
|
'reach_skip_cache': args.reach_skip_cache,
|
|
262
314
|
'reach_min_severity': args.reach_min_severity,
|
|
263
315
|
'reach_output_file': args.reach_output_file,
|
|
@@ -361,6 +413,10 @@ class CliConfig:
|
|
|
361
413
|
logging.error("--sarif-reachability potentially/reachable-or-potentially requires --sarif-scope full")
|
|
362
414
|
exit(1)
|
|
363
415
|
|
|
416
|
+
# Validate --exclude-paths patterns up front (mirrors Node's assertValidExcludePaths).
|
|
417
|
+
if config_args.get("exclude_paths"):
|
|
418
|
+
validate_exclude_paths(config_args["exclude_paths"])
|
|
419
|
+
|
|
364
420
|
# Validate that only_facts_file requires reach
|
|
365
421
|
if args.only_facts_file and not args.reach:
|
|
366
422
|
logging.error("--only-facts-file requires --reach to be specified")
|
|
@@ -570,6 +626,15 @@ def create_argument_parser() -> argparse.ArgumentParser:
|
|
|
570
626
|
help="List of ecosystems to exclude from analysis (JSON array string)"
|
|
571
627
|
)
|
|
572
628
|
|
|
629
|
+
path_group.add_argument(
|
|
630
|
+
"--exclude-paths",
|
|
631
|
+
dest="exclude_paths",
|
|
632
|
+
metavar="<list>",
|
|
633
|
+
help="Comma-separated paths/globs to exclude from BOTH manifest discovery and "
|
|
634
|
+
"reachability analysis (e.g. 'tests/**,packages/legacy,*.spec.ts'). "
|
|
635
|
+
"Supersedes --reach-exclude-paths."
|
|
636
|
+
)
|
|
637
|
+
|
|
573
638
|
# Branch and Scan Configuration
|
|
574
639
|
config_group = parser.add_argument_group('Branch and Scan Configuration')
|
|
575
640
|
config_group.add_argument(
|
|
@@ -919,7 +984,8 @@ def create_argument_parser() -> argparse.ArgumentParser:
|
|
|
919
984
|
"--reach-exclude-paths",
|
|
920
985
|
dest="reach_exclude_paths",
|
|
921
986
|
metavar="<list>",
|
|
922
|
-
help="Paths to exclude from reachability analysis
|
|
987
|
+
help="[DEPRECATED: use --exclude-paths] Paths to exclude from reachability analysis "
|
|
988
|
+
"(comma-separated). Still honored and unioned with --exclude-paths."
|
|
923
989
|
)
|
|
924
990
|
reachability_group.add_argument(
|
|
925
991
|
"--reach-min-severity",
|
|
@@ -213,6 +213,67 @@ class Core:
|
|
|
213
213
|
return True
|
|
214
214
|
return False
|
|
215
215
|
|
|
216
|
+
@staticmethod
|
|
217
|
+
def _exclude_glob_to_regex(pattern: str) -> str:
|
|
218
|
+
"""Translate a micromatch-style glob into an anchored regex string.
|
|
219
|
+
|
|
220
|
+
Mirrors the Node CLI's --exclude-paths matcher (src/commands/scan/exclude-paths.mts):
|
|
221
|
+
patterns are matched against scan-root-relative POSIX paths, case-sensitively, where
|
|
222
|
+
``*`` does NOT cross ``/`` and ``**`` DOES. Patterns are anchored at the scan root, so
|
|
223
|
+
``tests`` matches ``tests`` (not ``src/tests``); use ``**/tests`` to match at any depth.
|
|
224
|
+
"""
|
|
225
|
+
i, n = 0, len(pattern)
|
|
226
|
+
out = ["^"]
|
|
227
|
+
while i < n:
|
|
228
|
+
c = pattern[i]
|
|
229
|
+
if c == "*":
|
|
230
|
+
if i + 1 < n and pattern[i + 1] == "*":
|
|
231
|
+
if i + 2 < n and pattern[i + 2] == "/":
|
|
232
|
+
out.append("(?:[^/]+/)*") # '**/' -> zero or more path segments
|
|
233
|
+
i += 3
|
|
234
|
+
else:
|
|
235
|
+
out.append(".*") # '**' at end / before non-slash -> any, incl '/'
|
|
236
|
+
i += 2
|
|
237
|
+
else:
|
|
238
|
+
out.append("[^/]*") # '*' -> within a single path segment
|
|
239
|
+
i += 1
|
|
240
|
+
elif c == "?":
|
|
241
|
+
out.append("[^/]")
|
|
242
|
+
i += 1
|
|
243
|
+
else:
|
|
244
|
+
out.append(re.escape(c))
|
|
245
|
+
i += 1
|
|
246
|
+
out.append("$")
|
|
247
|
+
return "".join(out)
|
|
248
|
+
|
|
249
|
+
@staticmethod
|
|
250
|
+
def compile_exclude_paths(patterns: Optional[List[str]]) -> List["re.Pattern"]:
|
|
251
|
+
"""Compile --exclude-paths globs into anchored regexes (compiled once per scan).
|
|
252
|
+
|
|
253
|
+
Each pattern ``P`` is expanded the way Node feeds fast-glob's ``ignore``: ``P`` (a file-
|
|
254
|
+
or dir-shaped exact match) plus ``P/**`` (its subtree), unless ``P`` already ends with
|
|
255
|
+
``/**``. Validation of the patterns happens earlier, in CliConfig.from_args.
|
|
256
|
+
"""
|
|
257
|
+
compiled: List["re.Pattern"] = []
|
|
258
|
+
for raw in patterns or []:
|
|
259
|
+
p = (raw or "").strip().replace("\\", "/").rstrip("/")
|
|
260
|
+
if not p:
|
|
261
|
+
continue
|
|
262
|
+
globs = [p] if p.endswith("/**") else [p, f"{p}/**"]
|
|
263
|
+
compiled.extend(re.compile(Core._exclude_glob_to_regex(g)) for g in globs)
|
|
264
|
+
return compiled
|
|
265
|
+
|
|
266
|
+
@staticmethod
|
|
267
|
+
def path_matches_exclude_regexes(rel_path: str, regexes: List["re.Pattern"]) -> bool:
|
|
268
|
+
rp = rel_path.replace(os.sep, "/").replace("\\", "/")
|
|
269
|
+
return any(r.match(rp) for r in regexes)
|
|
270
|
+
|
|
271
|
+
@staticmethod
|
|
272
|
+
def matches_exclude_paths(file_path: str, base_path: str, patterns: List[str]) -> bool:
|
|
273
|
+
"""Convenience matcher (compiles patterns per call); used in tests/ad-hoc checks."""
|
|
274
|
+
rel_path = os.path.relpath(file_path, base_path).replace(os.sep, "/")
|
|
275
|
+
return Core.path_matches_exclude_regexes(rel_path, Core.compile_exclude_paths(patterns))
|
|
276
|
+
|
|
216
277
|
def save_submitted_files_list(self, files: List[str], output_path: str) -> None:
|
|
217
278
|
"""
|
|
218
279
|
Save the list of submitted file names to a JSON file for debugging.
|
|
@@ -336,6 +397,17 @@ class Core:
|
|
|
336
397
|
start_time = time.time()
|
|
337
398
|
files: Set[str] = set()
|
|
338
399
|
|
|
400
|
+
# Unified --exclude-paths: filter discovered manifests by the same paths/globs that are
|
|
401
|
+
# forwarded to coana's --exclude-dirs. Only consulted when the user supplied the flag.
|
|
402
|
+
# Patterns are anchored to `path` (the scan root this pass walks), matching coana's
|
|
403
|
+
# target and the Node CLI's fast-glob cwd. NOTE: when scanning multiple --sub-path
|
|
404
|
+
# targets, find_files runs once per sub-path, so a pattern like `tests` anchors to each
|
|
405
|
+
# sub-path independently (Node anchors all patterns to a single scan-root cwd). This only
|
|
406
|
+
# differs for the multi-target full-scan + --exclude-paths combo; the reach flow is
|
|
407
|
+
# single-target, so it matches Node there.
|
|
408
|
+
exclude_paths = getattr(self.cli_config, "exclude_paths", None) if self.cli_config else None
|
|
409
|
+
exclude_regexes = Core.compile_exclude_paths(exclude_paths) if exclude_paths else []
|
|
410
|
+
|
|
339
411
|
# Get supported patterns from the API
|
|
340
412
|
patterns = self.get_supported_patterns()
|
|
341
413
|
|
|
@@ -365,8 +437,15 @@ class Core:
|
|
|
365
437
|
|
|
366
438
|
for glob_file in glob_files:
|
|
367
439
|
glob_file_str = str(glob_file)
|
|
368
|
-
if os.path.isfile(glob_file_str)
|
|
369
|
-
|
|
440
|
+
if not os.path.isfile(glob_file_str):
|
|
441
|
+
continue
|
|
442
|
+
if Core.is_excluded(glob_file_str, self.config.excluded_dirs):
|
|
443
|
+
continue
|
|
444
|
+
if exclude_regexes:
|
|
445
|
+
rel = os.path.relpath(glob_file_str, path)
|
|
446
|
+
if Core.path_matches_exclude_regexes(rel, exclude_regexes):
|
|
447
|
+
continue
|
|
448
|
+
files.add(glob_file_str.replace("\\", "/"))
|
|
370
449
|
|
|
371
450
|
glob_end = time.time()
|
|
372
451
|
log.debug(f"Globbing took {glob_end - glob_start:.4f} seconds")
|
|
@@ -388,7 +388,15 @@ def main_code():
|
|
|
388
388
|
timeout=config.reach_analysis_timeout,
|
|
389
389
|
memory_limit=config.reach_analysis_memory_limit,
|
|
390
390
|
ecosystems=config.reach_ecosystems,
|
|
391
|
-
|
|
391
|
+
# Union the deprecated --reach-exclude-paths with the unified --exclude-paths
|
|
392
|
+
# and forward verbatim to coana's --exclude-dirs. Patterns are scan-root
|
|
393
|
+
# relative; coana resolves --exclude-dirs relative to its `run` target, which
|
|
394
|
+
# here is `.` == cwd == scan root, so passthrough is correct. If a nested
|
|
395
|
+
# target is ever supported, re-anchor patterns to the target first (see Node's
|
|
396
|
+
# pathRelativeToTarget in exclude-paths.mts).
|
|
397
|
+
exclude_paths=(
|
|
398
|
+
(config.reach_exclude_paths or []) + (config.exclude_paths or [])
|
|
399
|
+
) or None,
|
|
392
400
|
min_severity=config.reach_min_severity,
|
|
393
401
|
skip_cache=config.reach_skip_cache or False,
|
|
394
402
|
disable_analytics=config.reach_disable_analytics or False,
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"""Tests for the unified --exclude-paths flag (G2, Node alignment).
|
|
2
|
+
|
|
3
|
+
Covers the path matcher, config parsing + soft-deprecation of --reach-exclude-paths,
|
|
4
|
+
and that --exclude-paths filters SCA manifest discovery via Core.find_files.
|
|
5
|
+
"""
|
|
6
|
+
import logging
|
|
7
|
+
import types
|
|
8
|
+
from unittest.mock import MagicMock
|
|
9
|
+
|
|
10
|
+
import pytest
|
|
11
|
+
|
|
12
|
+
from socketsecurity.config import CliConfig
|
|
13
|
+
from socketsecurity.core import Core
|
|
14
|
+
from socketsecurity.core.socket_config import SocketConfig
|
|
15
|
+
|
|
16
|
+
# ---- matcher -------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
@pytest.mark.parametrize(
|
|
19
|
+
"rel, patterns, expected",
|
|
20
|
+
[
|
|
21
|
+
# directory prefix -> the directory's whole subtree
|
|
22
|
+
("packages/legacy/package.json", ["packages/legacy"], True),
|
|
23
|
+
("packages/keep/package.json", ["packages/legacy"], False),
|
|
24
|
+
# root-anchored: a bare name matches at the root only, NOT nested
|
|
25
|
+
("tests/x.json", ["tests"], True),
|
|
26
|
+
("src/tests/x.json", ["tests"], False),
|
|
27
|
+
# **/ matches at any depth
|
|
28
|
+
("src/tests/x.json", ["**/tests"], True),
|
|
29
|
+
("tests/unit/x.json", ["tests/**"], True),
|
|
30
|
+
("tests", ["tests/**"], False), # P/** is the subtree, not P itself
|
|
31
|
+
# '*' does NOT cross '/': anchored basename glob is root-level only
|
|
32
|
+
("index.spec.ts", ["*.spec.ts"], True),
|
|
33
|
+
("src/app/index.spec.ts", ["*.spec.ts"], False),
|
|
34
|
+
("src/app/index.spec.ts", ["**/*.spec.ts"], True),
|
|
35
|
+
("src/app/index.ts", ["**/*.spec.ts"], False),
|
|
36
|
+
# single-star matches exactly one path segment
|
|
37
|
+
("packages/a/node_modules/x.json", ["packages/*/node_modules"], True),
|
|
38
|
+
("packages/a/b/node_modules/x.json", ["packages/*/node_modules"], False),
|
|
39
|
+
],
|
|
40
|
+
)
|
|
41
|
+
def test_matches_exclude_paths(rel, patterns, expected):
|
|
42
|
+
assert Core.matches_exclude_paths(rel, ".", patterns) is expected
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@pytest.mark.parametrize(
|
|
46
|
+
"pattern, excluded, kept",
|
|
47
|
+
[
|
|
48
|
+
# Node parity cases (src/commands/scan/exclude-paths.mts), anchored at scan root.
|
|
49
|
+
("tests", "tests/pkg/package.json", "src/tests/package.json"),
|
|
50
|
+
("package-lock.json", "package-lock.json", "packages/a/package-lock.json"),
|
|
51
|
+
("**/node_modules", "packages/a/node_modules/dep/package.json", "src/app/package.json"),
|
|
52
|
+
("packages/legacy", "packages/legacy/p.json", "packages/legacy-x/p.json"),
|
|
53
|
+
("src/*.json", "src/a.json", "src/sub/a.json"),
|
|
54
|
+
],
|
|
55
|
+
)
|
|
56
|
+
def test_matches_exclude_paths_node_parity(pattern, excluded, kept):
|
|
57
|
+
assert Core.matches_exclude_paths(excluded, ".", [pattern]) is True
|
|
58
|
+
assert Core.matches_exclude_paths(kept, ".", [pattern]) is False
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def test_matches_exclude_paths_empty_is_false():
|
|
62
|
+
assert Core.matches_exclude_paths("a/b.json", ".", []) is False
|
|
63
|
+
assert Core.matches_exclude_paths("a/b.json", ".", [" "]) is False
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
# ---- config parsing ------------------------------------------------------
|
|
67
|
+
|
|
68
|
+
BASE_ARGS = ["--api-token", "test-token", "--repo", "test-repo"]
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def test_exclude_paths_parses_to_list():
|
|
72
|
+
config = CliConfig.from_args(BASE_ARGS + ["--exclude-paths", "tests/**, packages/legacy , *.spec.ts"])
|
|
73
|
+
assert config.exclude_paths == ["tests/**", "packages/legacy", "*.spec.ts"]
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def test_exclude_paths_defaults_none():
|
|
77
|
+
config = CliConfig.from_args(BASE_ARGS)
|
|
78
|
+
assert config.exclude_paths is None
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def test_reach_exclude_paths_still_works_and_warns(caplog):
|
|
82
|
+
with caplog.at_level(logging.WARNING):
|
|
83
|
+
config = CliConfig.from_args(BASE_ARGS + ["--reach", "--reach-exclude-paths", "a,b"])
|
|
84
|
+
assert config.reach_exclude_paths == ["a", "b"]
|
|
85
|
+
assert any("deprecated" in r.message for r in caplog.records)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@pytest.mark.parametrize(
|
|
89
|
+
"bad",
|
|
90
|
+
["!foo", "/abs/path", "..", "../escape", "a/../b", ".", "**", "**/", "/**", "./", "./**"],
|
|
91
|
+
)
|
|
92
|
+
def test_exclude_paths_validation_rejects(bad):
|
|
93
|
+
with pytest.raises(SystemExit) as exc:
|
|
94
|
+
CliConfig.from_args(BASE_ARGS + ["--exclude-paths", bad])
|
|
95
|
+
assert exc.value.code == 1
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def test_exclude_paths_validation_rejects_within_csv():
|
|
99
|
+
with pytest.raises(SystemExit) as exc:
|
|
100
|
+
CliConfig.from_args(BASE_ARGS + ["--exclude-paths", "src,..,tests"])
|
|
101
|
+
assert exc.value.code == 1
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _write_config(tmp_path, value):
|
|
105
|
+
import json
|
|
106
|
+
path = tmp_path / "socketcli.json"
|
|
107
|
+
path.write_text(json.dumps({"socketcli": {"exclude_paths": value}}), encoding="utf-8")
|
|
108
|
+
return str(path)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def test_exclude_paths_from_config_file_list(tmp_path):
|
|
112
|
+
"""A JSON list in --config flows through normalization (not just CSV strings)."""
|
|
113
|
+
cfg = _write_config(tmp_path, ["tests/**", "packages/legacy"])
|
|
114
|
+
config = CliConfig.from_args(BASE_ARGS + ["--config", cfg])
|
|
115
|
+
assert config.exclude_paths == ["tests/**", "packages/legacy"]
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def test_exclude_paths_from_config_file_string(tmp_path):
|
|
119
|
+
cfg = _write_config(tmp_path, "tests/**, packages/legacy")
|
|
120
|
+
config = CliConfig.from_args(BASE_ARGS + ["--config", cfg])
|
|
121
|
+
assert config.exclude_paths == ["tests/**", "packages/legacy"]
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def test_exclude_paths_from_config_file_is_validated(tmp_path):
|
|
125
|
+
"""Config-file patterns are validated too (not bypassed)."""
|
|
126
|
+
cfg = _write_config(tmp_path, ["../escape"])
|
|
127
|
+
with pytest.raises(SystemExit) as exc:
|
|
128
|
+
CliConfig.from_args(BASE_ARGS + ["--config", cfg])
|
|
129
|
+
assert exc.value.code == 1
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def test_exclude_paths_valid_globs_accepted():
|
|
133
|
+
config = CliConfig.from_args(BASE_ARGS + ["--exclude-paths", "tests/**,**/*.spec.ts,packages/legacy"])
|
|
134
|
+
assert config.exclude_paths == ["tests/**", "**/*.spec.ts", "packages/legacy"]
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
# ---- find_files integration ---------------------------------------------
|
|
138
|
+
|
|
139
|
+
def _make_core(exclude_paths):
|
|
140
|
+
core = Core.__new__(Core)
|
|
141
|
+
core.config = SocketConfig(api_key="test-key")
|
|
142
|
+
core.cli_config = types.SimpleNamespace(exclude_paths=exclude_paths)
|
|
143
|
+
core.sdk = MagicMock()
|
|
144
|
+
return core
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def _seed_manifests(tmp_path):
|
|
148
|
+
for rel in ("package.json", "sub/package.json", "legacy/package.json"):
|
|
149
|
+
p = tmp_path / rel
|
|
150
|
+
p.parent.mkdir(parents=True, exist_ok=True)
|
|
151
|
+
p.write_text("{}", encoding="utf-8")
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def test_find_files_excludes_matching_paths(tmp_path, mocker):
|
|
155
|
+
_seed_manifests(tmp_path)
|
|
156
|
+
core = _make_core(["legacy"])
|
|
157
|
+
mocker.patch.object(
|
|
158
|
+
core, "get_supported_patterns",
|
|
159
|
+
return_value={"npm": {"package.json": {"pattern": "package.json"}}},
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
found = core.find_files(str(tmp_path))
|
|
163
|
+
assert any(f.endswith("/package.json") and "/legacy/" not in f for f in found)
|
|
164
|
+
assert not any("/legacy/" in f for f in found)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def test_find_files_no_exclude_paths_keeps_all(tmp_path, mocker):
|
|
168
|
+
_seed_manifests(tmp_path)
|
|
169
|
+
core = _make_core(None)
|
|
170
|
+
mocker.patch.object(
|
|
171
|
+
core, "get_supported_patterns",
|
|
172
|
+
return_value={"npm": {"package.json": {"pattern": "package.json"}}},
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
found = core.find_files(str(tmp_path))
|
|
176
|
+
assert any("/legacy/" in f for f in found)
|
|
177
|
+
assert len(found) == 3
|
|
@@ -1257,20 +1257,20 @@ wheels = [
|
|
|
1257
1257
|
|
|
1258
1258
|
[[package]]
|
|
1259
1259
|
name = "socketdev"
|
|
1260
|
-
version = "3.
|
|
1260
|
+
version = "3.2.0"
|
|
1261
1261
|
source = { registry = "https://pypi.org/simple" }
|
|
1262
1262
|
dependencies = [
|
|
1263
1263
|
{ name = "requests" },
|
|
1264
1264
|
{ name = "typing-extensions" },
|
|
1265
1265
|
]
|
|
1266
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
1266
|
+
sdist = { url = "https://files.pythonhosted.org/packages/00/05/0748d1a357a743f968475aecfad4d53ce109ae65fc418d177faecbb25754/socketdev-3.2.0.tar.gz", hash = "sha256:d8743e1a83135f17e8713539c656b4847ada1450315b05e48ec8df1ed984c307", size = 178440, upload-time = "2026-06-03T02:47:26.696Z" }
|
|
1267
1267
|
wheels = [
|
|
1268
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1268
|
+
{ url = "https://files.pythonhosted.org/packages/f2/b5/6a3b2bcec759d5d306f416e1b167b985f44f89e990afcd25569a2e591ffd/socketdev-3.2.0-py3-none-any.whl", hash = "sha256:e4b97bdc22ec8e12899f218c8089eaa8e9696f7556930e13f05996ad210718af", size = 67267, upload-time = "2026-06-03T02:47:24.76Z" },
|
|
1269
1269
|
]
|
|
1270
1270
|
|
|
1271
1271
|
[[package]]
|
|
1272
1272
|
name = "socketsecurity"
|
|
1273
|
-
version = "2.4.
|
|
1273
|
+
version = "2.4.4"
|
|
1274
1274
|
source = { editable = "." }
|
|
1275
1275
|
dependencies = [
|
|
1276
1276
|
{ name = "brotli", marker = "platform_python_implementation == 'CPython'" },
|
|
@@ -1327,7 +1327,7 @@ requires-dist = [
|
|
|
1327
1327
|
{ name = "python-dotenv" },
|
|
1328
1328
|
{ name = "requests" },
|
|
1329
1329
|
{ name = "ruff", marker = "extra == 'dev'", specifier = ">=0.3.0" },
|
|
1330
|
-
{ name = "socketdev", specifier = ">=3.
|
|
1330
|
+
{ name = "socketdev", specifier = ">=3.2.0,<4.0.0" },
|
|
1331
1331
|
{ name = "twine", marker = "extra == 'dev'" },
|
|
1332
1332
|
{ name = "uv", marker = "extra == 'dev'", specifier = ">=0.1.0" },
|
|
1333
1333
|
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{socketsecurity-2.4.2 → socketsecurity-2.4.4}/socketsecurity/core/helper/socket_facts_loader.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/data/fullscans/diff/stream_diff_full.json
RENAMED
|
File without changes
|
|
File without changes
|
{socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/data/fullscans/head_scan/stream_scan.json
RENAMED
|
File without changes
|
{socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/data/fullscans/head_scan/stream_scan_full.json
RENAMED
|
File without changes
|
|
File without changes
|
{socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/data/fullscans/new_scan/stream_scan.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/e2e/fixtures/simple-pypi/requirements.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/fixtures/fossa/fossa-analyze-populated.json
RENAMED
|
File without changes
|
{socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/fixtures/fossa/fossa-sbom-empty-deep.json
RENAMED
|
File without changes
|
{socketsecurity-2.4.2 → socketsecurity-2.4.4}/tests/fixtures/fossa/fossa-sbom-populated.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|