owasp-depscan 5.0.2__tar.gz → 5.0.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of owasp-depscan might be problematic. Click here for more details.

Files changed (86) hide show
  1. {owasp-depscan-5.0.2/owasp_depscan.egg-info → owasp-depscan-5.0.4}/PKG-INFO +11 -6
  2. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/README.md +9 -4
  3. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/depscan/cli.py +42 -15
  4. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/depscan/lib/analysis.py +9 -3
  5. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/depscan/lib/audit.py +3 -1
  6. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/depscan/lib/csaf.py +20 -7
  7. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/depscan/lib/normalize.py +10 -8
  8. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4/owasp_depscan.egg-info}/PKG-INFO +11 -6
  9. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/owasp_depscan.egg-info/requires.txt +1 -1
  10. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/pyproject.toml +2 -2
  11. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/test/test_csaf.py +255 -484
  12. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/LICENSE +0 -0
  13. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/MANIFEST.in +0 -0
  14. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/depscan/__init__.py +0 -0
  15. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/depscan/lib/__init__.py +0 -0
  16. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/depscan/lib/bom.py +0 -0
  17. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/depscan/lib/config.py +0 -0
  18. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/depscan/lib/explainer.py +0 -0
  19. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/depscan/lib/github.py +0 -0
  20. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/depscan/lib/license.py +0 -0
  21. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/depscan/lib/logger.py +0 -0
  22. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/depscan/lib/pkg_query.py +0 -0
  23. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/depscan/lib/utils.py +0 -0
  24. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/owasp_depscan.egg-info/SOURCES.txt +0 -0
  25. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/owasp_depscan.egg-info/dependency_links.txt +0 -0
  26. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/owasp_depscan.egg-info/entry_points.txt +0 -0
  27. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/owasp_depscan.egg-info/top_level.txt +0 -0
  28. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/setup.cfg +0 -0
  29. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/test/test_analysis.py +0 -0
  30. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/test/test_bom.py +0 -0
  31. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/test/test_explainer.py +0 -0
  32. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/test/test_github.py +0 -0
  33. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/test/test_license.py +0 -0
  34. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/test/test_norm.py +0 -0
  35. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/test/test_pkg_query.py +0 -0
  36. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/test/test_utils.py +0 -0
  37. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/__init__.py +0 -0
  38. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_data/fields.yml +0 -0
  39. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_data/meta.yml +0 -0
  40. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_data/rules.yml +0 -0
  41. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/0bsd.txt +0 -0
  42. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/afl-3.0.txt +0 -0
  43. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/agpl-3.0.txt +0 -0
  44. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/apache-2.0.txt +0 -0
  45. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/artistic-2.0.txt +0 -0
  46. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/bsd-2-clause.txt +0 -0
  47. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/bsd-3-clause-clear.txt +0 -0
  48. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/bsd-3-clause.txt +0 -0
  49. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/bsd-4-clause.txt +0 -0
  50. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/bsl-1.0.txt +0 -0
  51. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/cc-by-4.0.txt +0 -0
  52. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/cc-by-sa-4.0.txt +0 -0
  53. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/cc0-1.0.txt +0 -0
  54. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/cecill-2.1.txt +0 -0
  55. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/cern-ohl-p-2.0.txt +0 -0
  56. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/cern-ohl-s-2.0.txt +0 -0
  57. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/cern-ohl-w-2.0.txt +0 -0
  58. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/ecl-2.0.txt +0 -0
  59. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/epl-1.0.txt +0 -0
  60. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/epl-2.0.txt +0 -0
  61. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/eupl-1.1.txt +0 -0
  62. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/eupl-1.2.txt +0 -0
  63. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/gfdl-1.3.txt +0 -0
  64. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/gpl-2.0.txt +0 -0
  65. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/gpl-3.0.txt +0 -0
  66. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/isc.txt +0 -0
  67. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/lgpl-2.1.txt +0 -0
  68. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/lgpl-3.0.txt +0 -0
  69. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/lppl-1.3c.txt +0 -0
  70. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/mit-0.txt +0 -0
  71. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/mit.txt +0 -0
  72. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/mpl-2.0.txt +0 -0
  73. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/ms-pl.txt +0 -0
  74. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/ms-rl.txt +0 -0
  75. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/mulanpsl-2.0.txt +0 -0
  76. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/ncsa.txt +0 -0
  77. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/odbl-1.0.txt +0 -0
  78. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/ofl-1.1.txt +0 -0
  79. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/osl-3.0.txt +0 -0
  80. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/postgresql.txt +0 -0
  81. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/unlicense.txt +0 -0
  82. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/upl-1.0.txt +0 -0
  83. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/vim.txt +0 -0
  84. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/wtfpl.txt +0 -0
  85. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/choosealicense.com/_licenses/zlib.txt +0 -0
  86. {owasp-depscan-5.0.2 → owasp-depscan-5.0.4}/vendor/spdx/json/licenses.json +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: owasp-depscan
