socketsecurity 2.2.38__tar.gz → 2.2.43__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.2.38 → socketsecurity-2.2.43}/PKG-INFO +34 -3
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/README.md +32 -1
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/pyproject.toml +7 -2
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/__init__.py +1 -1
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/core/__init__.py +85 -23
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/core/messages.py +3 -3
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/core/socket_config.py +0 -8
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/socketcli.py +3 -7
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/core/conftest.py +1 -11
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/core/test_package_and_alerts.py +2 -31
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/unit/test_config.py +1 -12
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/uv.lock +13 -9
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/.github/CODEOWNERS +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/.github/PULL_REQUEST_TEMPLATE/bug-fix.md +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/.github/PULL_REQUEST_TEMPLATE/feature.md +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/.github/PULL_REQUEST_TEMPLATE/improvement.md +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/.github/workflows/docker-stable.yml +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/.github/workflows/pr-preview.yml +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/.github/workflows/release.yml +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/.github/workflows/version-check.yml +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/.gitignore +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/.hooks/sync_version.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/.pre-commit-config.yaml +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/.python-version +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/Dockerfile +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/LICENSE +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/Makefile +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/docs/README.md +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/pytest.ini +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/scripts/build_container.sh +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/scripts/build_container_flexible.sh +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/scripts/deploy-test-docker.sh +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/scripts/deploy-test-pypi.sh +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/scripts/docker-entrypoint.sh +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/scripts/run.sh +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/config.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/core/classes.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/core/cli_client.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/core/exceptions.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/core/git_interface.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/core/helper/__init__.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/core/lazy_file_loader.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/core/logging.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/core/resource_utils.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/core/scm/__init__.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/core/scm/base.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/core/scm/client.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/core/scm/github.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/core/scm/gitlab.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/core/scm_comments.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/core/tools/reachability.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/core/utils.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/output.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/plugins/__init__.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/plugins/base.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/plugins/jira.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/plugins/manager.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/plugins/slack.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/plugins/teams.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/socketsecurity/plugins/webhook.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/__init__.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/core/create_diff_input.json +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/core/test_diff_generation.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/core/test_sdk_methods.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/core/test_supporting_methods.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/data/fullscans/create_response.json +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/data/fullscans/diff/stream_diff.json +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/data/fullscans/diff/stream_diff_full.json +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/data/fullscans/head_scan/metadata.json +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/data/fullscans/head_scan/stream_scan.json +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/data/fullscans/head_scan/stream_scan_full.json +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/data/fullscans/new_scan/metadata.json +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/data/fullscans/new_scan/stream_scan.json +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/data/repos/repo_info_error.json +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/data/repos/repo_info_no_head.json +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/data/repos/repo_info_success.json +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/data/settings/security-policy.json +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/unit/__init__.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/unit/test_cli_config.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/unit/test_client.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/unit/test_gitlab_auth.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/unit/test_gitlab_auth_fallback.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/unit/test_output.py +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/workflows/bitbucket-pipelines.yml +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/workflows/github-actions.yml +0 -0
- {socketsecurity-2.2.38 → socketsecurity-2.2.43}/workflows/gitlab-ci.yml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: socketsecurity
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.43
|
|
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>
|
|
@@ -40,7 +40,7 @@ Requires-Dist: packaging
|
|
|
40
40
|
Requires-Dist: prettytable
|
|
41
41
|
Requires-Dist: python-dotenv
|
|
42
42
|
Requires-Dist: requests
|
|
43
|
-
Requires-Dist: socketdev<4.0.0,>=3.0.
|
|
43
|
+
Requires-Dist: socketdev<4.0.0,>=3.0.21
|
|
44
44
|
Provides-Extra: dev
|
|
45
45
|
Requires-Dist: hatch; extra == 'dev'
|
|
46
46
|
Requires-Dist: pre-commit; extra == 'dev'
|
|
@@ -57,7 +57,7 @@ Description-Content-Type: text/markdown
|
|
|
57
57
|
|
|
58
58
|
# Socket Security CLI
|
|
59
59
|
|
|
60
|
-
The Socket Security CLI was created to enable integrations with other tools like GitHub Actions, GitLab, BitBucket, local use cases and more. The tool will get the head scan for the provided repo from Socket, create a new one, and then report any new alerts detected. If there are new alerts
|
|
60
|
+
The Socket Security CLI was created to enable integrations with other tools like GitHub Actions, GitLab, BitBucket, local use cases and more. The tool will get the head scan for the provided repo from Socket, create a new one, and then report any new alerts detected. If there are new alerts with blocking actions it'll exit with a non-Zero exit code.
|
|
61
61
|
|
|
62
62
|
## Quick Start
|
|
63
63
|
|
|
@@ -553,3 +553,34 @@ Implementation targets:
|
|
|
553
553
|
#### GitLab Integration
|
|
554
554
|
- `GITLAB_TOKEN`: GitLab API token for GitLab integration (supports both Bearer and PRIVATE-TOKEN authentication)
|
|
555
555
|
- `CI_JOB_TOKEN`: GitLab CI job token (automatically provided in GitLab CI environments)
|
|
556
|
+
|
|
557
|
+
### Manual Development Environment Setup
|
|
558
|
+
|
|
559
|
+
For manual setup without using the Make targets, follow these steps:
|
|
560
|
+
|
|
561
|
+
1. **Create a virtual environment:**
|
|
562
|
+
```bash
|
|
563
|
+
python -m venv .venv
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
2. **Activate the virtual environment:**
|
|
567
|
+
```bash
|
|
568
|
+
source .venv/bin/activate
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
3. **Sync dependencies with uv:**
|
|
572
|
+
```bash
|
|
573
|
+
uv sync
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
4. **Install pre-commit:**
|
|
577
|
+
```bash
|
|
578
|
+
uv add --dev pre-commit
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
5. **Register the pre-commit hook:**
|
|
582
|
+
```bash
|
|
583
|
+
pre-commit install
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
> **Note**: This manual setup is an alternative to the streamlined Make targets described above. For most development workflows, using `make first-time-setup` or `make first-time-local-setup` is recommended.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Socket Security CLI
|
|
2
2
|
|
|
3
|
-
The Socket Security CLI was created to enable integrations with other tools like GitHub Actions, GitLab, BitBucket, local use cases and more. The tool will get the head scan for the provided repo from Socket, create a new one, and then report any new alerts detected. If there are new alerts
|
|
3
|
+
The Socket Security CLI was created to enable integrations with other tools like GitHub Actions, GitLab, BitBucket, local use cases and more. The tool will get the head scan for the provided repo from Socket, create a new one, and then report any new alerts detected. If there are new alerts with blocking actions it'll exit with a non-Zero exit code.
|
|
4
4
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
@@ -496,3 +496,34 @@ Implementation targets:
|
|
|
496
496
|
#### GitLab Integration
|
|
497
497
|
- `GITLAB_TOKEN`: GitLab API token for GitLab integration (supports both Bearer and PRIVATE-TOKEN authentication)
|
|
498
498
|
- `CI_JOB_TOKEN`: GitLab CI job token (automatically provided in GitLab CI environments)
|
|
499
|
+
|
|
500
|
+
### Manual Development Environment Setup
|
|
501
|
+
|
|
502
|
+
For manual setup without using the Make targets, follow these steps:
|
|
503
|
+
|
|
504
|
+
1. **Create a virtual environment:**
|
|
505
|
+
```bash
|
|
506
|
+
python -m venv .venv
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
2. **Activate the virtual environment:**
|
|
510
|
+
```bash
|
|
511
|
+
source .venv/bin/activate
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
3. **Sync dependencies with uv:**
|
|
515
|
+
```bash
|
|
516
|
+
uv sync
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
4. **Install pre-commit:**
|
|
520
|
+
```bash
|
|
521
|
+
uv add --dev pre-commit
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
5. **Register the pre-commit hook:**
|
|
525
|
+
```bash
|
|
526
|
+
pre-commit install
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
> **Note**: This manual setup is an alternative to the streamlined Make targets described above. For most development workflows, using `make first-time-setup` or `make first-time-local-setup` is recommended.
|
|
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "socketsecurity"
|
|
9
|
-
version = "2.2.
|
|
9
|
+
version = "2.2.43"
|
|
10
10
|
requires-python = ">= 3.10"
|
|
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.0.
|
|
19
|
+
'socketdev>=3.0.21,<4.0.0',
|
|
20
20
|
"bs4>=0.0.2",
|
|
21
21
|
]
|
|
22
22
|
readme = "README.md"
|
|
@@ -160,3 +160,8 @@ docstring-code-line-length = "dynamic"
|
|
|
160
160
|
|
|
161
161
|
[tool.hatch.build.targets.wheel]
|
|
162
162
|
include = ["socketsecurity", "LICENSE"]
|
|
163
|
+
|
|
164
|
+
[dependency-groups]
|
|
165
|
+
dev = [
|
|
166
|
+
"pre-commit>=4.3.0",
|
|
167
|
+
]
|
|
@@ -10,13 +10,15 @@ from dataclasses import asdict
|
|
|
10
10
|
from glob import glob
|
|
11
11
|
from io import BytesIO
|
|
12
12
|
from pathlib import PurePath
|
|
13
|
-
from typing import BinaryIO, Dict, List, Tuple, Set, Union
|
|
13
|
+
from typing import BinaryIO, Dict, List, Tuple, Set, Union, TYPE_CHECKING, Optional
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from socketsecurity.config import CliConfig
|
|
14
17
|
from socketdev import socketdev
|
|
15
18
|
from socketdev.exceptions import APIFailure
|
|
16
19
|
from socketdev.fullscans import FullScanParams, SocketArtifact
|
|
17
20
|
from socketdev.org import Organization
|
|
18
21
|
from socketdev.repos import RepositoryInfo
|
|
19
|
-
from socketdev.settings import SecurityPolicyRule
|
|
20
22
|
import copy
|
|
21
23
|
from socketsecurity import __version__, USER_AGENT
|
|
22
24
|
from socketsecurity.core.classes import (
|
|
@@ -59,11 +61,13 @@ class Core:
|
|
|
59
61
|
|
|
60
62
|
config: SocketConfig
|
|
61
63
|
sdk: socketdev
|
|
64
|
+
cli_config: Optional['CliConfig']
|
|
62
65
|
|
|
63
|
-
def __init__(self, config: SocketConfig, sdk: socketdev) -> None:
|
|
66
|
+
def __init__(self, config: SocketConfig, sdk: socketdev, cli_config: Optional['CliConfig'] = None) -> None:
|
|
64
67
|
"""Initialize Core with configuration and SDK instance."""
|
|
65
68
|
self.config = config
|
|
66
69
|
self.sdk = sdk
|
|
70
|
+
self.cli_config = cli_config
|
|
67
71
|
self.set_org_vars()
|
|
68
72
|
|
|
69
73
|
def set_org_vars(self) -> None:
|
|
@@ -77,8 +81,6 @@ class Core:
|
|
|
77
81
|
self.config.full_scan_path = f"{base_path}/full-scans"
|
|
78
82
|
self.config.repository_path = f"{base_path}/repos"
|
|
79
83
|
|
|
80
|
-
self.config.security_policy = self.get_security_policy()
|
|
81
|
-
|
|
82
84
|
def get_org_id_slug(self) -> Tuple[str, str]:
|
|
83
85
|
"""Gets the Org ID and Org Slug for the API Token."""
|
|
84
86
|
response = self.sdk.org.get(use_types=True)
|
|
@@ -107,16 +109,7 @@ class Core:
|
|
|
107
109
|
"""Converts artifacts dictionary to a list."""
|
|
108
110
|
return list(artifacts_dict.values())
|
|
109
111
|
|
|
110
|
-
def get_security_policy(self) -> Dict[str, SecurityPolicyRule]:
|
|
111
|
-
"""Gets the organization's security policy."""
|
|
112
|
-
response = self.sdk.settings.get(self.config.org_slug, use_types=True)
|
|
113
|
-
|
|
114
|
-
if not response.success:
|
|
115
|
-
log.error(f"Failed to get security policy: {response.status}")
|
|
116
|
-
log.error(response.message)
|
|
117
|
-
raise Exception(f"Failed to get security policy: {response.status}, message: {response.message}")
|
|
118
112
|
|
|
119
|
-
return response.securityPolicyRules
|
|
120
113
|
|
|
121
114
|
def create_sbom_output(self, diff: Diff) -> dict:
|
|
122
115
|
"""Creates CycloneDX output for a given diff."""
|
|
@@ -453,7 +446,61 @@ class Core:
|
|
|
453
446
|
log.debug(f"Created temporary empty file for baseline scan: {temp_path}")
|
|
454
447
|
return [temp_path]
|
|
455
448
|
|
|
456
|
-
def
|
|
449
|
+
def finalize_tier1_scan(self, full_scan_id: str, facts_file_path: str) -> bool:
|
|
450
|
+
"""
|
|
451
|
+
Finalize a tier 1 reachability scan by associating it with a full scan.
|
|
452
|
+
|
|
453
|
+
This function reads the tier1ReachabilityScanId from the facts file and
|
|
454
|
+
calls the SDK to link it with the specified full scan.
|
|
455
|
+
|
|
456
|
+
Linking the tier 1 scan to the full scan helps the Socket team debug potential issues.
|
|
457
|
+
|
|
458
|
+
Args:
|
|
459
|
+
full_scan_id: The ID of the full scan to associate with the tier 1 scan
|
|
460
|
+
facts_file_path: Path to the .socket.facts.json file containing the tier1ReachabilityScanId
|
|
461
|
+
|
|
462
|
+
Returns:
|
|
463
|
+
True if successful, False otherwise
|
|
464
|
+
"""
|
|
465
|
+
log.debug(f"Finalizing tier 1 scan for full scan {full_scan_id}")
|
|
466
|
+
|
|
467
|
+
# Read the tier1ReachabilityScanId from the facts file
|
|
468
|
+
try:
|
|
469
|
+
if not os.path.exists(facts_file_path):
|
|
470
|
+
log.debug(f"Facts file not found: {facts_file_path}")
|
|
471
|
+
return False
|
|
472
|
+
|
|
473
|
+
with open(facts_file_path, 'r') as f:
|
|
474
|
+
facts = json.load(f)
|
|
475
|
+
|
|
476
|
+
tier1_scan_id = facts.get('tier1ReachabilityScanId')
|
|
477
|
+
if not tier1_scan_id:
|
|
478
|
+
log.debug(f"No tier1ReachabilityScanId found in {facts_file_path}")
|
|
479
|
+
return False
|
|
480
|
+
|
|
481
|
+
tier1_scan_id = tier1_scan_id.strip()
|
|
482
|
+
log.debug(f"Found tier1ReachabilityScanId: {tier1_scan_id}")
|
|
483
|
+
|
|
484
|
+
except (json.JSONDecodeError, IOError) as e:
|
|
485
|
+
log.debug(f"Failed to read tier1ReachabilityScanId from {facts_file_path}: {e}")
|
|
486
|
+
return False
|
|
487
|
+
|
|
488
|
+
# Call the SDK to finalize the tier 1 scan
|
|
489
|
+
try:
|
|
490
|
+
success = self.sdk.fullscans.finalize_tier1(
|
|
491
|
+
full_scan_id=full_scan_id,
|
|
492
|
+
tier1_reachability_scan_id=tier1_scan_id,
|
|
493
|
+
)
|
|
494
|
+
|
|
495
|
+
if success:
|
|
496
|
+
log.debug(f"Successfully finalized tier 1 scan {tier1_scan_id} for full scan {full_scan_id}")
|
|
497
|
+
return success
|
|
498
|
+
|
|
499
|
+
except Exception as e:
|
|
500
|
+
log.debug(f"Unable to finalize tier 1 scan: {e}")
|
|
501
|
+
return False
|
|
502
|
+
|
|
503
|
+
def create_full_scan(self, files: List[str], params: FullScanParams, base_paths: Optional[List[str]] = None) -> FullScan:
|
|
457
504
|
"""
|
|
458
505
|
Creates a new full scan via the Socket API.
|
|
459
506
|
|
|
@@ -478,6 +525,19 @@ class Core:
|
|
|
478
525
|
total_time = create_full_end - create_full_start
|
|
479
526
|
log.debug(f"New Full Scan created in {total_time:.2f} seconds")
|
|
480
527
|
|
|
528
|
+
# Finalize tier1 scan if reachability analysis was enabled
|
|
529
|
+
if self.cli_config and self.cli_config.reach:
|
|
530
|
+
facts_file_path = self.cli_config.reach_output_file or ".socket.facts.json"
|
|
531
|
+
log.debug(f"Reachability analysis enabled, finalizing tier1 scan for full scan {full_scan.id}")
|
|
532
|
+
try:
|
|
533
|
+
success = self.finalize_tier1_scan(full_scan.id, facts_file_path)
|
|
534
|
+
if success:
|
|
535
|
+
log.debug(f"Successfully finalized tier1 scan for full scan {full_scan.id}")
|
|
536
|
+
else:
|
|
537
|
+
log.debug(f"Failed to finalize tier1 scan for full scan {full_scan.id}")
|
|
538
|
+
except Exception as e:
|
|
539
|
+
log.warning(f"Error finalizing tier1 scan for full scan {full_scan.id}: {e}")
|
|
540
|
+
|
|
481
541
|
return full_scan
|
|
482
542
|
|
|
483
543
|
def create_full_scan_with_report_url(
|
|
@@ -485,9 +545,9 @@ class Core:
|
|
|
485
545
|
paths: List[str],
|
|
486
546
|
params: FullScanParams,
|
|
487
547
|
no_change: bool = False,
|
|
488
|
-
save_files_list_path: str = None,
|
|
489
|
-
save_manifest_tar_path: str = None,
|
|
490
|
-
base_paths: List[str] = None
|
|
548
|
+
save_files_list_path: Optional[str] = None,
|
|
549
|
+
save_manifest_tar_path: Optional[str] = None,
|
|
550
|
+
base_paths: Optional[List[str]] = None
|
|
491
551
|
) -> Diff:
|
|
492
552
|
"""Create a new full scan and return with html_report_url.
|
|
493
553
|
|
|
@@ -881,9 +941,9 @@ class Core:
|
|
|
881
941
|
paths: List[str],
|
|
882
942
|
params: FullScanParams,
|
|
883
943
|
no_change: bool = False,
|
|
884
|
-
save_files_list_path: str = None,
|
|
885
|
-
save_manifest_tar_path: str = None,
|
|
886
|
-
base_paths: List[str] = None
|
|
944
|
+
save_files_list_path: Optional[str] = None,
|
|
945
|
+
save_manifest_tar_path: Optional[str] = None,
|
|
946
|
+
base_paths: Optional[List[str]] = None
|
|
887
947
|
) -> Diff:
|
|
888
948
|
"""Create a new diff using the Socket SDK.
|
|
889
949
|
|
|
@@ -1130,6 +1190,7 @@ class Core:
|
|
|
1130
1190
|
)
|
|
1131
1191
|
return purl
|
|
1132
1192
|
|
|
1193
|
+
|
|
1133
1194
|
@staticmethod
|
|
1134
1195
|
def get_source_data(package: Package, packages: dict) -> list:
|
|
1135
1196
|
"""
|
|
@@ -1244,8 +1305,9 @@ class Core:
|
|
|
1244
1305
|
url=package.url
|
|
1245
1306
|
)
|
|
1246
1307
|
|
|
1247
|
-
|
|
1248
|
-
|
|
1308
|
+
# Use action from API (from security policy, label policy, triage, etc.)
|
|
1309
|
+
if 'action' in alert_item and alert_item['action']:
|
|
1310
|
+
action = alert_item['action']
|
|
1249
1311
|
setattr(issue_alert, action, True)
|
|
1250
1312
|
|
|
1251
1313
|
if issue_alert.key not in alerts_collection:
|
|
@@ -416,7 +416,7 @@ class Messages:
|
|
|
416
416
|
> **❗️ Caution**
|
|
417
417
|
> **Review the following alerts detected in dependencies.**
|
|
418
418
|
>
|
|
419
|
-
> According to your organization's
|
|
419
|
+
> According to your organization's policies, you **must** resolve all **"Block"** alerts before proceeding. It's recommended to resolve **"Warn"** alerts too.
|
|
420
420
|
> Learn more about [Socket for GitHub](https://socket.dev?utm_medium=gh).
|
|
421
421
|
|
|
422
422
|
<!-- start-socket-updated-alerts-table -->
|
|
@@ -622,7 +622,7 @@ class Messages:
|
|
|
622
622
|
@staticmethod
|
|
623
623
|
def create_security_alert_table(diff: Diff, md: MdUtils) -> tuple[MdUtils, list, dict]:
|
|
624
624
|
"""
|
|
625
|
-
Creates the detected issues table based on the
|
|
625
|
+
Creates the detected issues table based on alert actions from the API
|
|
626
626
|
:param diff: Diff - Diff report with the detected issues
|
|
627
627
|
:param md: MdUtils - Main markdown variable
|
|
628
628
|
:return:
|
|
@@ -794,7 +794,7 @@ class Messages:
|
|
|
794
794
|
@staticmethod
|
|
795
795
|
def create_console_security_alert_table(diff: Diff) -> PrettyTable:
|
|
796
796
|
"""
|
|
797
|
-
Creates the detected issues table based on the
|
|
797
|
+
Creates the detected issues table based on alert actions from the API
|
|
798
798
|
:param diff: Diff - Diff report with the detected issues
|
|
799
799
|
:return:
|
|
800
800
|
"""
|
|
@@ -25,7 +25,6 @@ class SocketConfig:
|
|
|
25
25
|
org_slug: Optional[str] = None
|
|
26
26
|
full_scan_path: Optional[str] = None
|
|
27
27
|
repository_path: Optional[str] = None
|
|
28
|
-
security_policy: Dict = None
|
|
29
28
|
repo_visibility: Optional[str] = 'private'
|
|
30
29
|
all_issues: Optional['AllIssues'] = None
|
|
31
30
|
excluded_dirs: Set[str] = field(default_factory=lambda: default_exclude_dirs)
|
|
@@ -42,10 +41,6 @@ class SocketConfig:
|
|
|
42
41
|
|
|
43
42
|
self._validate_api_url(self.api_url)
|
|
44
43
|
|
|
45
|
-
# Initialize empty dict for security policy if None
|
|
46
|
-
if self.security_policy is None:
|
|
47
|
-
self.security_policy = {}
|
|
48
|
-
|
|
49
44
|
# Initialize AllIssues if None
|
|
50
45
|
if self.all_issues is None:
|
|
51
46
|
self.all_issues = AllIssues()
|
|
@@ -70,6 +65,3 @@ class SocketConfig:
|
|
|
70
65
|
self.full_scan_path = f"{base_path}/full-scans"
|
|
71
66
|
self.repository_path = f"{base_path}/repos"
|
|
72
67
|
|
|
73
|
-
def update_security_policy(self, policy: Dict) -> None:
|
|
74
|
-
"""Update security policy"""
|
|
75
|
-
self.security_policy = policy
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import os
|
|
2
3
|
import sys
|
|
3
4
|
import traceback
|
|
4
5
|
import shutil
|
|
@@ -81,7 +82,7 @@ def main_code():
|
|
|
81
82
|
client = CliClient(socket_config)
|
|
82
83
|
sdk.api.api_url = socket_config.api_url
|
|
83
84
|
log.debug("loaded client")
|
|
84
|
-
core = Core(socket_config, sdk)
|
|
85
|
+
core = Core(socket_config, sdk, config)
|
|
85
86
|
log.debug("loaded core")
|
|
86
87
|
|
|
87
88
|
# Check for required dependencies if reachability analysis is enabled
|
|
@@ -207,7 +208,6 @@ def main_code():
|
|
|
207
208
|
base_paths = [config.target_path] # Always use target_path as the single base path
|
|
208
209
|
|
|
209
210
|
if config.sub_paths:
|
|
210
|
-
import os
|
|
211
211
|
for sub_path in config.sub_paths:
|
|
212
212
|
full_scan_path = os.path.join(config.target_path, sub_path)
|
|
213
213
|
log.debug(f"Using sub-path for scanning: {full_scan_path}")
|
|
@@ -299,7 +299,6 @@ def main_code():
|
|
|
299
299
|
|
|
300
300
|
# If only-facts-file mode, mark the facts file for submission
|
|
301
301
|
if config.only_facts_file:
|
|
302
|
-
import os
|
|
303
302
|
facts_file_to_submit = os.path.abspath(output_path)
|
|
304
303
|
log.info(f"Only-facts-file mode: will submit only {facts_file_to_submit}")
|
|
305
304
|
|
|
@@ -355,9 +354,6 @@ def main_code():
|
|
|
355
354
|
# If using sub_paths, we need to check if manifest files exist in the scan paths
|
|
356
355
|
if config.sub_paths and not files_explicitly_specified:
|
|
357
356
|
# Override file checking to look in the scan paths instead
|
|
358
|
-
import os
|
|
359
|
-
from pathlib import Path
|
|
360
|
-
|
|
361
357
|
# Get manifest files from all scan paths
|
|
362
358
|
try:
|
|
363
359
|
all_scan_files = []
|
|
@@ -569,7 +565,7 @@ def main_code():
|
|
|
569
565
|
)
|
|
570
566
|
output_handler.handle_output(diff)
|
|
571
567
|
|
|
572
|
-
|
|
568
|
+
# Handle license generation
|
|
573
569
|
if not should_skip_scan and diff.id != "NO_DIFF_RAN" and diff.id != "NO_SCAN_RAN" and config.generate_license:
|
|
574
570
|
all_packages = {}
|
|
575
571
|
for purl in diff.packages:
|
|
@@ -10,7 +10,6 @@ from socketdev.fullscans import (
|
|
|
10
10
|
StreamDiffResponse,
|
|
11
11
|
)
|
|
12
12
|
from socketdev.repos import GetRepoResponse
|
|
13
|
-
from socketdev.settings import OrgSecurityPolicyResponse
|
|
14
13
|
|
|
15
14
|
|
|
16
15
|
@pytest.fixture
|
|
@@ -88,14 +87,7 @@ def stream_diff_response(data_dir, load_json):
|
|
|
88
87
|
})
|
|
89
88
|
|
|
90
89
|
|
|
91
|
-
|
|
92
|
-
def security_policy(data_dir, load_json):
|
|
93
|
-
json_data = load_json(data_dir / "settings" / "security-policy.json")
|
|
94
|
-
return OrgSecurityPolicyResponse.from_dict({
|
|
95
|
-
"success": json_data["success"],
|
|
96
|
-
"status": json_data["status"],
|
|
97
|
-
"securityPolicyRules": json_data["securityPolicyRules"]
|
|
98
|
-
})
|
|
90
|
+
|
|
99
91
|
|
|
100
92
|
|
|
101
93
|
@pytest.fixture
|
|
@@ -146,13 +138,11 @@ def mock_sdk_with_responses(
|
|
|
146
138
|
new_scan_metadata,
|
|
147
139
|
new_scan_stream,
|
|
148
140
|
stream_diff_response,
|
|
149
|
-
security_policy,
|
|
150
141
|
create_full_scan_response,
|
|
151
142
|
):
|
|
152
143
|
sdk = mock_socket_sdk.return_value
|
|
153
144
|
|
|
154
145
|
# Simple returns
|
|
155
|
-
sdk.settings.get.return_value = security_policy
|
|
156
146
|
sdk.fullscans.post.return_value = create_full_scan_response
|
|
157
147
|
|
|
158
148
|
# Argument-based returns
|
|
@@ -33,11 +33,10 @@ class TestPackageAndAlerts:
|
|
|
33
33
|
}
|
|
34
34
|
})
|
|
35
35
|
|
|
36
|
-
# Set up settings.get() to return empty
|
|
36
|
+
# Set up settings.get() to return empty response
|
|
37
37
|
mock.settings = Mock()
|
|
38
38
|
settings_response = Mock()
|
|
39
39
|
settings_response.success = True
|
|
40
|
-
settings_response.security_policy = {}
|
|
41
40
|
mock.settings.get = Mock(return_value=settings_response)
|
|
42
41
|
|
|
43
42
|
return mock
|
|
@@ -48,7 +47,6 @@ class TestPackageAndAlerts:
|
|
|
48
47
|
api_key="test-key",
|
|
49
48
|
allow_unverified_ssl=False
|
|
50
49
|
)
|
|
51
|
-
config.security_policy = {} # Initialize with empty dict
|
|
52
50
|
return config
|
|
53
51
|
|
|
54
52
|
@pytest.fixture
|
|
@@ -135,34 +133,7 @@ class TestPackageAndAlerts:
|
|
|
135
133
|
assert alert.type == "networkAccess"
|
|
136
134
|
assert alert.severity == "high"
|
|
137
135
|
|
|
138
|
-
|
|
139
|
-
"""Test alerts are properly tagged based on security policy"""
|
|
140
|
-
# Mock security policy in config
|
|
141
|
-
core.config.security_policy = {
|
|
142
|
-
"networkAccess": {"action": "error"}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
package = Package(
|
|
146
|
-
id="pkg:npm/test@1.0.0",
|
|
147
|
-
name="test",
|
|
148
|
-
version="1.0.0",
|
|
149
|
-
type="npm",
|
|
150
|
-
alerts=[{
|
|
151
|
-
"type": "networkAccess",
|
|
152
|
-
"key": "test-alert",
|
|
153
|
-
"severity": "high"
|
|
154
|
-
}],
|
|
155
|
-
topLevelAncestors=[]
|
|
156
|
-
)
|
|
157
|
-
|
|
158
|
-
alerts_collection = {}
|
|
159
|
-
packages = {package.id: package}
|
|
160
|
-
|
|
161
|
-
result = core.add_package_alerts_to_collection(package, alerts_collection, packages)
|
|
162
|
-
|
|
163
|
-
assert len(result) == 1
|
|
164
|
-
alert = result["test-alert"][0]
|
|
165
|
-
assert alert.error is True
|
|
136
|
+
|
|
166
137
|
|
|
167
138
|
def test_get_capabilities_for_added_packages(self, core):
|
|
168
139
|
"""Test capability extraction from package alerts"""
|
|
@@ -7,13 +7,12 @@ def test_config_default_values():
|
|
|
7
7
|
|
|
8
8
|
assert config.api_key == "test_key"
|
|
9
9
|
assert config.api_url == "https://api.socket.dev/v0"
|
|
10
|
-
assert config.timeout ==
|
|
10
|
+
assert config.timeout == 1200
|
|
11
11
|
assert config.allow_unverified_ssl is False
|
|
12
12
|
assert config.org_id is None
|
|
13
13
|
assert config.org_slug is None
|
|
14
14
|
assert config.full_scan_path is None
|
|
15
15
|
assert config.repository_path is None
|
|
16
|
-
assert config.security_policy == {}
|
|
17
16
|
|
|
18
17
|
def test_config_custom_values():
|
|
19
18
|
"""Test that config accepts custom values"""
|
|
@@ -67,14 +66,4 @@ def test_config_update_org_details():
|
|
|
67
66
|
assert config.full_scan_path == "orgs/test-org/full-scans"
|
|
68
67
|
assert config.repository_path == "orgs/test-org/repos"
|
|
69
68
|
|
|
70
|
-
def test_config_update_security_policy():
|
|
71
|
-
"""Test updating security policy"""
|
|
72
|
-
config = SocketConfig(api_key="test_key")
|
|
73
|
-
|
|
74
|
-
test_policy = {
|
|
75
|
-
"rule1": {"action": "block"},
|
|
76
|
-
"rule2": {"action": "warn"}
|
|
77
|
-
}
|
|
78
69
|
|
|
79
|
-
config.security_policy = test_policy
|
|
80
|
-
assert config.security_policy == test_policy
|
|
@@ -1052,28 +1052,26 @@ wheels = [
|
|
|
1052
1052
|
|
|
1053
1053
|
[[package]]
|
|
1054
1054
|
name = "socketdev"
|
|
1055
|
-
version = "3.0.
|
|
1055
|
+
version = "3.0.21"
|
|
1056
1056
|
source = { registry = "https://pypi.org/simple" }
|
|
1057
1057
|
dependencies = [
|
|
1058
1058
|
{ name = "requests" },
|
|
1059
1059
|
{ name = "typing-extensions" },
|
|
1060
1060
|
]
|
|
1061
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
1061
|
+
sdist = { url = "https://files.pythonhosted.org/packages/33/fb/4669dcd763144f7ebba824562b58648be08f93474ce12fbe3e21836e622f/socketdev-3.0.21.tar.gz", hash = "sha256:c5fe8bdba8c2c114e3bfff9f5f3a4224eca5c85f86a68f68dda8a2d3fea26815", size = 134528, upload-time = "2025-11-27T17:27:09.608Z" }
|
|
1062
1062
|
wheels = [
|
|
1063
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1063
|
+
{ url = "https://files.pythonhosted.org/packages/e3/40/2974cca90077b861206e8f402571047ac074f6233c524eb88e8ee9323ecc/socketdev-3.0.21-py3-none-any.whl", hash = "sha256:39a85991445a4a37b0a3bc05138d5799cefc3185b77177fdb1e0d9a2ed81fd08", size = 59698, upload-time = "2025-11-27T17:27:07.696Z" },
|
|
1064
1064
|
]
|
|
1065
1065
|
|
|
1066
1066
|
[[package]]
|
|
1067
1067
|
name = "socketsecurity"
|
|
1068
|
-
version = "2.2.
|
|
1068
|
+
version = "2.2.41"
|
|
1069
1069
|
source = { editable = "." }
|
|
1070
1070
|
dependencies = [
|
|
1071
1071
|
{ name = "bs4" },
|
|
1072
1072
|
{ name = "gitpython" },
|
|
1073
|
-
{ name = "hatch" },
|
|
1074
1073
|
{ name = "mdutils" },
|
|
1075
1074
|
{ name = "packaging" },
|
|
1076
|
-
{ name = "pluggy" },
|
|
1077
1075
|
{ name = "prettytable" },
|
|
1078
1076
|
{ name = "python-dotenv" },
|
|
1079
1077
|
{ name = "requests" },
|
|
@@ -1096,15 +1094,18 @@ test = [
|
|
|
1096
1094
|
{ name = "pytest-watch" },
|
|
1097
1095
|
]
|
|
1098
1096
|
|
|
1097
|
+
[package.dev-dependencies]
|
|
1098
|
+
dev = [
|
|
1099
|
+
{ name = "pre-commit" },
|
|
1100
|
+
]
|
|
1101
|
+
|
|
1099
1102
|
[package.metadata]
|
|
1100
1103
|
requires-dist = [
|
|
1101
1104
|
{ name = "bs4", specifier = ">=0.0.2" },
|
|
1102
1105
|
{ name = "gitpython" },
|
|
1103
|
-
{ name = "hatch", specifier = ">=1.14.1" },
|
|
1104
1106
|
{ name = "hatch", marker = "extra == 'dev'" },
|
|
1105
1107
|
{ name = "mdutils" },
|
|
1106
1108
|
{ name = "packaging" },
|
|
1107
|
-
{ name = "pluggy", specifier = ">=1.6.0" },
|
|
1108
1109
|
{ name = "pre-commit", marker = "extra == 'dev'" },
|
|
1109
1110
|
{ name = "prettytable" },
|
|
1110
1111
|
{ name = "pytest", marker = "extra == 'test'", specifier = ">=7.4.0" },
|
|
@@ -1115,12 +1116,15 @@ requires-dist = [
|
|
|
1115
1116
|
{ name = "python-dotenv" },
|
|
1116
1117
|
{ name = "requests" },
|
|
1117
1118
|
{ name = "ruff", marker = "extra == 'dev'", specifier = ">=0.3.0" },
|
|
1118
|
-
{ name = "socketdev", specifier = ">=3.0.
|
|
1119
|
+
{ name = "socketdev", specifier = ">=3.0.21,<4.0.0" },
|
|
1119
1120
|
{ name = "twine", marker = "extra == 'dev'" },
|
|
1120
1121
|
{ name = "uv", marker = "extra == 'dev'", specifier = ">=0.1.0" },
|
|
1121
1122
|
]
|
|
1122
1123
|
provides-extras = ["test", "dev"]
|
|
1123
1124
|
|
|
1125
|
+
[package.metadata.requires-dev]
|
|
1126
|
+
dev = [{ name = "pre-commit", specifier = ">=4.3.0" }]
|
|
1127
|
+
|
|
1124
1128
|
[[package]]
|
|
1125
1129
|
name = "soupsieve"
|
|
1126
1130
|
version = "2.8"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{socketsecurity-2.2.38 → socketsecurity-2.2.43}/.github/PULL_REQUEST_TEMPLATE/improvement.md
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
|
|
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.2.38 → socketsecurity-2.2.43}/tests/data/fullscans/diff/stream_diff_full.json
RENAMED
|
File without changes
|
{socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/data/fullscans/head_scan/metadata.json
RENAMED
|
File without changes
|
{socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/data/fullscans/head_scan/stream_scan.json
RENAMED
|
File without changes
|
{socketsecurity-2.2.38 → socketsecurity-2.2.43}/tests/data/fullscans/head_scan/stream_scan_full.json
RENAMED
|
File without changes
|
|
File without changes
|
{socketsecurity-2.2.38 → socketsecurity-2.2.43}/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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|