socketsecurity 2.2.59__tar.gz → 2.2.62__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.59 → socketsecurity-2.2.62}/PKG-INFO +111 -11
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/README.md +108 -9
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/pyproject.toml +3 -2
- socketsecurity-2.2.62/session.md +127 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/__init__.py +1 -1
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/config.py +27 -5
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/core/__init__.py +4 -1
- socketsecurity-2.2.62/socketsecurity/core/helper/socket_facts_loader.py +387 -0
- socketsecurity-2.2.62/socketsecurity/plugins/formatters/__init__.py +5 -0
- socketsecurity-2.2.62/socketsecurity/plugins/formatters/slack.py +272 -0
- socketsecurity-2.2.62/socketsecurity/plugins/slack.py +712 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/socketcli.py +4 -3
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/uv.lock +285 -274
- socketsecurity-2.2.59/socketsecurity/plugins/slack.py +0 -95
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/.github/CODEOWNERS +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/.github/PULL_REQUEST_TEMPLATE/bug-fix.md +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/.github/PULL_REQUEST_TEMPLATE/feature.md +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/.github/PULL_REQUEST_TEMPLATE/improvement.md +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/.github/workflows/docker-stable.yml +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/.github/workflows/pr-preview.yml +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/.github/workflows/release.yml +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/.github/workflows/version-check.yml +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/.gitignore +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/.hooks/sync_version.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/.pre-commit-config.yaml +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/.python-version +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/CHANGELOG.md +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/Dockerfile +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/LICENSE +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/Makefile +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/docs/README.md +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/pytest.ini +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/scripts/build_container.sh +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/scripts/build_container_flexible.sh +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/scripts/deploy-test-docker.sh +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/scripts/deploy-test-pypi.sh +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/scripts/docker-entrypoint.sh +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/scripts/run.sh +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/core/classes.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/core/cli_client.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/core/exceptions.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/core/git_interface.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/core/helper/__init__.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/core/lazy_file_loader.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/core/logging.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/core/messages.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/core/resource_utils.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/core/scm/__init__.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/core/scm/base.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/core/scm/client.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/core/scm/github.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/core/scm/gitlab.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/core/scm_comments.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/core/socket_config.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/core/tools/reachability.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/core/utils.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/output.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/plugins/__init__.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/plugins/base.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/plugins/jira.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/plugins/manager.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/plugins/teams.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/socketsecurity/plugins/webhook.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/__init__.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/core/conftest.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/core/create_diff_input.json +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/core/test_diff_generation.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/core/test_package_and_alerts.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/core/test_sdk_methods.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/core/test_supporting_methods.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/data/fullscans/create_response.json +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/data/fullscans/diff/stream_diff.json +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/data/fullscans/diff/stream_diff_full.json +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/data/fullscans/head_scan/metadata.json +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/data/fullscans/head_scan/stream_scan.json +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/data/fullscans/head_scan/stream_scan_full.json +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/data/fullscans/new_scan/metadata.json +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/data/fullscans/new_scan/stream_scan.json +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/data/repos/repo_info_error.json +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/data/repos/repo_info_no_head.json +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/data/repos/repo_info_success.json +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/data/settings/security-policy.json +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/unit/__init__.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/unit/test_cli_config.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/unit/test_client.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/unit/test_config.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/unit/test_gitlab_auth.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/unit/test_gitlab_auth_fallback.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/tests/unit/test_output.py +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/workflows/bitbucket-pipelines.yml +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/workflows/github-actions.yml +0 -0
- {socketsecurity-2.2.59 → socketsecurity-2.2.62}/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.62
|
|
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>
|
|
@@ -35,12 +35,13 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
35
35
|
Requires-Python: >=3.10
|
|
36
36
|
Requires-Dist: bs4>=0.0.2
|
|
37
37
|
Requires-Dist: gitpython
|
|
38
|
+
Requires-Dist: markdown>=3.10
|
|
38
39
|
Requires-Dist: mdutils
|
|
39
40
|
Requires-Dist: packaging
|
|
40
41
|
Requires-Dist: prettytable
|
|
41
42
|
Requires-Dist: python-dotenv
|
|
42
43
|
Requires-Dist: requests
|
|
43
|
-
Requires-Dist: socketdev<4.0.0,>=3.0.
|
|
44
|
+
Requires-Dist: socketdev<4.0.0,>=3.0.25
|
|
44
45
|
Provides-Extra: dev
|
|
45
46
|
Requires-Dist: hatch; extra == 'dev'
|
|
46
47
|
Requires-Dist: pre-commit; extra == 'dev'
|
|
@@ -158,14 +159,14 @@ socketcli [-h] [--api-token API_TOKEN] [--repo REPO] [--repo-is-public] [--branc
|
|
|
158
159
|
[--only-facts-file] [--version]
|
|
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 `
|
|
162
|
+
If you don't want to provide the Socket API Token every time then you can use the environment variable `SOCKET_SECURITY_API_TOKEN`
|
|
162
163
|
|
|
163
164
|
### Parameters
|
|
164
165
|
|
|
165
166
|
#### Authentication
|
|
166
|
-
| Parameter | Required | Default | Description
|
|
167
|
-
|
|
168
|
-
| --api-token | False | | Socket Security API token (can also be set via
|
|
167
|
+
| Parameter | Required | Default | Description |
|
|
168
|
+
|:------------|:---------|:--------|:----------------------------------------------------------------------------------|
|
|
169
|
+
| --api-token | False | | Socket Security API token (can also be set via SOCKET_SECURITY_API_TOKEN env var) |
|
|
169
170
|
|
|
170
171
|
#### Repository
|
|
171
172
|
| Parameter | Required | Default | Description |
|
|
@@ -278,15 +279,113 @@ Example `SOCKET_JIRA_CONFIG_JSON` value
|
|
|
278
279
|
|
|
279
280
|
| Environment Variable | Required | Default | Description |
|
|
280
281
|
|:-------------------------|:---------|:--------|:-----------------------------------|
|
|
281
|
-
|
|
|
282
|
-
|
|
|
282
|
+
| SOCKET_SLACK_CONFIG_JSON | False | None | Slack configuration (enables plugin when set). Supports webhook or bot mode. Alternatively, use --slack-webhook CLI flag for simple webhook mode. |
|
|
283
|
+
| SOCKET_SLACK_BOT_TOKEN | False | None | Slack Bot User OAuth Token (starts with `xoxb-`). Required when using bot mode. |
|
|
283
284
|
|
|
284
|
-
|
|
285
|
+
**Slack supports two modes:**
|
|
286
|
+
|
|
287
|
+
1. **Webhook Mode** (default): Posts to incoming webhooks
|
|
288
|
+
2. **Bot Mode**: Posts via Slack API with bot token authentication
|
|
289
|
+
|
|
290
|
+
###### Webhook Mode Examples
|
|
291
|
+
|
|
292
|
+
Simple webhook:
|
|
293
|
+
|
|
294
|
+
````json
|
|
295
|
+
{"url": "https://hooks.slack.com/services/YOUR/WEBHOOK/URL"}
|
|
296
|
+
````
|
|
297
|
+
|
|
298
|
+
Multiple webhooks with advanced filtering:
|
|
285
299
|
|
|
286
300
|
````json
|
|
287
|
-
{
|
|
301
|
+
{
|
|
302
|
+
"mode": "webhook",
|
|
303
|
+
"url": [
|
|
304
|
+
{
|
|
305
|
+
"name": "prod_alerts",
|
|
306
|
+
"url": "https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
"name": "critical_only",
|
|
310
|
+
"url": "https://hooks.slack.com/services/YOUR/OTHER/WEBHOOK/URL"
|
|
311
|
+
}
|
|
312
|
+
],
|
|
313
|
+
"url_configs": {
|
|
314
|
+
"prod_alerts": {
|
|
315
|
+
"reachability_alerts_only": true,
|
|
316
|
+
"severities": ["high", "critical"]
|
|
317
|
+
},
|
|
318
|
+
"critical_only": {
|
|
319
|
+
"severities": ["critical"]
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
288
323
|
````
|
|
289
324
|
|
|
325
|
+
###### Bot Mode Examples
|
|
326
|
+
|
|
327
|
+
**Setting up a Slack Bot:**
|
|
328
|
+
1. Go to https://api.slack.com/apps and create a new app
|
|
329
|
+
2. Under "OAuth & Permissions", add the `chat:write` bot scope
|
|
330
|
+
3. Install the app to your workspace and copy the "Bot User OAuth Token"
|
|
331
|
+
4. Invite the bot to your channels: `/invite @YourBotName`
|
|
332
|
+
|
|
333
|
+
Basic bot configuration:
|
|
334
|
+
|
|
335
|
+
````json
|
|
336
|
+
{
|
|
337
|
+
"mode": "bot",
|
|
338
|
+
"bot_configs": [
|
|
339
|
+
{
|
|
340
|
+
"name": "security_alerts",
|
|
341
|
+
"channels": ["security-alerts", "dev-team"]
|
|
342
|
+
}
|
|
343
|
+
]
|
|
344
|
+
}
|
|
345
|
+
````
|
|
346
|
+
|
|
347
|
+
Bot with filtering (reachability-only alerts):
|
|
348
|
+
|
|
349
|
+
````json
|
|
350
|
+
{
|
|
351
|
+
"mode": "bot",
|
|
352
|
+
"bot_configs": [
|
|
353
|
+
{
|
|
354
|
+
"name": "critical_reachable",
|
|
355
|
+
"channels": ["security-critical"],
|
|
356
|
+
"severities": ["critical", "high"],
|
|
357
|
+
"reachability_alerts_only": true
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
"name": "all_alerts",
|
|
361
|
+
"channels": ["security-all"],
|
|
362
|
+
"repos": ["myorg/backend", "myorg/frontend"]
|
|
363
|
+
}
|
|
364
|
+
]
|
|
365
|
+
}
|
|
366
|
+
````
|
|
367
|
+
|
|
368
|
+
Set the bot token:
|
|
369
|
+
```bash
|
|
370
|
+
export SOCKET_SLACK_BOT_TOKEN="xoxb-your-bot-token-here"
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
**Configuration Options:**
|
|
374
|
+
|
|
375
|
+
Webhook mode (`url_configs`):
|
|
376
|
+
- `reachability_alerts_only` (boolean, default: false): When `--reach` is enabled, only send blocking alerts (error=true) from diff scans
|
|
377
|
+
- `repos` (array): Only send alerts for specific repositories (e.g., `["owner/repo1", "owner/repo2"]`)
|
|
378
|
+
- `alert_types` (array): Only send specific alert types (e.g., `["malware", "typosquat"]`)
|
|
379
|
+
- `severities` (array): Only send alerts with specific severities (e.g., `["high", "critical"]`)
|
|
380
|
+
|
|
381
|
+
Bot mode (`bot_configs` array items):
|
|
382
|
+
- `name` (string, required): Friendly name for this configuration
|
|
383
|
+
- `channels` (array, required): Channel names (without #) where alerts will be posted
|
|
384
|
+
- `severities` (array, optional): Only send alerts with specific severities (e.g., `["high", "critical"]`)
|
|
385
|
+
- `repos` (array, optional): Only send alerts for specific repositories
|
|
386
|
+
- `alert_types` (array, optional): Only send specific alert types
|
|
387
|
+
- `reachability_alerts_only` (boolean, default: false): Only send reachable vulnerabilities when using `--reach`
|
|
388
|
+
|
|
290
389
|
## Automatic Git Detection
|
|
291
390
|
|
|
292
391
|
The CLI now automatically detects repository information from your git environment, significantly simplifying usage in CI/CD pipelines:
|
|
@@ -547,7 +646,8 @@ Implementation targets:
|
|
|
547
646
|
### Environment Variables
|
|
548
647
|
|
|
549
648
|
#### Core Configuration
|
|
550
|
-
- `
|
|
649
|
+
- `SOCKET_SECURITY_API_TOKEN`: Socket Security API token (alternative to --api-token parameter)
|
|
650
|
+
- For backwards compatibility, also accepts: `SOCKET_SECURITY_API_KEY`, `SOCKET_API_KEY`, `SOCKET_API_TOKEN`
|
|
551
651
|
- `SOCKET_SDK_PATH`: Path to local socketdev repository (default: ../socketdev)
|
|
552
652
|
|
|
553
653
|
#### GitLab Integration
|
|
@@ -101,14 +101,14 @@ socketcli [-h] [--api-token API_TOKEN] [--repo REPO] [--repo-is-public] [--branc
|
|
|
101
101
|
[--only-facts-file] [--version]
|
|
102
102
|
````
|
|
103
103
|
|
|
104
|
-
If you don't want to provide the Socket API Token every time then you can use the environment variable `
|
|
104
|
+
If you don't want to provide the Socket API Token every time then you can use the environment variable `SOCKET_SECURITY_API_TOKEN`
|
|
105
105
|
|
|
106
106
|
### Parameters
|
|
107
107
|
|
|
108
108
|
#### Authentication
|
|
109
|
-
| Parameter | Required | Default | Description
|
|
110
|
-
|
|
111
|
-
| --api-token | False | | Socket Security API token (can also be set via
|
|
109
|
+
| Parameter | Required | Default | Description |
|
|
110
|
+
|:------------|:---------|:--------|:----------------------------------------------------------------------------------|
|
|
111
|
+
| --api-token | False | | Socket Security API token (can also be set via SOCKET_SECURITY_API_TOKEN env var) |
|
|
112
112
|
|
|
113
113
|
#### Repository
|
|
114
114
|
| Parameter | Required | Default | Description |
|
|
@@ -221,15 +221,113 @@ Example `SOCKET_JIRA_CONFIG_JSON` value
|
|
|
221
221
|
|
|
222
222
|
| Environment Variable | Required | Default | Description |
|
|
223
223
|
|:-------------------------|:---------|:--------|:-----------------------------------|
|
|
224
|
-
|
|
|
225
|
-
|
|
|
224
|
+
| SOCKET_SLACK_CONFIG_JSON | False | None | Slack configuration (enables plugin when set). Supports webhook or bot mode. Alternatively, use --slack-webhook CLI flag for simple webhook mode. |
|
|
225
|
+
| SOCKET_SLACK_BOT_TOKEN | False | None | Slack Bot User OAuth Token (starts with `xoxb-`). Required when using bot mode. |
|
|
226
226
|
|
|
227
|
-
|
|
227
|
+
**Slack supports two modes:**
|
|
228
|
+
|
|
229
|
+
1. **Webhook Mode** (default): Posts to incoming webhooks
|
|
230
|
+
2. **Bot Mode**: Posts via Slack API with bot token authentication
|
|
231
|
+
|
|
232
|
+
###### Webhook Mode Examples
|
|
233
|
+
|
|
234
|
+
Simple webhook:
|
|
235
|
+
|
|
236
|
+
````json
|
|
237
|
+
{"url": "https://hooks.slack.com/services/YOUR/WEBHOOK/URL"}
|
|
238
|
+
````
|
|
239
|
+
|
|
240
|
+
Multiple webhooks with advanced filtering:
|
|
228
241
|
|
|
229
242
|
````json
|
|
230
|
-
{
|
|
243
|
+
{
|
|
244
|
+
"mode": "webhook",
|
|
245
|
+
"url": [
|
|
246
|
+
{
|
|
247
|
+
"name": "prod_alerts",
|
|
248
|
+
"url": "https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
"name": "critical_only",
|
|
252
|
+
"url": "https://hooks.slack.com/services/YOUR/OTHER/WEBHOOK/URL"
|
|
253
|
+
}
|
|
254
|
+
],
|
|
255
|
+
"url_configs": {
|
|
256
|
+
"prod_alerts": {
|
|
257
|
+
"reachability_alerts_only": true,
|
|
258
|
+
"severities": ["high", "critical"]
|
|
259
|
+
},
|
|
260
|
+
"critical_only": {
|
|
261
|
+
"severities": ["critical"]
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
231
265
|
````
|
|
232
266
|
|
|
267
|
+
###### Bot Mode Examples
|
|
268
|
+
|
|
269
|
+
**Setting up a Slack Bot:**
|
|
270
|
+
1. Go to https://api.slack.com/apps and create a new app
|
|
271
|
+
2. Under "OAuth & Permissions", add the `chat:write` bot scope
|
|
272
|
+
3. Install the app to your workspace and copy the "Bot User OAuth Token"
|
|
273
|
+
4. Invite the bot to your channels: `/invite @YourBotName`
|
|
274
|
+
|
|
275
|
+
Basic bot configuration:
|
|
276
|
+
|
|
277
|
+
````json
|
|
278
|
+
{
|
|
279
|
+
"mode": "bot",
|
|
280
|
+
"bot_configs": [
|
|
281
|
+
{
|
|
282
|
+
"name": "security_alerts",
|
|
283
|
+
"channels": ["security-alerts", "dev-team"]
|
|
284
|
+
}
|
|
285
|
+
]
|
|
286
|
+
}
|
|
287
|
+
````
|
|
288
|
+
|
|
289
|
+
Bot with filtering (reachability-only alerts):
|
|
290
|
+
|
|
291
|
+
````json
|
|
292
|
+
{
|
|
293
|
+
"mode": "bot",
|
|
294
|
+
"bot_configs": [
|
|
295
|
+
{
|
|
296
|
+
"name": "critical_reachable",
|
|
297
|
+
"channels": ["security-critical"],
|
|
298
|
+
"severities": ["critical", "high"],
|
|
299
|
+
"reachability_alerts_only": true
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
"name": "all_alerts",
|
|
303
|
+
"channels": ["security-all"],
|
|
304
|
+
"repos": ["myorg/backend", "myorg/frontend"]
|
|
305
|
+
}
|
|
306
|
+
]
|
|
307
|
+
}
|
|
308
|
+
````
|
|
309
|
+
|
|
310
|
+
Set the bot token:
|
|
311
|
+
```bash
|
|
312
|
+
export SOCKET_SLACK_BOT_TOKEN="xoxb-your-bot-token-here"
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
**Configuration Options:**
|
|
316
|
+
|
|
317
|
+
Webhook mode (`url_configs`):
|
|
318
|
+
- `reachability_alerts_only` (boolean, default: false): When `--reach` is enabled, only send blocking alerts (error=true) from diff scans
|
|
319
|
+
- `repos` (array): Only send alerts for specific repositories (e.g., `["owner/repo1", "owner/repo2"]`)
|
|
320
|
+
- `alert_types` (array): Only send specific alert types (e.g., `["malware", "typosquat"]`)
|
|
321
|
+
- `severities` (array): Only send alerts with specific severities (e.g., `["high", "critical"]`)
|
|
322
|
+
|
|
323
|
+
Bot mode (`bot_configs` array items):
|
|
324
|
+
- `name` (string, required): Friendly name for this configuration
|
|
325
|
+
- `channels` (array, required): Channel names (without #) where alerts will be posted
|
|
326
|
+
- `severities` (array, optional): Only send alerts with specific severities (e.g., `["high", "critical"]`)
|
|
327
|
+
- `repos` (array, optional): Only send alerts for specific repositories
|
|
328
|
+
- `alert_types` (array, optional): Only send specific alert types
|
|
329
|
+
- `reachability_alerts_only` (boolean, default: false): Only send reachable vulnerabilities when using `--reach`
|
|
330
|
+
|
|
233
331
|
## Automatic Git Detection
|
|
234
332
|
|
|
235
333
|
The CLI now automatically detects repository information from your git environment, significantly simplifying usage in CI/CD pipelines:
|
|
@@ -490,7 +588,8 @@ Implementation targets:
|
|
|
490
588
|
### Environment Variables
|
|
491
589
|
|
|
492
590
|
#### Core Configuration
|
|
493
|
-
- `
|
|
591
|
+
- `SOCKET_SECURITY_API_TOKEN`: Socket Security API token (alternative to --api-token parameter)
|
|
592
|
+
- For backwards compatibility, also accepts: `SOCKET_SECURITY_API_KEY`, `SOCKET_API_KEY`, `SOCKET_API_TOKEN`
|
|
494
593
|
- `SOCKET_SDK_PATH`: Path to local socketdev repository (default: ../socketdev)
|
|
495
594
|
|
|
496
595
|
#### GitLab Integration
|
|
@@ -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.62"
|
|
10
10
|
requires-python = ">= 3.10"
|
|
11
11
|
license = {"file" = "LICENSE"}
|
|
12
12
|
dependencies = [
|
|
@@ -16,8 +16,9 @@ dependencies = [
|
|
|
16
16
|
'GitPython',
|
|
17
17
|
'packaging',
|
|
18
18
|
'python-dotenv',
|
|
19
|
-
|
|
19
|
+
"socketdev>=3.0.25,<4.0.0",
|
|
20
20
|
"bs4>=0.0.2",
|
|
21
|
+
"markdown>=3.10",
|
|
21
22
|
]
|
|
22
23
|
readme = "README.md"
|
|
23
24
|
description = "Socket Security CLI for CI/CD"
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Session Directions: Add Slack Bot Mode Support
|
|
2
|
+
|
|
3
|
+
## Context
|
|
4
|
+
The Socket Python CLI currently supports Slack notifications via incoming webhooks. We need to add an alternative "bot" mode that uses a Slack App with Bot Token for more flexible channel routing.
|
|
5
|
+
|
|
6
|
+
## Current Implementation
|
|
7
|
+
- File: `socketsecurity/plugins/slack.py`
|
|
8
|
+
- File: `socketsecurity/config.py`
|
|
9
|
+
- Env var: `SOCKET_SLACK_CONFIG_JSON`
|
|
10
|
+
- Current config uses `url` and `url_configs` for webhook routing
|
|
11
|
+
|
|
12
|
+
## Requirements
|
|
13
|
+
|
|
14
|
+
### 1. Add Mode Selection
|
|
15
|
+
- Add top-level `mode` field to Slack config
|
|
16
|
+
- Valid values: "webhook" (default), "bot"
|
|
17
|
+
- Mode determines which authentication and routing method to use
|
|
18
|
+
|
|
19
|
+
### 2. Webhook Mode (existing, default)
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"enabled": true,
|
|
23
|
+
"mode": "webhook",
|
|
24
|
+
"url": ["https://hooks.slack.com/..."],
|
|
25
|
+
"url_configs": {
|
|
26
|
+
"webhook_0": {"repos": ["repo1"], "severities": ["critical"]}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
Keep all existing webhook functionality unchanged.
|
|
31
|
+
|
|
32
|
+
### 3. Bot Mode (new)
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"enabled": true,
|
|
36
|
+
"mode": "bot",
|
|
37
|
+
"bot_configs": [
|
|
38
|
+
{
|
|
39
|
+
"name": "critical_alerts",
|
|
40
|
+
"channels": ["security-alerts", "critical-incidents"],
|
|
41
|
+
"repos": ["prod-app"],
|
|
42
|
+
"severities": ["critical"],
|
|
43
|
+
"reachability_alerts_only": true
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"name": "all_alerts",
|
|
47
|
+
"channels": ["dev-alerts"],
|
|
48
|
+
"severities": ["high", "medium"]
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
- New env var: `SOCKET_SLACK_BOT_TOKEN` (Bot User OAuth Token starting with `xoxb-`)
|
|
55
|
+
- Use `bot_configs` array instead of `url` + `url_configs`
|
|
56
|
+
- Each bot_config has:
|
|
57
|
+
- `name`: identifier for logging
|
|
58
|
+
- `channels`: array of Slack channel names or IDs to post to
|
|
59
|
+
- All existing filter options: `repos`, `severities`, `alert_types`, `reachability_alerts_only`, `always_send_reachability`
|
|
60
|
+
|
|
61
|
+
### 4. Channel Routing
|
|
62
|
+
- Slack API accepts both channel names (without #) and channel IDs (C1234567890)
|
|
63
|
+
- Recommend supporting both: try name first, fallback to ID if needed
|
|
64
|
+
- API endpoint: `https://slack.com/api/chat.postMessage`
|
|
65
|
+
- Request format:
|
|
66
|
+
```python
|
|
67
|
+
{
|
|
68
|
+
"channel": "channel-name", # or "C1234567890"
|
|
69
|
+
"blocks": blocks
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
- Headers: `{"Authorization": f"Bearer {bot_token}", "Content-Type": "application/json"}`
|
|
73
|
+
|
|
74
|
+
### 5. Implementation Tasks
|
|
75
|
+
|
|
76
|
+
#### config.py
|
|
77
|
+
- No changes needed (config is loaded from JSON env var)
|
|
78
|
+
|
|
79
|
+
#### slack.py
|
|
80
|
+
1. Update `send()` method:
|
|
81
|
+
- Check `self.config.get("mode", "webhook")`
|
|
82
|
+
- If "webhook": call existing `_send_webhook_alerts()` (refactor current logic)
|
|
83
|
+
- If "bot": call new `_send_bot_alerts()`
|
|
84
|
+
|
|
85
|
+
2. Create `_send_bot_alerts()` method:
|
|
86
|
+
- Get bot token from env: `os.getenv("SOCKET_SLACK_BOT_TOKEN")`
|
|
87
|
+
- Validate token exists and starts with "xoxb-"
|
|
88
|
+
- Get `bot_configs` from config
|
|
89
|
+
- For each bot_config, filter alerts same way as webhooks
|
|
90
|
+
- For each channel in bot_config's channels array, post message via chat.postMessage API
|
|
91
|
+
|
|
92
|
+
3. Create `_post_to_slack_api()` helper method:
|
|
93
|
+
- Takes bot_token, channel, blocks
|
|
94
|
+
- Posts to https://slack.com/api/chat.postMessage
|
|
95
|
+
- Returns response
|
|
96
|
+
- Log errors with channel name/ID for debugging
|
|
97
|
+
|
|
98
|
+
4. Error handling:
|
|
99
|
+
- Log if bot token missing when mode is "bot"
|
|
100
|
+
- Handle API errors (invalid channel, missing permissions, rate limits)
|
|
101
|
+
- Parse Slack API response JSON (it returns 200 with error in body)
|
|
102
|
+
|
|
103
|
+
5. Reuse existing:
|
|
104
|
+
- All filtering logic (`_filter_alerts`)
|
|
105
|
+
- All block building (`create_slack_blocks_from_diff`, `_create_reachability_slack_blocks_from_structured`)
|
|
106
|
+
- All reachability data loading
|
|
107
|
+
|
|
108
|
+
### 6. Testing Considerations
|
|
109
|
+
- Test both modes don't interfere with each other
|
|
110
|
+
- Test channel name resolution
|
|
111
|
+
- Test channel ID usage
|
|
112
|
+
- Test multiple channels per bot_config
|
|
113
|
+
- Test error handling when bot token invalid or missing
|
|
114
|
+
- Verify block count limits still respected (50 blocks)
|
|
115
|
+
|
|
116
|
+
### 7. Documentation Updates (README.md)
|
|
117
|
+
Add bot mode configuration examples and SOCKET_SLACK_BOT_TOKEN env var documentation.
|
|
118
|
+
|
|
119
|
+
## Key Files to Modify
|
|
120
|
+
1. `socketsecurity/plugins/slack.py` - main implementation
|
|
121
|
+
2. `README.md` - add bot mode documentation
|
|
122
|
+
|
|
123
|
+
## Notes
|
|
124
|
+
- Slack chat.postMessage returns HTTP 200 even on errors. Check response JSON for `"ok": false`
|
|
125
|
+
- Rate limit: 1 message per second per channel (more generous than webhooks)
|
|
126
|
+
- Channel names are case-insensitive, don't need # prefix
|
|
127
|
+
- Public and private channels both work if bot is invited
|
|
@@ -57,6 +57,7 @@ class CliConfig:
|
|
|
57
57
|
version: str = __version__
|
|
58
58
|
jira_plugin: PluginConfig = field(default_factory=PluginConfig)
|
|
59
59
|
slack_plugin: PluginConfig = field(default_factory=PluginConfig)
|
|
60
|
+
slack_webhook: Optional[str] = None
|
|
60
61
|
license_file_name: str = "license_output.json"
|
|
61
62
|
save_submitted_files_list: Optional[str] = None
|
|
62
63
|
save_manifest_tar: Optional[str] = None
|
|
@@ -85,8 +86,14 @@ class CliConfig:
|
|
|
85
86
|
parser = create_argument_parser()
|
|
86
87
|
args = parser.parse_args(args_list)
|
|
87
88
|
|
|
88
|
-
# Get API token from env or args
|
|
89
|
-
api_token =
|
|
89
|
+
# Get API token from env or args (check multiple env var names)
|
|
90
|
+
api_token = (
|
|
91
|
+
os.getenv("SOCKET_SECURITY_API_KEY") or
|
|
92
|
+
os.getenv("SOCKET_SECURITY_API_TOKEN") or
|
|
93
|
+
os.getenv("SOCKET_API_KEY") or
|
|
94
|
+
os.getenv("SOCKET_API_TOKEN") or
|
|
95
|
+
args.api_token
|
|
96
|
+
)
|
|
90
97
|
|
|
91
98
|
# Strip quotes from commit message if present
|
|
92
99
|
commit_message = args.commit_message
|
|
@@ -128,6 +135,7 @@ class CliConfig:
|
|
|
128
135
|
'save_manifest_tar': args.save_manifest_tar,
|
|
129
136
|
'sub_paths': args.sub_paths or [],
|
|
130
137
|
'workspace_name': args.workspace_name,
|
|
138
|
+
'slack_webhook': args.slack_webhook,
|
|
131
139
|
'reach': args.reach,
|
|
132
140
|
'reach_version': args.reach_version,
|
|
133
141
|
'reach_analysis_timeout': args.reach_analysis_timeout,
|
|
@@ -151,6 +159,11 @@ class CliConfig:
|
|
|
151
159
|
except json.JSONDecodeError:
|
|
152
160
|
logging.error(f"Unable to parse excluded_ecosystems: {config_args['excluded_ecosystems']}")
|
|
153
161
|
exit(1)
|
|
162
|
+
# Build Slack plugin config, merging CLI arg with env config
|
|
163
|
+
slack_config = get_plugin_config_from_env("SOCKET_SLACK")
|
|
164
|
+
if args.slack_webhook:
|
|
165
|
+
slack_config["url"] = args.slack_webhook
|
|
166
|
+
|
|
154
167
|
config_args.update({
|
|
155
168
|
"jira_plugin": PluginConfig(
|
|
156
169
|
enabled=os.getenv("SOCKET_JIRA_ENABLED", "false").lower() == "true",
|
|
@@ -158,9 +171,9 @@ class CliConfig:
|
|
|
158
171
|
config=get_plugin_config_from_env("SOCKET_JIRA")
|
|
159
172
|
),
|
|
160
173
|
"slack_plugin": PluginConfig(
|
|
161
|
-
enabled=
|
|
174
|
+
enabled=bool(slack_config) or bool(args.slack_webhook),
|
|
162
175
|
levels=os.getenv("SOCKET_SLACK_LEVELS", "block,warn").split(","),
|
|
163
|
-
config=
|
|
176
|
+
config=slack_config
|
|
164
177
|
)
|
|
165
178
|
})
|
|
166
179
|
|
|
@@ -212,7 +225,7 @@ def create_argument_parser() -> argparse.ArgumentParser:
|
|
|
212
225
|
"--api-token",
|
|
213
226
|
dest="api_token",
|
|
214
227
|
metavar="<token>",
|
|
215
|
-
help="Socket Security API token (can also be set via
|
|
228
|
+
help="Socket Security API token (can also be set via SOCKET_SECURITY_API_TOKEN env var)",
|
|
216
229
|
required=False
|
|
217
230
|
)
|
|
218
231
|
auth_group.add_argument(
|
|
@@ -475,6 +488,15 @@ def create_argument_parser() -> argparse.ArgumentParser:
|
|
|
475
488
|
help=argparse.SUPPRESS
|
|
476
489
|
)
|
|
477
490
|
|
|
491
|
+
# Plugin Configuration
|
|
492
|
+
plugin_group = parser.add_argument_group('Plugin Configuration')
|
|
493
|
+
plugin_group.add_argument(
|
|
494
|
+
"--slack-webhook",
|
|
495
|
+
dest="slack_webhook",
|
|
496
|
+
metavar="<url>",
|
|
497
|
+
help="Slack webhook URL for notifications (automatically enables Slack plugin)"
|
|
498
|
+
)
|
|
499
|
+
|
|
478
500
|
# Advanced Configuration
|
|
479
501
|
advanced_group = parser.add_argument_group('Advanced Configuration')
|
|
480
502
|
advanced_group.add_argument(
|
|
@@ -553,7 +553,10 @@ class Core:
|
|
|
553
553
|
|
|
554
554
|
# Finalize tier1 scan if reachability analysis was enabled
|
|
555
555
|
if self.cli_config and self.cli_config.reach:
|
|
556
|
-
facts_file_path =
|
|
556
|
+
facts_file_path = os.path.join(
|
|
557
|
+
self.cli_config.target_path or ".",
|
|
558
|
+
self.cli_config.reach_output_file
|
|
559
|
+
)
|
|
557
560
|
log.debug(f"Reachability analysis enabled, finalizing tier1 scan for full scan {full_scan.id}")
|
|
558
561
|
try:
|
|
559
562
|
success = self.finalize_tier1_scan(full_scan.id, facts_file_path)
|