pysentry-rs 0.2.0__tar.gz → 0.2.1__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.

Potentially problematic release.


This version of pysentry-rs might be problematic. Click here for more details.

Files changed (46) hide show
  1. pysentry_rs-0.2.1/.github/FUNDING.yml +1 -0
  2. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/.github/workflows/ci.yml +12 -10
  3. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/Cargo.lock +1 -1
  4. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/Cargo.toml +1 -1
  5. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/PKG-INFO +60 -25
  6. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/README.md +59 -24
  7. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/python/pysentry/__init__.py +114 -9
  8. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/main.rs +376 -28
  9. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/output/report.rs +292 -0
  10. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/parsers/poetry_lock.rs +67 -2
  11. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/providers/osv.rs +286 -21
  12. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/python.rs +56 -12
  13. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/types.rs +1 -0
  14. pysentry_rs-0.2.1/src/vulnerability/database.rs +439 -0
  15. pysentry_rs-0.2.0/src/vulnerability/database.rs +0 -163
  16. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/.github/dependabot.yml +0 -0
  17. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/.github/workflows/release.yml +0 -0
  18. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/.gitignore +0 -0
  19. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/.pre-commit-config.yaml +0 -0
  20. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/LICENSE +0 -0
  21. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/fixtures/requirements-tests/requirements-dev.txt +0 -0
  22. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/fixtures/requirements-tests/requirements.txt +0 -0
  23. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/fixtures/requirements-tests-vulnerable/requirements.txt +0 -0
  24. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/pyproject.toml +0 -0
  25. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/python/pysentry/__main__.py +0 -0
  26. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/cache/audit.rs +0 -0
  27. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/cache/mod.rs +0 -0
  28. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/cache/storage.rs +0 -0
  29. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/dependency/mod.rs +0 -0
  30. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/dependency/resolvers/mod.rs +0 -0
  31. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/dependency/resolvers/pip_tools.rs +0 -0
  32. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/dependency/resolvers/uv.rs +0 -0
  33. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/dependency/scanner.rs +0 -0
  34. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/error.rs +0 -0
  35. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/lib.rs +0 -0
  36. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/output/mod.rs +0 -0
  37. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/output/sarif.rs +0 -0
  38. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/parsers/lock.rs +0 -0
  39. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/parsers/mod.rs +0 -0
  40. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/parsers/pyproject.rs +0 -0
  41. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/parsers/requirements.rs +0 -0
  42. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/providers/mod.rs +0 -0
  43. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/providers/pypa.rs +0 -0
  44. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/providers/pypi.rs +0 -0
  45. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/vulnerability/matcher.rs +0 -0
  46. {pysentry_rs-0.2.0 → pysentry_rs-0.2.1}/src/vulnerability/mod.rs +0 -0
@@ -0,0 +1 @@
1
+ buy_me_a_coffee: nyudenkov
@@ -4,19 +4,21 @@ on:
4
4
  push:
5
5
  branches: [main]
6
6
  paths-ignore:
7
- - '**.md'
8
- - 'LICENSE'
9
- - '.gitignore'
10
- - '.editorconfig'
11
- - '.github/dependabot.yml'
7
+ - "**.md"
8
+ - "LICENSE"
9
+ - ".gitignore"
10
+ - ".editorconfig"
11
+ - ".github/dependabot.yml"
12
+ - ".github/FUNDING.yml"
12
13
  pull_request:
13
14
  branches: [main]
14
15
  paths-ignore:
15
- - '**.md'
16
- - 'LICENSE'
17
- - '.gitignore'
18
- - '.editorconfig'
19
- - '.github/dependabot.yml'
16
+ - "**.md"
17
+ - "LICENSE"
18
+ - ".gitignore"
19
+ - ".editorconfig"
20
+ - ".github/dependabot.yml"
21
+ - ".github/FUNDING.yml"
20
22
 
21
23
  env:
22
24
  CARGO_TERM_COLOR: always