3
- Version: 5.0.2
3
+ Version: 5.0.4
4
4
  Summary: Fully open-source security audit for project dependencies based on known vulnerabilities and advisories.
5
5
  Author-email: Team AppThreat <cloud@appthreat.com>
6
6
  License: MIT
@@ -20,7 +20,7 @@ Classifier: Topic :: Utilities
20
20
  Requires-Python: >=3.8
21
21
  Description-Content-Type: text/markdown
22
22
  License-File: LICENSE
23
- Requires-Dist: appthreat-vulnerability-db>=5.5.4
23
+ Requires-Dist: appthreat-vulnerability-db>=5.5.5
24
24
  Requires-Dist: defusedxml
25
25
  Requires-Dist: oras
26
26
  Requires-Dist: PyYAML
@@ -147,22 +147,26 @@ Use the `/scan` endpoint to perform scans.
147
147
  > [!NOTE]
148
148
  > The `type` parameter is mandatory in server mode.
149
149
 
150
- * Scanning a local directory.
150
+ - Scanning a local directory.
151
+
151
152
  ```bash
152
153
  curl --json '{"path": "/tmp/vulnerable-aws-koa-app", "type": "js"}' http://0.0.0.0:7070/scan
153
154
  ```
154
155
 
155
- * Scanning a SBOM file (present locally).
156
+ - Scanning a SBOM file (present locally).
157
+
156
158
  ```bash
157
159
  curl --json '{"path": "/tmp/vulnerable-aws-koa-app/sbom_file.json", "type": "js"}' http://0.0.0.0:7070/scan
158
160
  ```
159
161
 
160
- * Scanning a GitHub repo.
162
+ - Scanning a GitHub repo.
163
+
161
164
  ```bash
162
165
  curl --json '{"url": "https://github.com/HooliCorp/vulnerable-aws-koa-app", "type": "js"}' http://0.0.0.0:7070/scan -o app.vdr.json
163
166
  ```
164
167
 
165
- * Uploading a SBOM file and generating results based on it.
168
+ - Uploading a SBOM file and generating results based on it.
169
+
166
170
  ```bash
167
171
  curl -X POST -H 'Content-Type: multipart/form-data' -F 'file=@/tmp/app/sbom_file.json' http://0.0.0.0:7070/scan?type=js
168
172
  ```
@@ -242,6 +246,7 @@ options:
242
246
  --explain Makes depscan to explain the various analysis. Useful for creating detailed reports.
243
247
  --reachables-slices-file REACHABLES_SLICES_FILE
244
248
  Path for the reachables slices file created by atom.
249
+ --purl SEARCH_PURL Scan a single package url.
245
250
  -v, --version Display the version
246
251
  ```
247
252
 
@@ -108,22 +108,26 @@ Use the `/scan` endpoint to perform scans.
108
108
  > [!NOTE]
109
109
  > The `type` parameter is mandatory in server mode.
110
110
 
111
- * Scanning a local directory.
111
+ - Scanning a local directory.
112
+
112
113
  ```bash
113
114
  curl --json '{"path": "/tmp/vulnerable-aws-koa-app", "type": "js"}' http://0.0.0.0:7070/scan
114
115
  ```
115
116
 
116
- * Scanning a SBOM file (present locally).
117
+ - Scanning a SBOM file (present locally).
118
+
117
119
  ```bash
