socketsecurity 2.0.52__tar.gz → 2.0.56__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.0.52 → socketsecurity-2.0.56}/PKG-INFO +15 -13
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/README.md +14 -12
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/pyproject.toml +1 -1
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/__init__.py +1 -1
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/config.py +39 -14
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/core/__init__.py +20 -7
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/core/classes.py +1 -1
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/core/messages.py +130 -40
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/core/scm_comments.py +106 -4
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/core/socket_config.py +3 -1
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/socketcli.py +9 -1
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/.github/CODEOWNERS +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/.github/PULL_REQUEST_TEMPLATE/bug-fix.md +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/.github/PULL_REQUEST_TEMPLATE/feature.md +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/.github/PULL_REQUEST_TEMPLATE/improvement.md +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/.github/workflows/docker-stable.yml +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/.github/workflows/pr-preview.yml +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/.github/workflows/release.yml +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/.github/workflows/version-check.yml +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/.gitignore +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/.hooks/sync_version.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/.pre-commit-config.yaml +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/.python-version +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/Dockerfile +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/LICENSE +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/Makefile +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/Pipfile.lock +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/docs/README.md +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/pytest.ini +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/requirements-dev.lock +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/requirements.lock +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/scripts/build_container.sh +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/scripts/deploy-test-docker.sh +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/scripts/deploy-test-pypi.sh +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/scripts/run.sh +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/core/cli_client.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/core/exceptions.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/core/git_interface.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/core/issues.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/core/licenses.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/core/logging.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/core/scm/__init__.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/core/scm/base.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/core/scm/client.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/core/scm/github.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/core/scm/gitlab.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/core/utils.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/output.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/plugins/__init__.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/plugins/base.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/plugins/jira.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/plugins/manager.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/plugins/slack.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/plugins/teams.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/socketsecurity/plugins/webhook.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/__init__.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/core/conftest.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/core/create_diff_input.json +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/core/test_diff_generation.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/core/test_package_and_alerts.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/core/test_sdk_methods.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/core/test_supporting_methods.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/data/fullscans/create_response.json +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/data/fullscans/diff/stream_diff.json +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/data/fullscans/diff/stream_diff_full.json +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/data/fullscans/head_scan/metadata.json +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/data/fullscans/head_scan/stream_scan.json +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/data/fullscans/head_scan/stream_scan_full.json +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/data/fullscans/new_scan/metadata.json +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/data/fullscans/new_scan/stream_scan.json +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/data/repos/repo_info_error.json +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/data/repos/repo_info_no_head.json +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/data/repos/repo_info_success.json +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/data/settings/security-policy.json +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/unit/__init__.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/unit/test_cli_config.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/unit/test_client.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/unit/test_config.py +0 -0
- {socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/unit/test_output.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: socketsecurity
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.56
|
|
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>
|
|
@@ -79,13 +79,14 @@ If you don't want to provide the Socket API Token every time then you can use th
|
|
|
79
79
|
| --api-token | False | | Socket Security API token (can also be set via SOCKET_SECURITY_API_KEY env var) |
|
|
80
80
|
|
|
81
81
|
#### Repository
|
|
82
|
-
| Parameter
|
|
83
|
-
|
|
84
|
-
| --repo
|
|
85
|
-
| --integration
|
|
86
|
-
| --owner
|
|
87
|
-
| --branch
|
|
88
|
-
| --committers
|
|
82
|
+
| Parameter | Required | Default | Description |
|
|
83
|
+
|:-----------------|:---------|:--------|:------------------------------------------------------------------------|
|
|
84
|
+
| --repo | False | | Repository name in owner/repo format |
|
|
85
|
+
| --integration | False | api | Integration type (api, github, gitlab) |
|
|
86
|
+
| --owner | False | | Name of the integration owner, defaults to the socket organization slug |
|
|
87
|
+
| --branch | False | "" | Branch name |
|
|
88
|
+
| --committers | False | | Committer(s) to filter by |
|
|
89
|
+
| --repo-is-public | False | False | If set, flags a new repository creation as public. Defaults to false. |
|
|
89
90
|
|
|
90
91
|
#### Pull Request and Commit
|
|
91
92
|
| Parameter | Required | Default | Description |
|
|
@@ -95,11 +96,12 @@ If you don't want to provide the Socket API Token every time then you can use th
|
|
|
95
96
|
| --commit-sha | False | "" | Commit SHA |
|
|
96
97
|
|
|
97
98
|
#### Path and File
|
|
98
|
-
| Parameter
|
|
99
|
-
|
|
100
|
-
| --target-path
|
|
101
|
-
| --sbom-file
|
|
102
|
-
| --files
|
|
99
|
+
| Parameter | Required | Default | Description |
|
|
100
|
+
|:-------------------|:---------|:--------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
101
|
+
| --target-path | False | ./ | Target path for analysis |
|
|
102
|
+
| --sbom-file | False | | SBOM file path |
|
|
103
|
+
| --files | False | [] | Files to analyze (JSON array string) |
|
|
104
|
+
| --exclude-patterns | False | [] | List of patterns to exclude from analysis (JSON array string). You can get supported files form the [Supported Files API](https://docs.socket.dev/reference/getsupportedfiles) |
|
|
103
105
|
|
|
104
106
|
#### Branch and Scan Configuration
|
|
105
107
|
| Parameter | Required | Default | Description |
|
|
@@ -23,13 +23,14 @@ If you don't want to provide the Socket API Token every time then you can use th
|
|
|
23
23
|
| --api-token | False | | Socket Security API token (can also be set via SOCKET_SECURITY_API_KEY env var) |
|
|
24
24
|
|
|
25
25
|
#### Repository
|
|
26
|
-
| Parameter
|
|
27
|
-
|
|
28
|
-
| --repo
|
|
29
|
-
| --integration
|
|
30
|
-
| --owner
|
|
31
|
-
| --branch
|
|
32
|
-
| --committers
|
|
26
|
+
| Parameter | Required | Default | Description |
|
|
27
|
+
|:-----------------|:---------|:--------|:------------------------------------------------------------------------|
|
|
28
|
+
| --repo | False | | Repository name in owner/repo format |
|
|
29
|
+
| --integration | False | api | Integration type (api, github, gitlab) |
|
|
30
|
+
| --owner | False | | Name of the integration owner, defaults to the socket organization slug |
|
|
31
|
+
| --branch | False | "" | Branch name |
|
|
32
|
+
| --committers | False | | Committer(s) to filter by |
|
|
33
|
+
| --repo-is-public | False | False | If set, flags a new repository creation as public. Defaults to false. |
|
|
33
34
|
|
|
34
35
|
#### Pull Request and Commit
|
|
35
36
|
| Parameter | Required | Default | Description |
|
|
@@ -39,11 +40,12 @@ If you don't want to provide the Socket API Token every time then you can use th
|
|
|
39
40
|
| --commit-sha | False | "" | Commit SHA |
|
|
40
41
|
|
|
41
42
|
#### Path and File
|
|
42
|
-
| Parameter
|
|
43
|
-
|
|
44
|
-
| --target-path
|
|
45
|
-
| --sbom-file
|
|
46
|
-
| --files
|
|
43
|
+
| Parameter | Required | Default | Description |
|
|
44
|
+
|:-------------------|:---------|:--------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
45
|
+
| --target-path | False | ./ | Target path for analysis |
|
|
46
|
+
| --sbom-file | False | | SBOM file path |
|
|
47
|
+
| --files | False | [] | Files to analyze (JSON array string) |
|
|
48
|
+
| --exclude-patterns | False | [] | List of patterns to exclude from analysis (JSON array string). You can get supported files form the [Supported Files API](https://docs.socket.dev/reference/getsupportedfiles) |
|
|
47
49
|
|
|
48
50
|
#### Branch and Scan Configuration
|
|
49
51
|
| Parameter | Required | Default | Description |
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
__author__ = 'socket.dev'
|
|
2
|
-
__version__ = '2.0.
|
|
2
|
+
__version__ = '2.0.56'
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import argparse
|
|
2
|
+
import logging
|
|
2
3
|
import os
|
|
3
4
|
from dataclasses import asdict, dataclass, field
|
|
4
5
|
from typing import List, Optional
|
|
@@ -50,6 +51,8 @@ class CliConfig:
|
|
|
50
51
|
timeout: Optional[int] = 1200
|
|
51
52
|
exclude_license_details: bool = False
|
|
52
53
|
include_module_folders: bool = False
|
|
54
|
+
repo_is_public: bool = False
|
|
55
|
+
excluded_ecosystems: list[str] = field(default_factory=lambda: [])
|
|
53
56
|
version: str = __version__
|
|
54
57
|
jira_plugin: PluginConfig = field(default_factory=PluginConfig)
|
|
55
58
|
slack_plugin: PluginConfig = field(default_factory=PluginConfig)
|
|
@@ -94,8 +97,15 @@ class CliConfig:
|
|
|
94
97
|
'timeout': args.timeout,
|
|
95
98
|
'exclude_license_details': args.exclude_license_details,
|
|
96
99
|
'include_module_folders': args.include_module_folders,
|
|
100
|
+
'repo_is_public': args.repo_is_public,
|
|
101
|
+
"excluded_ecosystems": args.excluded_ecosystems,
|
|
97
102
|
'version': __version__
|
|
98
103
|
}
|
|
104
|
+
try:
|
|
105
|
+
config_args["excluded_ecosystems"] = json.loads(config_args["excluded_ecosystems"].replace("'", '"'))
|
|
106
|
+
except json.JSONDecodeError:
|
|
107
|
+
logging.error(f"Unable to parse excluded_ecosystems: {config_args['excluded_ecosystems']}")
|
|
108
|
+
exit(1)
|
|
99
109
|
config_args.update({
|
|
100
110
|
"jira_plugin": PluginConfig(
|
|
101
111
|
enabled=os.getenv("SOCKET_JIRA_ENABLED", "false").lower() == "true",
|
|
@@ -147,30 +157,32 @@ def create_argument_parser() -> argparse.ArgumentParser:
|
|
|
147
157
|
required=False
|
|
148
158
|
)
|
|
149
159
|
repo_group.add_argument(
|
|
160
|
+
"--repo-is-public",
|
|
161
|
+
dest="repo_is_public",
|
|
162
|
+
action="store_true",
|
|
163
|
+
help="If set it will flag a new repository creation as public. Defaults to false."
|
|
164
|
+
)
|
|
165
|
+
repo_group.add_argument(
|
|
166
|
+
"--branch",
|
|
167
|
+
metavar="<name>",
|
|
168
|
+
help="Branch name",
|
|
169
|
+
default=""
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
integration_group = parser.add_argument_group('Integration')
|
|
173
|
+
integration_group.add_argument(
|
|
150
174
|
"--integration",
|
|
151
175
|
choices=INTEGRATION_TYPES,
|
|
152
176
|
metavar="<type>",
|
|
153
|
-
help="Integration type",
|
|
177
|
+
help="Integration type of api, github, gitlab, azure, or bitbucket. Defaults to api",
|
|
154
178
|
default="api"
|
|
155
179
|
)
|
|
156
|
-
|
|
180
|
+
integration_group.add_argument(
|
|
157
181
|
"--owner",
|
|
158
182
|
metavar="<name>",
|
|
159
183
|
help="Name of the integration owner, defaults to the socket organization slug",
|
|
160
184
|
required=False
|
|
161
185
|
)
|
|
162
|
-
repo_group.add_argument(
|
|
163
|
-
"--branch",
|
|
164
|
-
metavar="<name>",
|
|
165
|
-
help="Branch name",
|
|
166
|
-
default=""
|
|
167
|
-
)
|
|
168
|
-
repo_group.add_argument(
|
|
169
|
-
"--committers",
|
|
170
|
-
metavar="<name>",
|
|
171
|
-
help="Committer(s) to filter by",
|
|
172
|
-
nargs="*"
|
|
173
|
-
)
|
|
174
186
|
|
|
175
187
|
# Pull Request and Commit info
|
|
176
188
|
pr_group = parser.add_argument_group('Pull Request and Commit')
|
|
@@ -209,6 +221,12 @@ def create_argument_parser() -> argparse.ArgumentParser:
|
|
|
209
221
|
dest="commit_sha",
|
|
210
222
|
help=argparse.SUPPRESS
|
|
211
223
|
)
|
|
224
|
+
pr_group.add_argument(
|
|
225
|
+
"--committers",
|
|
226
|
+
metavar="<name>",
|
|
227
|
+
help="Committer for the commit (comma separated)",
|
|
228
|
+
nargs="*"
|
|
229
|
+
)
|
|
212
230
|
|
|
213
231
|
# Path and File options
|
|
214
232
|
path_group = parser.add_argument_group('Path and File')
|
|
@@ -242,6 +260,13 @@ def create_argument_parser() -> argparse.ArgumentParser:
|
|
|
242
260
|
help="Files to analyze (JSON array string)"
|
|
243
261
|
)
|
|
244
262
|
|
|
263
|
+
path_group.add_argument(
|
|
264
|
+
"--excluded-ecosystems",
|
|
265
|
+
default="[]",
|
|
266
|
+
dest="excluded_ecosystems",
|
|
267
|
+
help="List of ecosystems to exclude from analysis (JSON array string)"
|
|
268
|
+
)
|
|
269
|
+
|
|
245
270
|
# Branch and Scan Configuration
|
|
246
271
|
config_group = parser.add_argument_group('Branch and Scan Configuration')
|
|
247
272
|
config_group.add_argument(
|
|
@@ -21,7 +21,7 @@ from socketsecurity.core.classes import (
|
|
|
21
21
|
FullScan,
|
|
22
22
|
Issue,
|
|
23
23
|
Package,
|
|
24
|
-
Purl
|
|
24
|
+
Purl
|
|
25
25
|
)
|
|
26
26
|
from socketsecurity.core.exceptions import APIResourceNotFound
|
|
27
27
|
from socketsecurity.core.licenses import Licenses
|
|
@@ -184,6 +184,8 @@ class Core:
|
|
|
184
184
|
patterns = fallback_patterns
|
|
185
185
|
|
|
186
186
|
for ecosystem in patterns:
|
|
187
|
+
if ecosystem in self.config.excluded_ecosystems:
|
|
188
|
+
continue
|
|
187
189
|
ecosystem_patterns = patterns[ecosystem]
|
|
188
190
|
for file_name in ecosystem_patterns:
|
|
189
191
|
original_pattern = ecosystem_patterns[file_name]["pattern"]
|
|
@@ -439,7 +441,12 @@ class Core:
|
|
|
439
441
|
log.warning(f"Failed to get repository {repo_slug}, attempting to create it")
|
|
440
442
|
try:
|
|
441
443
|
|
|
442
|
-
create_response = self.sdk.repos.post(
|
|
444
|
+
create_response = self.sdk.repos.post(
|
|
445
|
+
self.config.org_slug,
|
|
446
|
+
name=repo_slug,
|
|
447
|
+
default_branch=default_branch,
|
|
448
|
+
visibility=self.config.repo_visibility
|
|
449
|
+
)
|
|
443
450
|
|
|
444
451
|
# Check if the response is empty (failure) or has content (success)
|
|
445
452
|
if not create_response:
|
|
@@ -644,7 +651,7 @@ class Core:
|
|
|
644
651
|
seen_removed_packages = set()
|
|
645
652
|
|
|
646
653
|
for package_id, package in added_packages.items():
|
|
647
|
-
purl =
|
|
654
|
+
purl = self.create_purl(package_id, added_packages)
|
|
648
655
|
base_purl = f"{purl.ecosystem}/{purl.name}@{purl.version}"
|
|
649
656
|
|
|
650
657
|
if (not direct_only or package.direct) and base_purl not in seen_new_packages:
|
|
@@ -658,7 +665,7 @@ class Core:
|
|
|
658
665
|
)
|
|
659
666
|
|
|
660
667
|
for package_id, package in removed_packages.items():
|
|
661
|
-
purl =
|
|
668
|
+
purl = self.create_purl(package_id, removed_packages)
|
|
662
669
|
base_purl = f"{purl.ecosystem}/{purl.name}@{purl.version}"
|
|
663
670
|
|
|
664
671
|
if (not direct_only or package.direct) and base_purl not in seen_removed_packages:
|
|
@@ -682,8 +689,13 @@ class Core:
|
|
|
682
689
|
|
|
683
690
|
return diff
|
|
684
691
|
|
|
685
|
-
|
|
686
|
-
|
|
692
|
+
def get_all_scores(self, packages: dict[str, Package]) -> dict[str, Package]:
|
|
693
|
+
components = []
|
|
694
|
+
for package_id in packages:
|
|
695
|
+
package = packages[package_id]
|
|
696
|
+
return packages
|
|
697
|
+
|
|
698
|
+
def create_purl(self, package_id: str, packages: dict[str, Package]) -> Purl:
|
|
687
699
|
"""
|
|
688
700
|
Creates the extended PURL data for package identification and tracking.
|
|
689
701
|
|
|
@@ -707,7 +719,8 @@ class Core:
|
|
|
707
719
|
size=package.size,
|
|
708
720
|
transitives=package.transitives,
|
|
709
721
|
url=package.url,
|
|
710
|
-
purl=package.purl
|
|
722
|
+
purl=package.purl,
|
|
723
|
+
scores=package.score
|
|
711
724
|
)
|
|
712
725
|
return purl
|
|
713
726
|
|
|
@@ -370,7 +370,6 @@ class Repository:
|
|
|
370
370
|
def __str__(self):
|
|
371
371
|
return json.dumps(self.__dict__)
|
|
372
372
|
|
|
373
|
-
|
|
374
373
|
class Purl:
|
|
375
374
|
"""
|
|
376
375
|
Represents a Package URL (PURL) with extended metadata.
|
|
@@ -392,6 +391,7 @@ class Purl:
|
|
|
392
391
|
author_url: str
|
|
393
392
|
url: str
|
|
394
393
|
purl: str
|
|
394
|
+
scores: dict[str, int]
|
|
395
395
|
|
|
396
396
|
def __init__(self, **kwargs):
|
|
397
397
|
if kwargs:
|
|
@@ -302,26 +302,95 @@ class Messages:
|
|
|
302
302
|
@staticmethod
|
|
303
303
|
def security_comment_template(diff: Diff) -> str:
|
|
304
304
|
"""
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
305
|
+
Generates the security comment template in the new required format.
|
|
306
|
+
Dynamically determines placement of the alerts table if markers like `<!-- start-socket-alerts-table -->` are used.
|
|
307
|
+
|
|
308
|
+
:param diff: Diff - Contains the detected vulnerabilities and warnings.
|
|
309
|
+
:return: str - The formatted Markdown/HTML string.
|
|
308
310
|
"""
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
311
|
+
# Start of the comment
|
|
312
|
+
comment = """<!-- socket-security-comment-actions -->
|
|
313
|
+
|
|
314
|
+
> **❗️ Caution**
|
|
315
|
+
> **Review the following alerts detected in dependencies.**
|
|
316
|
+
>
|
|
317
|
+
> According to your organization’s Security Policy, you **must** resolve all **“Block”** alerts before proceeding. It’s recommended to resolve **“Warn”** alerts too.
|
|
318
|
+
> Learn more about [Socket for GitHub](https://socket.dev?utm_medium=gh).
|
|
319
|
+
|
|
320
|
+
<!-- start-socket-updated-alerts-table -->
|
|
321
|
+
<table>
|
|
322
|
+
<thead>
|
|
323
|
+
<tr>
|
|
324
|
+
<th>Action</th>
|
|
325
|
+
<th>Severity</th>
|
|
326
|
+
<th align="left">Alert (click for details)</th>
|
|
327
|
+
</tr>
|
|
328
|
+
</thead>
|
|
329
|
+
<tbody>
|
|
330
|
+
"""
|
|
331
|
+
|
|
332
|
+
# Loop through alerts, dynamically generating rows
|
|
333
|
+
for alert in diff.new_alerts:
|
|
334
|
+
severity_icon = Messages.get_severity_icon(alert.severity)
|
|
335
|
+
action = "Block" if alert.error else "Warn"
|
|
336
|
+
details_open = ""
|
|
337
|
+
# Generate a table row for each alert
|
|
338
|
+
comment += f"""
|
|
339
|
+
<!-- start-socket-alert-{alert.pkg_name}@{alert.pkg_version} -->
|
|
340
|
+
<tr>
|
|
341
|
+
<td><strong>{action}</strong></td>
|
|
342
|
+
<td align="center">
|
|
343
|
+
<img src="{severity_icon}" alt="{alert.severity}" width="20" height="20">
|
|
344
|
+
</td>
|
|
345
|
+
<td>
|
|
346
|
+
<details {details_open}>
|
|
347
|
+
<summary>{alert.pkg_name}@{alert.pkg_version} - {alert.title}</summary>
|
|
348
|
+
<p><strong>Note:</strong> {alert.description}</p>
|
|
349
|
+
<p><strong>Source:</strong> <a href="{alert.manifests}">Manifest File</a></p>
|
|
350
|
+
<p>ℹ️ Read more on:
|
|
351
|
+
<a href="{alert.purl}">This package</a> |
|
|
352
|
+
<a href="{alert.url}">This alert</a> |
|
|
353
|
+
<a href="https://socket.dev/alerts/malware">What is known malware?</a></p>
|
|
354
|
+
<blockquote>
|
|
355
|
+
<p><em>Suggestion:</em> {alert.suggestion}</p>
|
|
356
|
+
<p><em>Mark as acceptable risk:</em> To ignore this alert only in this pull request, reply with:<br/>
|
|
357
|
+
<code>@SocketSecurity ignore {alert.pkg_name}@{alert.pkg_version}</code><br/>
|
|
358
|
+
Or ignore all future alerts with:<br/>
|
|
359
|
+
<code>@SocketSecurity ignore-all</code></p>
|
|
360
|
+
</blockquote>
|
|
361
|
+
</details>
|
|
362
|
+
</td>
|
|
363
|
+
</tr>
|
|
364
|
+
<!-- end-socket-alert-{alert.pkg_name}@{alert.pkg_version} -->
|
|
365
|
+
"""
|
|
366
|
+
|
|
367
|
+
# Close table and comment
|
|
368
|
+
comment += """
|
|
369
|
+
</tbody>
|
|
370
|
+
</table>
|
|
371
|
+
<!-- end-socket-alerts-table -->
|
|
372
|
+
|
|
373
|
+
[View full report](https://socket.dev/...&action=error%2Cwarn)
|
|
374
|
+
"""
|
|
375
|
+
|
|
376
|
+
return comment
|
|
377
|
+
|
|
378
|
+
@staticmethod
|
|
379
|
+
def get_severity_icon(severity: str) -> str:
|
|
380
|
+
"""
|
|
381
|
+
Maps severity levels to their corresponding badge/icon URLs.
|
|
382
|
+
|
|
383
|
+
:param severity: str - Severity level (e.g., "Critical", "High").
|
|
384
|
+
:return: str - Badge/icon URL.
|
|
385
|
+
"""
|
|
386
|
+
severity_map = {
|
|
387
|
+
"critical": "https://github-app-statics.socket.dev/severity-3.svg",
|
|
388
|
+
"high": "https://github-app-statics.socket.dev/severity-2.svg",
|
|
389
|
+
"medium": "https://github-app-statics.socket.dev/severity-1.svg",
|
|
390
|
+
"low": "https://github-app-statics.socket.dev/severity-0.svg",
|
|
391
|
+
}
|
|
392
|
+
return severity_map.get(severity.lower(), "https://github-app-statics.socket.dev/severity-0.svg")
|
|
393
|
+
|
|
325
394
|
|
|
326
395
|
@staticmethod
|
|
327
396
|
def create_next_steps(md: MdUtils, next_steps: dict):
|
|
@@ -456,11 +525,9 @@ class Messages:
|
|
|
456
525
|
md = MdUtils(file_name="markdown_overview_temp.md")
|
|
457
526
|
md.new_line("<!-- socket-overview-comment-actions -->")
|
|
458
527
|
md.new_header(level=1, title="Socket Security: Dependency Overview")
|
|
459
|
-
md.new_line("
|
|
528
|
+
md.new_line("Review the following changes in direct dependencies. Learn more about [socket.dev](https://socket.dev)")
|
|
460
529
|
md.new_line()
|
|
461
530
|
md = Messages.create_added_table(diff, md)
|
|
462
|
-
if len(diff.removed_packages) > 0:
|
|
463
|
-
md = Messages.create_remove_line(diff, md)
|
|
464
531
|
md.create_md_file()
|
|
465
532
|
if len(md.file_data_text.lstrip()) >= 65500:
|
|
466
533
|
md = Messages.short_dependency_overview_comment(diff)
|
|
@@ -471,7 +538,7 @@ class Messages:
|
|
|
471
538
|
md = MdUtils(file_name="markdown_overview_temp.md")
|
|
472
539
|
md.new_line("<!-- socket-overview-comment-actions -->")
|
|
473
540
|
md.new_header(level=1, title="Socket Security: Dependency Overview")
|
|
474
|
-
md.new_line("
|
|
541
|
+
md.new_line("Review the following changes in direct dependencies. Learn more about [socket.dev](https://socket.dev)")
|
|
475
542
|
md.new_line()
|
|
476
543
|
md.new_line("The amount of dependency changes were to long for this comment. Please check out the full report")
|
|
477
544
|
md.new_line(f"To view more information about this report checkout the [Full Report]({diff.diff_url})")
|
|
@@ -498,40 +565,63 @@ class Messages:
|
|
|
498
565
|
def create_added_table(diff: Diff, md: MdUtils) -> MdUtils:
|
|
499
566
|
"""
|
|
500
567
|
Create the Added packages table for the Dependency Overview template
|
|
501
|
-
:param diff: Diff - Diff report with the Added
|
|
568
|
+
:param diff: Diff - Diff report with the Added package information
|
|
502
569
|
:param md: MdUtils - Main markdown variable
|
|
503
570
|
:return:
|
|
504
571
|
"""
|
|
572
|
+
# Table column headers
|
|
505
573
|
overview_table = [
|
|
574
|
+
"Diff",
|
|
506
575
|
"Package",
|
|
507
|
-
"
|
|
508
|
-
"
|
|
509
|
-
"
|
|
510
|
-
"
|
|
511
|
-
"
|
|
576
|
+
"Supply Chain<br/>Security",
|
|
577
|
+
"Vulnerability",
|
|
578
|
+
"Quality",
|
|
579
|
+
"Maintenance",
|
|
580
|
+
"License"
|
|
512
581
|
]
|
|
513
582
|
num_of_overview_columns = len(overview_table)
|
|
583
|
+
|
|
514
584
|
count = 0
|
|
515
585
|
for added in diff.new_packages:
|
|
516
|
-
added: Purl
|
|
517
|
-
|
|
518
|
-
|
|
586
|
+
added: Purl # Ensure `added` has scores and relevant attributes.
|
|
587
|
+
|
|
588
|
+
package_url = f"[{added.purl}]({added.url})"
|
|
589
|
+
diff_badge = f"[]({added.url})"
|
|
590
|
+
|
|
591
|
+
# Scores dynamically converted to badge URLs and linked
|
|
592
|
+
def score_to_badge(score):
|
|
593
|
+
score_percent = int(score * 100) # Convert to integer percentage
|
|
594
|
+
return f"[]({added.url})"
|
|
595
|
+
|
|
596
|
+
# Generate badges for each score type
|
|
597
|
+
supply_chain_risk_badge = score_to_badge(added.scores.get("supplyChain", 100))
|
|
598
|
+
vulnerability_badge = score_to_badge(added.scores.get("vulnerability", 100))
|
|
599
|
+
quality_badge = score_to_badge(added.scores.get("quality", 100))
|
|
600
|
+
maintenance_badge = score_to_badge(added.scores.get("maintenance", 100))
|
|
601
|
+
license_badge = score_to_badge(added.scores.get("license", 100))
|
|
602
|
+
|
|
603
|
+
# Add the row for this package
|
|
519
604
|
row = [
|
|
605
|
+
diff_badge,
|
|
520
606
|
package_url,
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
607
|
+
supply_chain_risk_badge,
|
|
608
|
+
vulnerability_badge,
|
|
609
|
+
quality_badge,
|
|
610
|
+
maintenance_badge,
|
|
611
|
+
license_badge
|
|
526
612
|
]
|
|
527
613
|
overview_table.extend(row)
|
|
528
|
-
count += 1
|
|
529
|
-
|
|
614
|
+
count += 1 # Count total packages
|
|
615
|
+
|
|
616
|
+
# Calculate total rows for table
|
|
617
|
+
num_of_overview_rows = count + 1 # Include header row
|
|
618
|
+
|
|
619
|
+
# Generate Markdown table
|
|
530
620
|
md.new_table(
|
|
531
621
|
columns=num_of_overview_columns,
|
|
532
622
|
rows=num_of_overview_rows,
|
|
533
623
|
text=overview_table,
|
|
534
|
-
text_align="
|
|
624
|
+
text_align="center"
|
|
535
625
|
)
|
|
536
626
|
return md
|
|
537
627
|
|
|
@@ -84,9 +84,22 @@ class Comments:
|
|
|
84
84
|
|
|
85
85
|
@staticmethod
|
|
86
86
|
def process_security_comment(comment: Comment, comments) -> str:
|
|
87
|
-
lines = []
|
|
88
|
-
start = False
|
|
89
87
|
ignore_all, ignore_commands = Comments.get_ignore_options(comments)
|
|
88
|
+
if "start-socket-alerts-table" in "".join(comment.body_list):
|
|
89
|
+
new_body = Comments.process_original_security_comment(comment, ignore_all, ignore_commands)
|
|
90
|
+
else:
|
|
91
|
+
new_body = Comments.process_updated_security_comment(comment, ignore_all, ignore_commands)
|
|
92
|
+
|
|
93
|
+
return new_body
|
|
94
|
+
|
|
95
|
+
@staticmethod
|
|
96
|
+
def process_original_security_comment(
|
|
97
|
+
comment: Comment,
|
|
98
|
+
ignore_all: bool,
|
|
99
|
+
ignore_commands: list[tuple[str, str]]
|
|
100
|
+
) -> str:
|
|
101
|
+
start = False
|
|
102
|
+
lines = []
|
|
90
103
|
for line in comment.body_list:
|
|
91
104
|
line = line.strip()
|
|
92
105
|
if "start-socket-alerts-table" in line:
|
|
@@ -110,8 +123,97 @@ class Comments:
|
|
|
110
123
|
lines.append(line)
|
|
111
124
|
else:
|
|
112
125
|
lines.append(line)
|
|
113
|
-
|
|
114
|
-
|
|
126
|
+
return "\n".join(lines)
|
|
127
|
+
|
|
128
|
+
@staticmethod
|
|
129
|
+
def process_updated_security_comment(
|
|
130
|
+
comment: Comment,
|
|
131
|
+
ignore_all: bool,
|
|
132
|
+
ignore_commands: list[tuple[str, str]]
|
|
133
|
+
) -> str:
|
|
134
|
+
"""
|
|
135
|
+
Processes an updated security comment containing an HTML table with alert sections.
|
|
136
|
+
Removes entire sections marked by start and end hidden comments if the alert matches
|
|
137
|
+
ignore conditions.
|
|
138
|
+
|
|
139
|
+
:param comment: Comment - The raw comment object containing the existing information.
|
|
140
|
+
:param ignore_all: bool - Flag to ignore all alerts.
|
|
141
|
+
:param ignore_commands: list of tuples - Specific ignore commands representing (pkg_name, pkg_version).
|
|
142
|
+
:return: str - The updated comment as a single string.
|
|
143
|
+
"""
|
|
144
|
+
lines = []
|
|
145
|
+
ignore_section = False
|
|
146
|
+
pkg_name = pkg_version = "" # Track current package and version
|
|
147
|
+
|
|
148
|
+
# Loop through the comment lines
|
|
149
|
+
for line in comment.body_list:
|
|
150
|
+
line = line.strip()
|
|
151
|
+
|
|
152
|
+
# Detect the start of an alert section
|
|
153
|
+
if line.startswith("<!-- start-socket-alert-"):
|
|
154
|
+
# Extract package name and version from the comment
|
|
155
|
+
try:
|
|
156
|
+
start_marker = line[len("<!-- start-socket-alert-"):-4] # Strip the comment markers
|
|
157
|
+
pkg_name, pkg_version = start_marker.split("@") # Extract pkg_name and pkg_version
|
|
158
|
+
except ValueError:
|
|
159
|
+
pkg_name, pkg_version = "", ""
|
|
160
|
+
|
|
161
|
+
# Determine if we should ignore this alert
|
|
162
|
+
ignore_section = ignore_all or any(
|
|
163
|
+
Comments.is_ignore(pkg_name, pkg_version, name, version)
|
|
164
|
+
for name, version in ignore_commands
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
# If not ignored, include this start marker
|
|
168
|
+
if not ignore_section:
|
|
169
|
+
lines.append(line)
|
|
170
|
+
|
|
171
|
+
# Detect the end of an alert section
|
|
172
|
+
elif line.startswith("<!-- end-socket-alert-"):
|
|
173
|
+
# Only include if we are not ignoring this section
|
|
174
|
+
if not ignore_section:
|
|
175
|
+
lines.append(line)
|
|
176
|
+
ignore_section = False # Reset ignore flag
|
|
177
|
+
|
|
178
|
+
# Include lines inside an alert section only if not ignored
|
|
179
|
+
elif not ignore_section:
|
|
180
|
+
lines.append(line)
|
|
181
|
+
|
|
182
|
+
return "\n".join(lines)
|
|
183
|
+
|
|
184
|
+
@staticmethod
|
|
185
|
+
def extract_alert_details_from_row(row: str, ignore_all: bool, ignore_commands: list[tuple[str, str]]) -> tuple:
|
|
186
|
+
"""
|
|
187
|
+
Parses an HTML table row (<tr>) to extract alert details and determine if it should be ignored.
|
|
188
|
+
|
|
189
|
+
:param row: str - The HTML table row as a string.
|
|
190
|
+
:param ignore_all: bool - Flag to ignore all alerts.
|
|
191
|
+
:param ignore_commands: list of tuples - List of (pkg_name, pkg_version) to ignore.
|
|
192
|
+
:return: tuple - (pkg_name, pkg_version, ignore)
|
|
193
|
+
"""
|
|
194
|
+
# Extract package details (pkg_name and pkg_version) from the HTML table row
|
|
195
|
+
try:
|
|
196
|
+
# Find the relevant <summary> element to extract package information
|
|
197
|
+
start_index = row.index("<summary>")
|
|
198
|
+
end_index = row.index("</summary>")
|
|
199
|
+
summary_content = row[start_index + 9:end_index] # Extract content between <summary> tags
|
|
200
|
+
|
|
201
|
+
# Example: "npm/malicious-package@1.0.0 - Known Malware Alert"
|
|
202
|
+
pkg_info, _ = summary_content.split(" - ", 1)
|
|
203
|
+
pkg_name, pkg_version = pkg_info.split("@")
|
|
204
|
+
except ValueError:
|
|
205
|
+
# If parsing fails, skip this row
|
|
206
|
+
return "", "", False
|
|
207
|
+
|
|
208
|
+
# Check ignore logic
|
|
209
|
+
ignore = False
|
|
210
|
+
for name, version in ignore_commands:
|
|
211
|
+
if ignore_all or Comments.is_ignore(pkg_name, pkg_version, name, version):
|
|
212
|
+
ignore = True
|
|
213
|
+
break
|
|
214
|
+
|
|
215
|
+
return pkg_name, pkg_version, ignore
|
|
216
|
+
|
|
115
217
|
|
|
116
218
|
@staticmethod
|
|
117
219
|
def check_for_socket_comments(comments: dict):
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from dataclasses import dataclass, field
|
|
2
2
|
from typing import Dict, Optional
|
|
3
3
|
from urllib.parse import urlparse
|
|
4
|
-
from typing import Set
|
|
4
|
+
from typing import Set, List
|
|
5
5
|
import os
|
|
6
6
|
|
|
7
7
|
from socketsecurity.core.issues import AllIssues
|
|
@@ -26,8 +26,10 @@ class SocketConfig:
|
|
|
26
26
|
full_scan_path: Optional[str] = None
|
|
27
27
|
repository_path: Optional[str] = None
|
|
28
28
|
security_policy: Dict = None
|
|
29
|
+
repo_visibility: Optional[str] = 'private'
|
|
29
30
|
all_issues: Optional['AllIssues'] = None
|
|
30
31
|
excluded_dirs: Set[str] = field(default_factory=lambda: default_exclude_dirs)
|
|
32
|
+
excluded_ecosystems: List[str] = field(default_factory=lambda: [])
|
|
31
33
|
version: str = __version__
|
|
32
34
|
|
|
33
35
|
def __post_init__(self):
|
|
@@ -148,8 +148,16 @@ def main_code():
|
|
|
148
148
|
log.debug("Found manifest files or forced scan, proceeding")
|
|
149
149
|
|
|
150
150
|
org_slug = core.config.org_slug
|
|
151
|
+
if config.repo_is_public:
|
|
152
|
+
core.config.repo_visibility = "public"
|
|
153
|
+
if config.excluded_ecosystems and len(config.excluded_ecosystems) > 0:
|
|
154
|
+
core.config.excluded_ecosystems = config.excluded_ecosystems
|
|
151
155
|
integration_type = config.integration_type
|
|
152
156
|
integration_org_slug = config.integration_org_slug or org_slug
|
|
157
|
+
try:
|
|
158
|
+
pr_number = int(config.pr_number)
|
|
159
|
+
except (ValueError, TypeError):
|
|
160
|
+
pr_number = 0
|
|
153
161
|
|
|
154
162
|
params = FullScanParams(
|
|
155
163
|
org_slug=org_slug,
|
|
@@ -159,7 +167,7 @@ def main_code():
|
|
|
159
167
|
branch=config.branch,
|
|
160
168
|
commit_message=config.commit_message,
|
|
161
169
|
commit_hash=config.commit_sha,
|
|
162
|
-
pull_request=
|
|
170
|
+
pull_request=pr_number,
|
|
163
171
|
committers=config.committers,
|
|
164
172
|
make_default_branch=config.default_branch,
|
|
165
173
|
set_as_pending_head=True
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{socketsecurity-2.0.52 → socketsecurity-2.0.56}/.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
|
{socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/data/fullscans/diff/stream_diff_full.json
RENAMED
|
File without changes
|
{socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/data/fullscans/head_scan/metadata.json
RENAMED
|
File without changes
|
{socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/data/fullscans/head_scan/stream_scan.json
RENAMED
|
File without changes
|
{socketsecurity-2.0.52 → socketsecurity-2.0.56}/tests/data/fullscans/head_scan/stream_scan_full.json
RENAMED
|
File without changes
|
|
File without changes
|
{socketsecurity-2.0.52 → socketsecurity-2.0.56}/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
|