@@ -1067,7 +1067,7 @@ dependencies = [
1067
1067
 
1068
1068
  [[package]]
1069
1069
  name = "pysentry"
1070
- version = "0.2.0"
1070
+ version = "0.2.1"
1071
1071
  dependencies = [
1072
1072
  "anyhow",
1073
1073
  "async-trait",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "pysentry"
3
- version = "0.2.0"
3
+ version = "0.2.1"
4
4
  edition = "2021"
5
5
  rust-version = "1.79"
6
6
  description = "Security vulnerability auditing for Python packages"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pysentry-rs
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
@@ -26,6 +26,8 @@ Project-URL: Issues, https://github.com/nyudenkov/pysentry/issues
26
26
 
27
27
  # 🐍 PySentry
28
28
 
29
+ [![OSV Integration](https://img.shields.io/badge/OSV-Integrated-blue)](https://google.github.io/osv.dev/)
30
+
29
31
  [Help to test and improve](https://github.com/nyudenkov/pysentry/issues/12)
30
32
 
31
33
  A fast, reliable security vulnerability scanner for Python projects, written in Rust.
@@ -42,7 +44,7 @@ PySentry audits Python projects for known security vulnerabilities by analyzing
42
44
  - PyPA Advisory Database (default)
43
45
  - PyPI JSON API
44
46
  - OSV.dev (Open Source Vulnerabilities)
45
- - **Flexible Output**: Human-readable, JSON, and SARIF formats
47
+ - **Flexible Output for different workflows**: Human-readable, JSON, SARIF, and Markdown formats
46
48
  - **Performance Focused**:
47
49
  - Written in Rust for speed
48
50
  - Async/concurrent processing
@@ -197,7 +199,7 @@ pysentry --resolver uv /path/to/project
197
199
  pysentry --resolver pip-tools /path/to/project
198
200
 
199
201
  # Include all dependencies (main + dev + optional)
200
- pysentry --all
202
+ pysentry --all-extras
201
203
 
202
204
  # Filter by severity (only show high and critical)
203
205
  pysentry --severity high
@@ -210,14 +212,22 @@ pysentry --format json --output audit-results.json
210
212
 
211
213
  ```bash
212
214
  # Using uvx for comprehensive audit
213
- uvx pysentry-rs --all --format sarif --output security-report.sarif
215
+ uvx pysentry-rs --all-extras --format sarif --output security-report.sarif
216
+
217
+ # Check multiple vulnerability sources concurrently
218
+ uvx pysentry-rs --sources pypa,osv,pypi /path/to/project
219
+ uvx pysentry-rs --sources pypa --sources osv --sources pypi
214
220
 
215
- # Check only direct dependencies using OSV database
216
- uvx pysentry-rs --direct-only --source osv
221
+ # Generate markdown report
222
+ uvx pysentry-rs --format markdown --output security-report.md
223
+
224
+ # Control CI exit codes - only fail on critical vulnerabilities
225
+ uvx pysentry-rs --fail-on critical
217
226
 
218
227
  # Or with installed binary
219
- pysentry --all --format sarif --output security-report.sarif
220
- pysentry --direct-only --source osv
228
+ pysentry --all-extras --format sarif --output security-report.sarif
229
+ pysentry --sources pypa,osv --direct-only
230
+ pysentry --format markdown --output security-report.md
221
231
 
222
232
  # Ignore specific vulnerabilities
223
233
  pysentry --ignore CVE-2023-12345 --ignore GHSA-xxxx-yyyy-zzzz
@@ -246,25 +256,45 @@ pysentry /path/to/project
246
256
  pysentry --verbose --resolver uv /path/to/project
247
257
  ```
248
258
 
259
+ ### CI/CD Integration Examples
260
+
261
+ ```bash
262
+ # Development environment - only fail on critical vulnerabilities
263
+ pysentry --fail-on critical --format json --output security-report.json
264
+
265
+ # Staging environment - fail on high+ vulnerabilities
266
+ pysentry --fail-on high --sources pypa,osv --format sarif --output security.sarif
267
+
268
+ # Production deployment - strict security (fail on medium+, default)
269
+ pysentry --sources pypa,pypi,osv --format json --output prod-security.json
270
+
271
+ # Generate markdown report for GitHub issues/PRs
272
+ pysentry --format markdown --output SECURITY-REPORT.md
273
+
274
+ # Comprehensive audit with all sources and full reporting
275
+ pysentry --sources pypa,pypi,osv --all-extras --format json --fail-on low
276
+ ```
277
+
249
278
  ## Configuration
250
279
 
251
280
  ### Command Line Options
252
281
 
253
- | Option | Description | Default |
254
- | ---------------- | ----------------------------------------------------- | ------------------- |
255
- | `--format` | Output format: `human`, `json`, `sarif` | `human` |
256
- | `--severity` | Minimum severity: `low`, `medium`, `high`, `critical` | `low` |
257
- | `--source` | Vulnerability source: `pypa`, `pypi`, `osv` | `pypa` |
258
- | `--all` | Include all dependencies (main + dev + optional) | `false` |
259
- | `--direct-only` | Check only direct dependencies | `false` |
260
- | `--ignore` | Vulnerability IDs to ignore (repeatable) | `[]` |
261
- | `--output` | Output file path | `stdout` |
262
- | `--no-cache` | Disable caching | `false` |
263
- | `--cache-dir` | Custom cache directory | `~/.cache/pysentry` |
264
- | `--verbose` | Enable verbose output | `false` |
265
- | `--quiet` | Suppress non-error output | `false` |
266
- | `--resolver` | Dependency resolver: `auto`, `uv`, `pip-tools` | `auto` |
267
- | `--requirements` | Additional requirements files (repeatable) | `[]` |
282
+ | Option | Description | Default |
283
+ | ---------------- | ------------------------------------------------------- | ------------------- |
284
+ | `--format` | Output format: `human`, `json`, `sarif`, `markdown` | `human` |
285
+ | `--severity` | Minimum severity: `low`, `medium`, `high`, `critical` | `low` |
286
+ | `--fail-on` | Fail (exit non-zero) on vulnerabilities ≥ severity | `medium` |
287
+ | `--sources` | Vulnerability sources: `pypa`, `pypi`, `osv` (multiple) | `pypa` |
288
+ | `--all-extras` | Include all dependencies (main + dev + optional) | `false` |
289
+ | `--direct-only` | Check only direct dependencies | `false` |
290
+ | `--ignore` | Vulnerability IDs to ignore (repeatable) | `[]` |
291
+ | `--output` | Output file path | `stdout` |
292
+ | `--no-cache` | Disable caching | `false` |
293
+ | `--cache-dir` | Custom cache directory | `~/.cache/pysentry` |
294
+ | `--verbose` | Enable verbose output | `false` |
295
+ | `--quiet` | Suppress non-error output | `false` |
296
+ | `--resolver` | Dependency resolver: `auto`, `uv`, `pip-tools` | `auto` |
297
+ | `--requirements` | Additional requirements files (repeatable) | `[]` |
268
298
 
269
299
  ### Cache Management
270
300
 
@@ -376,6 +406,10 @@ Support for projects without lock files:
376
406
 
377
407
  Most comfortable to read.
378
408
 
409
+ ### Markdown
410
+
411
+ GitHub-friendly format with structured sections and severity indicators. Perfect for documentation, GitHub issues, and security reports.
412
+
379
413
  ### JSON
380
414
 
381
415
  ```json
@@ -510,8 +544,9 @@ pysentry --verbose /path/to/project
510
544
  # Check network connectivity
511
545
  curl -I https://osv-vulnerabilities.storage.googleapis.com/
512
546
 
513
- # Try with different source
514
- pysentry --source pypi
547
+ # Try with different or multiple sources
548
+ pysentry --sources pypi
549
+ pysentry --sources pypa,osv
515
550
  ```
516
551
 
517
552
  **Slow requirements.txt resolution**
@@ -1,5 +1,7 @@
1
1
  # 🐍 PySentry
2
2
 
3
+ [![OSV Integration](https://img.shields.io/badge/OSV-Integrated-blue)](https://google.github.io/osv.dev/)
4
+
3
5
  [Help to test and improve](https://github.com/nyudenkov/pysentry/issues/12)
4
6
 
5
7
  A fast, reliable security vulnerability scanner for Python projects, written in Rust.
@@ -16,7 +18,7 @@ PySentry audits Python projects for known security vulnerabilities by analyzing
16
18
  - PyPA Advisory Database (default)
17
19
  - PyPI JSON API
18
20
  - OSV.dev (Open Source Vulnerabilities)
19
- - **Flexible Output**: Human-readable, JSON, and SARIF formats
21
+ - **Flexible Output for different workflows**: Human-readable, JSON, SARIF, and Markdown formats
20
22
  - **Performance Focused**:
21
23
  - Written in Rust for speed
22
24
  - Async/concurrent processing
@@ -171,7 +173,7 @@ pysentry --resolver uv /path/to/project
171
173
  pysentry --resolver pip-tools /path/to/project
172
174
 
173
175
  # Include all dependencies (main + dev + optional)
174
- pysentry --all
176
+ pysentry --all-extras
175
177
 
176
178
  # Filter by severity (only show high and critical)
177
179
  pysentry --severity high
@@ -184,14 +186,22 @@ pysentry --format json --output audit-results.json
184
186
 
185
187
  ```bash
186
188
  # Using uvx for comprehensive audit
187
- uvx pysentry-rs --all --format sarif --output security-report.sarif
189
+ uvx pysentry-rs --all-extras --format sarif --output security-report.sarif
190
+
191
+ # Check multiple vulnerability sources concurrently
192
+ uvx pysentry-rs --sources pypa,osv,pypi /path/to/project
193
+ uvx pysentry-rs --sources pypa --sources osv --sources pypi
188
194
 
189
- # Check only direct dependencies using OSV database
190
- uvx pysentry-rs --direct-only --source osv
195
+ # Generate markdown report
196
+ uvx pysentry-rs --format markdown --output security-report.md
197
+
198
+ # Control CI exit codes - only fail on critical vulnerabilities
199
+ uvx pysentry-rs --fail-on critical
191
200
 
192
201
  # Or with installed binary
193
- pysentry --all --format sarif --output security-report.sarif
194
- pysentry --direct-only --source osv
202
+ pysentry --all-extras --format sarif --output security-report.sarif
203
+ pysentry --sources pypa,osv --direct-only
204
+ pysentry --format markdown --output security-report.md
195
205
 
196
206
  # Ignore specific vulnerabilities
197
207
  pysentry --ignore CVE-2023-12345 --ignore GHSA-xxxx-yyyy-zzzz
@@ -220,25 +230,45 @@ pysentry /path/to/project
220
230
  pysentry --verbose --resolver uv /path/to/project
221
231
  ```
222
232
 
233
+ ### CI/CD Integration Examples
234
+
235
+ ```bash
236
+ # Development environment - only fail on critical vulnerabilities
237
+ pysentry --fail-on critical --format json --output security-report.json
238
+
239
+ # Staging environment - fail on high+ vulnerabilities
240
+ pysentry --fail-on high --sources pypa,osv --format sarif --output security.sarif
241
+
242
+ # Production deployment - strict security (fail on medium+, default)
243
+ pysentry --sources pypa,pypi,osv --format json --output prod-security.json
244
+
245
+ # Generate markdown report for GitHub issues/PRs
246
+ pysentry --format markdown --output SECURITY-REPORT.md
247
+
248
+ # Comprehensive audit with all sources and full reporting
249
+ pysentry --sources pypa,pypi,osv --all-extras --format json --fail-on low
250
+ ```
251
+
223
252
  ## Configuration
224
253
 
225
254
  ### Command Line Options
226
255
 
227
- | Option | Description | Default |
228
- | ---------------- | ----------------------------------------------------- | ------------------- |
229
- | `--format` | Output format: `human`, `json`, `sarif` | `human` |
230
- | `--severity` | Minimum severity: `low`, `medium`, `high`, `critical` | `low` |
231
- | `--source` | Vulnerability source: `pypa`, `pypi`, `osv` | `pypa` |
232
- | `--all` | Include all dependencies (main + dev + optional) | `false` |
233
- | `--direct-only` | Check only direct dependencies | `false` |
234
- | `--ignore` | Vulnerability IDs to ignore (repeatable) | `[]` |
235
- | `--output` | Output file path | `stdout` |
236
- | `--no-cache` | Disable caching | `false` |
237
- | `--cache-dir` | Custom cache directory | `~/.cache/pysentry` |
238
- | `--verbose` | Enable verbose output | `false` |
239
- | `--quiet` | Suppress non-error output | `false` |
240
- | `--resolver` | Dependency resolver: `auto`, `uv`, `pip-tools` | `auto` |
241
- | `--requirements` | Additional requirements files (repeatable) | `[]` |
256
+ | Option | Description | Default |
257
+ | ---------------- | ------------------------------------------------------- | ------------------- |
258
+ | `--format` | Output format: `human`, `json`, `sarif`, `markdown` | `human` |
259
+ | `--severity` | Minimum severity: `low`, `medium`, `high`, `critical` | `low` |
260
+ | `--fail-on` | Fail (exit non-zero) on vulnerabilities ≥ severity | `medium` |
261
+ | `--sources` | Vulnerability sources: `pypa`, `pypi`, `osv` (multiple) | `pypa` |
262
+ | `--all-extras` | Include all dependencies (main + dev + optional) | `false` |
263
+ | `--direct-only` | Check only direct dependencies | `false` |
264
+ | `--ignore` | Vulnerability IDs to ignore (repeatable) | `[]` |
265
+ | `--output` | Output file path | `stdout` |
266
+ | `--no-cache` | Disable caching | `false` |
267
+ | `--cache-dir` | Custom cache directory | `~/.cache/pysentry` |
268
+ | `--verbose` | Enable verbose output | `false` |
269
+ | `--quiet` | Suppress non-error output | `false` |
270
+ | `--resolver` | Dependency resolver: `auto`, `uv`, `pip-tools` | `auto` |
271
+ | `--requirements` | Additional requirements files (repeatable) | `[]` |
242
272
 
243
273
  ### Cache Management
244
274
 
@@ -350,6 +380,10 @@ Support for projects without lock files:
350
380
 
351
381
  Most comfortable to read.
352
382
 
383
+ ### Markdown
384
+
385
+ GitHub-friendly format with structured sections and severity indicators. Perfect for documentation, GitHub issues, and security reports.
386
+
353
387
  ### JSON
354
388
 
355
389
  ```json
@@ -484,8 +518,9 @@ pysentry --verbose /path/to/project
484
518
  # Check network connectivity
485
519
  curl -I https://osv-vulnerabilities.storage.googleapis.com/
486
520
 
487
- # Try with different source
488
- pysentry --source pypi
521
+ # Try with different or multiple sources
522
+ pysentry --sources pypi
523
+ pysentry --sources pypa,osv
489
524
  ```
490
525
 
491
526
  **Slow requirements.txt resolution**
@@ -2,7 +2,7 @@
2
2
 
3
3
  from ._internal import audit_python, audit_with_options, check_resolvers, check_version
4
4
 
5
- __version__ = "0.2.0"
5
+ __version__ = "0.2.1"
6
6
  __all__ = [
7
7
  "audit_python",
8
8
  "audit_with_options",
@@ -12,11 +12,74 @@ __all__ = [
12
12
  ]
13
13
 
14
14
 
15
+ def resolve_sources(source, sources_list):
16
+ import sys
17
+
18
+ resolved_sources = []
19
+
20
+ if sources_list:
21
+ for source_arg in sources_list:
22
+ for source_str in source_arg.split(","):
23
+ source_str = source_str.strip()
24
+ if not source_str:
25
+ continue
26
+ if source_str not in ["pypa", "pypi", "osv"]:
27
+ print(
28
+ f"Error: Invalid vulnerability source: '{source_str}'. Valid sources: pypa, pypi, osv",
29
+ file=sys.stderr,
30
+ )
31
+ sys.exit(1)
32
+ resolved_sources.append(source_str)
33
+
34
+ if not resolved_sources:
35
+ if source != "pypa":
36
+ print(
37
+ "Warning: --source flag is deprecated and will be removed in a future version. Use --sources instead.",
38
+ file=sys.stderr,
39
+ )
40
+ resolved_sources.append(source)
41
+ else:
42
+ resolved_sources.append("pypa")
43
+
44
+ unique_sources = []
45
+ for src in resolved_sources:
46
+ if src not in unique_sources:
47
+ unique_sources.append(src)
48
+
49
+ return unique_sources
50
+
51
+
15
52
  def main():
16
53
  """CLI entry point."""
17
54
  import sys
18
55
  import argparse
19
56
 
57
+ # Global flag to track if deprecation warning has been shown
58
+ _deprecation_warning_shown = False
59
+
60
+ def handle_all_flags(args):
61
+ """Handle the deprecated --all flag and new --all-extras flag with appropriate warnings."""
62
+ nonlocal _deprecation_warning_shown
63
+
64
+ if args.all and getattr(args, "all_extras", False):
65
+ if not _deprecation_warning_shown:
66
+ print(
67
+ "Warning: Both --all and --all-extras flags are specified. Using --all-extras only. The --all flag is deprecated.",
68
+ file=sys.stderr,
69
+ )
70
+ _deprecation_warning_shown = True
71
+ return True
72
+ elif args.all:
73
+ if not _deprecation_warning_shown:
74
+ print(
75
+ "Warning: --all flag is deprecated and will be removed in a future version. Use --all-extras instead.",
76
+ file=sys.stderr,
77
+ )
78
+ _deprecation_warning_shown = True
79
+ return True
80
+ else:
81
+ return getattr(args, "all_extras", False)
82
+
20
83
  # Handle subcommands manually to match Rust CLI structure exactly
21
84
  if len(sys.argv) > 1:
22
85
  if sys.argv[1] == "resolvers":
@@ -85,9 +148,9 @@ def main():
85
148
  )
86
149
  parser.add_argument(
87
150
  "--format",
88
- choices=["human", "json", "sarif"],
151
+ choices=["human", "json", "sarif", "markdown"],
89
152
  default="human",
90
- help="Output format [default: human] [possible values: human, json, sarif]",
153
+ help="Output format [default: human] [possible values: human, json, sarif, markdown]",
91
154
  )
92
155
  parser.add_argument(
93
156
  "--severity",
@@ -95,6 +158,12 @@ def main():
95
158
  default="low",
96
159
  help="Minimum severity level to report [default: low] [possible values: low, medium, high, critical]",
97
160
  )
161
+ parser.add_argument(
162
+ "--fail-on",
163
+ choices=["low", "medium", "high", "critical"],
164
+ default="medium",
165
+ help="Fail (exit non-zero) if vulnerabilities of this severity or higher are found [default: medium] [possible values: low, medium, high, critical]",
166
+ )
98
167
  parser.add_argument(
99
168
  "--ignore",
100
169
  action="append",
@@ -108,7 +177,12 @@ def main():
108
177
  parser.add_argument(
109
178
  "--all",
110
179
  action="store_true",
111
- help="Include ALL dependencies (main + dev, optional, etc)",
180
+ help=argparse.SUPPRESS, # Hide deprecated flag from help
181
+ )
182
+ parser.add_argument(
183
+ "--all-extras",
184
+ action="store_true",
185
+ help="Include ALL extra dependencies (main + dev, optional, etc)",
112
186
  )
113
187
  parser.add_argument(
114
188
  "--direct-only",
@@ -121,7 +195,12 @@ def main():
121
195
  "--source",
122
196
  choices=["pypa", "pypi", "osv"],
123
197
  default="pypa",
124
- help="Vulnerability data source [default: pypa] [possible values: pypa, pypi, osv]",
198
+ help="Vulnerability data source [DEPRECATED: use --sources instead] [default: pypa] [possible values: pypa, pypi, osv]",
199
+ )
200
+ parser.add_argument(
201
+ "--sources",
202
+ action="append",
203
+ help="Vulnerability data sources (can be specified multiple times or comma-separated)",
125
204
  )
126
205
  parser.add_argument(
127
206
  "--resolver",
@@ -153,14 +232,19 @@ Commands:
153
232
  args = parser.parse_args()
154
233
 
155
234
  try:
156
- # Main audit functionality - convert --all to dev/optional
157
- dev = args.all
158
- optional = args.all
235
+ # Main audit functionality - handle deprecated --all flag and new --all-extras flag
236
+ include_all = handle_all_flags(args)
237
+ dev = include_all
238
+ optional = include_all
239
+
240
+ resolved_sources = resolve_sources(
241
+ args.source, getattr(args, "sources", None) or []
242
+ )
159
243
 
160
244
  result = audit_with_options(
161
245
  path=args.path,
162
246
  format=args.format,
163
- source=args.source,
247
+ sources=resolved_sources,
164
248
  min_severity=args.severity,
165
249
  ignore_ids=args.ignore_ids,
166
250
  output=args.output,
@@ -178,6 +262,27 @@ Commands:
178
262
  if not args.output:
179
263
  print(result)
180
264
 
265
+ if args.format == "json":
266
+ import json
267
+
268
+ try:
269
+ report_data = json.loads(result)
270
+ vulnerabilities = report_data.get("vulnerabilities", [])
271
+
272
+ severity_levels = {"low": 1, "medium": 2, "high": 3, "critical": 4}
273
+ fail_on_level = severity_levels.get(args.fail_on, 2) # default medium
274
+
275
+ for vuln in vulnerabilities:
276
+ vuln_severity = vuln.get("severity", "low").lower()
277
+ vuln_level = severity_levels.get(vuln_severity, 1)
278
+ if vuln_level >= fail_on_level:
279
+ sys.exit(1)
280
+
281
+ except (json.JSONDecodeError, KeyError):
282
+ pass
283
+ else:
284
+ pass
285
+
181
286
  except Exception as e:
182
287
  print(f"Error: {e}", file=sys.stderr)
183
288
  sys.exit(1)