118
120
  curl --json '{"path": "/tmp/vulnerable-aws-koa-app/sbom_file.json", "type": "js"}' http://0.0.0.0:7070/scan
119
121
  ```
120
122
 
121
- * Scanning a GitHub repo.
123
+ - Scanning a GitHub repo.
124
+
122
125
  ```bash
123
126
  curl --json '{"url": "https://github.com/HooliCorp/vulnerable-aws-koa-app", "type": "js"}' http://0.0.0.0:7070/scan -o app.vdr.json
124
127
  ```
125
128
 
126
- * Uploading a SBOM file and generating results based on it.
129
+ - Uploading a SBOM file and generating results based on it.
130
+
127
131
  ```bash
128
132
  curl -X POST -H 'Content-Type: multipart/form-data' -F 'file=@/tmp/app/sbom_file.json' http://0.0.0.0:7070/scan?type=js
129
133
  ```
@@ -203,6 +207,7 @@ options:
203
207
  --explain Makes depscan to explain the various analysis. Useful for creating detailed reports.
204
208
  --reachables-slices-file REACHABLES_SLICES_FILE
205
209
  Path for the reachables slices file created by atom.
210
+ --purl SEARCH_PURL Scan a single package url.
206
211
  -v, --version Display the version
207
212
  ```
208
213
 
@@ -298,6 +298,11 @@ def build_args():
298
298
  dest="reachables_slices_file",
299
299
  help="Path for the reachables slices file created by atom.",
300
300
  )
301
+ parser.add_argument(
302
+ "--purl",
303
+ dest="search_purl",
304
+ help="Scan a single package url.",
305
+ )
301
306
  parser.add_argument(
302
307
  "-v",
303
308
  "--version",
@@ -448,7 +453,7 @@ def summarise(
448
453
  reached_purls=reached_purls,
449
454
  )
450
455
  pkg_vulnerabilities, pkg_group_rows = prepare_vdr(options)
451
- vdr_file = bom_file.replace(".json", ".vdr.json")
456
+ vdr_file = bom_file.replace(".json", ".vdr.json") if bom_file else None
452
457
  if pkg_vulnerabilities and bom_file:
453
458
  try:
454
459
  with open(bom_file, encoding="utf-8") as fp:
@@ -508,9 +513,15 @@ def download_rafs_based_image():
508
513
  target=vdb_rafs_database_url, outdir=rafs_data_dir.name
509
514
  )
510
515
 
511
- if paths_list and os.path.exists(
512
- os.path.join(rafs_data_dir.name, "data.rafs")
513
- ) and os.path.exists(os.path.join(rafs_data_dir.name, "meta.rafs")):
516
+ if (
517
+ paths_list
518
+ and os.path.exists(
519
+ os.path.join(rafs_data_dir.name, "data.rafs")
520
+ )
521
+ and os.path.exists(
522
+ os.path.join(rafs_data_dir.name, "meta.rafs")
523
+ )
524
+ ):
514
525
  nydus_download_command = [
515
526
  f"{nydus_image_command}",
516
527
  "unpack",
@@ -540,7 +551,8 @@ def download_rafs_based_image():
540
551
 
541
552
  except Exception:
542
553
  LOG.info(
543
- "Unable to pull the vulnerability database (rafs image) from %s. Trying to pull the non-rafs-based VDB image.", vdb_rafs_database_url
554
+ "Unable to pull the vulnerability database (rafs image) from %s. Trying to pull the non-rafs-based VDB image.",
555
+ vdb_rafs_database_url,
544
556
  )
545
557
  rafs_image_downloaded = False
546
558
 
@@ -819,6 +831,12 @@ def main():
819
831
  # Detect the project types and perform the right type of scan
820
832
  if args.project_type:
821
833
  project_types_list = args.project_type.split(",")
834
+ elif args.search_purl:
835
+ purl_obj = parse_purl(args.search_purl)
836
+ purl_obj["purl"] = args.search_purl
837
+ purl_obj["vendor"] = purl_obj.get("namespace")
838
+ project_types_list = [purl_obj.get("type")]
839
+ pkg_list = [purl_obj]
822
840
  elif args.bom and not args.project_type:
823
841
  project_types_list = ["bom"]
824
842
  elif not args.non_universal_scan:
@@ -857,7 +875,12 @@ def main():
857
875
  risk_report_file = areport_file.replace(
858
876
  ".json", f"-risk.{project_type}.json"
859
877
  )
860
- if args.bom and os.path.exists(args.bom):
878
+ # Are we scanning a single purl
879
+ if args.search_purl:
880
+ bom_file = None
881
+ creation_status = True
882
+ # Are we scanning a bom file
883
+ elif args.bom and os.path.exists(args.bom):
861
884
  bom_file = args.bom
862
885
  creation_status = True
863
886
  else:
@@ -876,14 +899,15 @@ def main():
876
899
  if not creation_status:
877
900
  LOG.debug("Bom file %s was not created successfully", bom_file)
878
901
  continue
879
- LOG.debug("Scanning using the bom file %s", bom_file)
880
- if not args.bom:
881
- LOG.info(
882
- "To improve performance, cache the bom file and invoke "
883
- "depscan with --bom %s instead of -i",
884
- bom_file,
885
- )
886
- pkg_list = get_pkg_list(bom_file)
902
+ if bom_file:
903
+ LOG.debug("Scanning using the bom file %s", bom_file)
904
+ if not args.bom:
905
+ LOG.info(
906
+ "To improve performance, cache the bom file and invoke "
907
+ "depscan with --bom %s instead of -i",
908
+ bom_file,
909
+ )
910
+ pkg_list = get_pkg_list(bom_file)
887
911
  if not pkg_list:
888
912
  LOG.debug("No packages found in the project!")
889
913
  continue
@@ -1097,7 +1121,10 @@ def main():
1097
1121
  result_file=os.path.join(reports_dir, args.report_name),
1098
1122
  )
1099
1123
  elif args.report_template:
1100
- LOG.warning("Template file %s doesn't exist, custom report not created.", args.report_template)
1124
+ LOG.warning(
1125
+ "Template file %s doesn't exist, custom report not created.",
1126
+ args.report_template,
1127
+ )
1101
1128
  # Submit vdr/vex files to threatdb server
1102
1129
  if args.threatdb_server and (args.threatdb_username or args.threatdb_token):
1103
1130
  submit_bom(
@@ -11,7 +11,7 @@ from rich.style import Style
11
11
  from rich.table import Table
12
12
  from rich.tree import Tree
13
13
  from vdb.lib import CPE_FULL_REGEX
14
- from vdb.lib.config import placeholder_fix_version
14
+ from vdb.lib.config import placeholder_exclude_version, placeholder_fix_version
15
15
  from vdb.lib.utils import parse_cpe, parse_purl
16
16
 
17
17
  from depscan.lib import config
@@ -84,7 +84,7 @@ def retrieve_bom_dependency_tree(bom_file):
84
84
  :return: Dependency tree as a list
85
85
  """
86
86
  if not bom_file:
87
- return []
87
+ return [], None
88
88
  try:
89
89
  with open(bom_file, encoding="utf-8") as bfp:
90
90
  bom_data = json.load(bfp)
@@ -97,6 +97,8 @@ def retrieve_bom_dependency_tree(bom_file):
97
97
 
98
98
  def retrieve_oci_properties(bom_data):
99
99
  props = {}
100
+ if not bom_data:
101
+ return props
100
102
  for p in bom_data.get("metadata", {}).get("properties", []):
101
103
  if p.get("name", "").startswith("oci:image:"):
102
104
  props[p.get("name")] = p.get("value")
@@ -1174,7 +1176,11 @@ def suggest_version(results, pkg_aliases=None, purl_aliases=None):
1174
1176
  else:
1175
1177
  full_pkg = pkg_aliases.get(full_pkg, full_pkg)
1176
1178
  version_upgrades = pkg_fix_map.get(full_pkg, set())
1177
- version_upgrades.add(fixed_location)
1179
+ if (
1180
+ fixed_location != placeholder_fix_version
1181
+ and fixed_location != placeholder_exclude_version
1182
+ ):
1183
+ version_upgrades.add(fixed_location)
1178
1184
  pkg_fix_map[full_pkg] = version_upgrades
1179
1185
  for k, v in pkg_fix_map.items():
1180
1186
  # Don't go near certain packages
@@ -4,14 +4,16 @@ from depscan.lib import config
4
4
  from depscan.lib.pkg_query import npm_metadata, pypi_metadata
5
5
 
6
6
  # Dict mapping project type to the audit source
7
- type_audit_map = {"nodejs": NpmSource(), "js": NpmSource()}
7
+ type_audit_map = {"nodejs": NpmSource(), "js": NpmSource(), "npm": NpmSource()}
8
8
 
9
9
  # Dict mapping project type to risk audit
10
10
  risk_audit_map = {
11
+ "npm": npm_metadata,
11
12
  "nodejs": npm_metadata,
12
13
  "js": npm_metadata,
13
14
  "python": pypi_metadata,
14
15
  "py": pypi_metadata,
16
+ "pypi": pypi_metadata,
15
17
  }
16
18
 
17
19
 
@@ -1173,7 +1173,11 @@ class CsafOccurence:
1173
1173
  )
1174
1174
  self.references = res["related_urls"]
1175
1175
  self.type = (res["type"],)
1176
- self.severity = res["severity"]
1176
+ self.severity = (
1177
+ res["severity"] if (
1178
+ res["severity"] in ["CRITICAL", "HIGH", "MEDIUM", "LOW", "NONE"]) else (
1179
+ "UNKNOWN")
1180
+ )
1177
1181
  self.orig_date = res["source_orig_time"] or None
1178
1182
  self.update_date = res["source_update_time"] or None
1179
1183
 
@@ -1186,7 +1190,8 @@ class CsafOccurence:
1186
1190
  vuln["product_status"] = self.product_status
1187
1191
  [ids, vuln["references"]] = format_references(self.references)
1188
1192
  vuln["ids"] = ids
1189
- vuln["scores"] = [{"cvss_v3": self.cvss_v3, "products": [self.pkg]}]
1193
+ if self.cvss_v3:
1194
+ vuln["scores"] = [{"cvss_v3": self.cvss_v3, "products": [self.pkg]}]
1190
1195
  self.notes.append(
1191
1196
  {
1192
1197
  "category": "general",
@@ -1299,27 +1304,32 @@ def parse_cvss(res):
1299
1304
  version is not 3.0 or 3.1, None is returned.
1300
1305
  """
1301
1306
 
1302
- # baseScore, vectorString, and version are required for a valid score
1307
+ # baseScore, baseSeverity, vectorString, and version are required
1303
1308
  cvss_v3 = res.get("cvss_v3")
1304
1309
  if (
1305
1310
  not cvss_v3
1306
1311
  or not (vector_string := cvss_v3.get("vector_string"))
1307
- or not (version := re.findall(r"3.0|3.1", cvss_v3.get("vector_string", "")))
1312
+ or not (version := re.findall(r"3.0|3.1",
1313
+ cvss_v3.get("vector_string", "")))
1308
1314
  or not (base_score := cvss_v3.get("base_score"))
1315
+ or (severity := res.get("severity")) not in
1316
+ ["CRITICAL", "HIGH", "MEDIUM", "LOW", "NONE"]
1309
1317
  ):
1310
1318
  return None
1311
1319
  version = version[0]
1312
- return {
1320
+ cvss_v3_data = {
1313
1321
  "baseScore": base_score,
1322
+ "baseSeverity": severity,
1314
1323
  "attackVector": cvss_v3.get("attack_vector"),
1315
1324
  "privilegesRequired": cvss_v3.get("privileges_required"),
1316
1325
  "userInteraction": cvss_v3.get("user_interaction"),
1317
1326
  "scope": cvss_v3.get("scope"),
1318
- "baseSeverity": res.get("severity"),
1319
1327
  "version": version,
1320
1328
  "vectorString": vector_string,
1321
1329
  }
1322
1330
 
1331
+ return cvss_v3_data
1332
+
1323
1333
 
1324
1334
  def format_references(ref):
1325
1335
  """
@@ -1567,6 +1577,7 @@ def parse_toml(metadata):
1567
1577
  'current_release_date'.
1568
1578
  """
1569
1579
  tracking = parse_revision_history(metadata.get("tracking"))
1580
+ # FIXME: Could this be simplified as list comprehension without append
1570
1581
  refs = []
1571
1582
  [refs.append(v) for v in metadata.get("reference")]
1572
1583
  notes = []
@@ -1873,6 +1884,8 @@ def add_vulnerabilities(data, results, direct_purls, reached_purls):
1873
1884
  "HIGH": 2,
1874
1885
  "MEDIUM": 3,
1875
1886
  "LOW": 4,
1887
+ "UNKNOWN": 5,
1888
+ "NONE": 6,
1876
1889
  }
1877
1890
  affected_regex = re.compile(
1878
1891
  r"(?P<lmod>[>=]{1,2})(?P<lower>\w+(?:.\w+)?(?:.\w+)?)-(?P<umod>[<=]{"
@@ -1884,7 +1897,7 @@ def add_vulnerabilities(data, results, direct_purls, reached_purls):
1884
1897
  for r in results:
1885
1898
  c = CsafOccurence(r)
1886
1899
  new_vuln = c.to_dict()
1887
- agg_score.add(severity_ref.get(c.severity))
1900
+ agg_score.add(severity_ref.get(c.severity, 5))
1888
1901
  if c.search_string:
1889
1902
  found = reached_dict.get(c.search_string)
1890
1903
  if not found:
@@ -54,10 +54,10 @@ def create_pkg_variations(pkg_dict):
54
54
  if purl_obj:
55
55
  pkg_type = purl_obj.get("type")
56
56
  qualifiers = purl_obj.get("qualifiers", {})
57
- if qualifiers.get("distro_name"):
57
+ if qualifiers and qualifiers.get("distro_name"):
58
58
  os_distro_name = qualifiers.get("distro_name")
59
59
  name_aliases.add(f"""{os_distro_name}/{name}""")
60
- if qualifiers.get("distro"):
60
+ if qualifiers and qualifiers.get("distro"):
61
61
  os_distro = qualifiers.get("distro")
62
62
  name_aliases.add(f"""{os_distro}/{name}""")
63
63
  # almalinux-9.2 becomes almalinux-9
@@ -70,6 +70,7 @@ def create_pkg_variations(pkg_dict):
70
70
  if vendor:
71
71
  vendor_aliases.add(vendor)
72
72
  vendor_aliases.add(vendor.lower())
73
+ vendor_aliases.add(vendor.lstrip("@"))
73
74
  if (
74
75
  vendor.startswith("org.")
75
76
  or vendor.startswith("io.")
@@ -94,7 +95,6 @@ def create_pkg_variations(pkg_dict):
94
95
  vendor_aliases.add("golang")
95
96
  if pkg_type not in config.OS_PKG_TYPES:
96
97
  name_aliases.add("package_" + name)
97
- vendor_aliases.add(pkg_type)
98
98
  if purl.startswith("pkg:composer"):
99
99
  vendor_aliases.add("get" + name)
100
100
  vendor_aliases.add(name + "_project")
@@ -155,10 +155,12 @@ def create_pkg_variations(pkg_dict):
155
155
  for suffix in COMMON_SUFFIXES:
156
156
  if name.endswith(suffix):
157
157
  name_aliases.add(name.replace(suffix, ""))
158
- for k, v in config.package_alias.items():
159
- if name.startswith(k) or k.startswith(name) or v.startswith(name):
160
- name_aliases.add(k)
161
- name_aliases.add(v)
158
+ # The below aliasing is resulting in several false positives for npm
159
+ if pkg_type not in ("npm",):
160
+ for k, v in config.package_alias.items():
161
+ if name.startswith(k) or k.startswith(name) or v.startswith(name):
162
+ name_aliases.add(k)
163
+ name_aliases.add(v)
162
164
  if pkg_type in config.OS_PKG_TYPES:
163
165
  if "lib" in name:
164
166
  name_aliases.add(name.replace("lib", ""))
@@ -168,7 +170,7 @@ def create_pkg_variations(pkg_dict):
168
170
  name_aliases.add(name + "-bin")
169
171
  else:
170
172
  # Filter vendor aliases that are also name aliases
171
- vendor_aliases = [x for x in vendor_aliases if x not in name_aliases]
173
+ vendor_aliases = [x for x in vendor_aliases if x not in name_aliases or x == vendor]
172
174
  if len(vendor_aliases) > 0:
173
175
  for vvar in list(vendor_aliases):
174
176
  for nvar in list(name_aliases):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: owasp-depscan
3
- Version: 5.0.2
3
+ Version: 5.0.4
4
4
  Summary: Fully open-source security audit for project dependencies based on known vulnerabilities and advisories.
5
5
  Author-email: Team AppThreat <cloud@appthreat.com>
6
6
  License: MIT
@@ -20,7 +20,7 @@ Classifier: Topic :: Utilities
20
20
  Requires-Python: >=3.8
21
21
  Description-Content-Type: text/markdown
22
22
  License-File: LICENSE
23
- Requires-Dist: appthreat-vulnerability-db>=5.5.4
23
+ Requires-Dist: appthreat-vulnerability-db>=5.5.5
24
24
  Requires-Dist: defusedxml
25
25
  Requires-Dist: oras
26
26
  Requires-Dist: PyYAML
@@ -147,22 +147,26 @@ Use the `/scan` endpoint to perform scans.
147
147
  > [!NOTE]
148
148
  > The `type` parameter is mandatory in server mode.
149
149
 
150
- * Scanning a local directory.
150
+ - Scanning a local directory.
151
+
151
152
  ```bash
152
153
  curl --json '{"path": "/tmp/vulnerable-aws-koa-app", "type": "js"}' http://0.0.0.0:7070/scan
153
154
  ```
154
155
 
155
- * Scanning a SBOM file (present locally).
156
+ - Scanning a SBOM file (present locally).
157
+
156
158
  ```bash
157
159
  curl --json '{"path": "/tmp/vulnerable-aws-koa-app/sbom_file.json", "type": "js"}' http://0.0.0.0:7070/scan
158
160
  ```
159
161
 
160
- * Scanning a GitHub repo.
162
+ - Scanning a GitHub repo.
163
+
161
164
  ```bash
162
165
  curl --json '{"url": "https://github.com/HooliCorp/vulnerable-aws-koa-app", "type": "js"}' http://0.0.0.0:7070/scan -o app.vdr.json
163
166
  ```
164
167
 
165
- * Uploading a SBOM file and generating results based on it.
168
+ - Uploading a SBOM file and generating results based on it.
169
+
166
170
  ```bash
167
171
  curl -X POST -H 'Content-Type: multipart/form-data' -F 'file=@/tmp/app/sbom_file.json' http://0.0.0.0:7070/scan?type=js
168
172
  ```
@@ -242,6 +246,7 @@ options:
242
246
  --explain Makes depscan to explain the various analysis. Useful for creating detailed reports.
243
247
  --reachables-slices-file REACHABLES_SLICES_FILE
244
248
  Path for the reachables slices file created by atom.
249
+ --purl SEARCH_PURL Scan a single package url.
245
250
  -v, --version Display the version
246
251
  ```
247
252
 
@@ -1,4 +1,4 @@
1
- appthreat-vulnerability-db>=5.5.4
1
+ appthreat-vulnerability-db>=5.5.5
2
2
  defusedxml
3
3
  oras
4
4
  PyYAML
@@ -1,12 +1,12 @@
1
1
  [project]
2
2
  name = "owasp-depscan"
3
- version = "5.0.2"
3
+ version = "5.0.4"
4
4
  description = "Fully open-source security audit for project dependencies based on known vulnerabilities and advisories."
5
5
  authors = [
6
6
  {name = "Team AppThreat", email = "cloud@appthreat.com"},
7
7
  ]
8
8
  dependencies = [
9
- "appthreat-vulnerability-db>=5.5.4",
9
+ "appthreat-vulnerability-db>=5.5.5",
10
10
  "defusedxml",
11
11
  "oras",
12
12
  "PyYAML",