owasp-depscan 4.2.8__py3-none-any.whl → 4.3.0__py3-none-any.whl
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.
- depscan/cli.py +81 -21
- depscan/lib/bom.py +1 -1
- depscan/lib/csaf.py +1680 -0
- {owasp_depscan-4.2.8.dist-info → owasp_depscan-4.3.0.dist-info}/METADATA +30 -8
- {owasp_depscan-4.2.8.dist-info → owasp_depscan-4.3.0.dist-info}/RECORD +9 -8
- {owasp_depscan-4.2.8.dist-info → owasp_depscan-4.3.0.dist-info}/LICENSE +0 -0
- {owasp_depscan-4.2.8.dist-info → owasp_depscan-4.3.0.dist-info}/WHEEL +0 -0
- {owasp_depscan-4.2.8.dist-info → owasp_depscan-4.3.0.dist-info}/entry_points.txt +0 -0
- {owasp_depscan-4.2.8.dist-info → owasp_depscan-4.3.0.dist-info}/top_level.txt +0 -0
depscan/cli.py
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import argparse
|
|
5
5
|
import json
|
|
6
6
|
import os
|
|
7
|
+
import sys
|
|
7
8
|
import tempfile
|
|
8
9
|
|
|
9
10
|
from quart import Quart, request
|
|
@@ -11,7 +12,6 @@ from rich.panel import Panel
|
|
|
11
12
|
from rich.terminal_theme import MONOKAI
|
|
12
13
|
from vdb.lib import config
|
|
13
14
|
from vdb.lib import db as db_lib
|
|
14
|
-
from vdb.lib.aqua import AquaSource
|
|
15
15
|
from vdb.lib.config import data_dir
|
|
16
16
|
from vdb.lib.gha import GitHubSource
|
|
17
17
|
from vdb.lib.nvd import NvdSource
|
|
@@ -20,6 +20,7 @@ from vdb.lib.utils import parse_purl
|
|
|
20
20
|
|
|
21
21
|
import oras.client
|
|
22
22
|
|
|
23
|
+
from depscan.lib.csaf import export_csaf, write_toml
|
|
23
24
|
from depscan.lib import privado, utils
|
|
24
25
|
from depscan.lib.analysis import (
|
|
25
26
|
PrepareVexOptions,
|
|
@@ -31,7 +32,12 @@ from depscan.lib.analysis import (
|
|
|
31
32
|
summary_stats,
|
|
32
33
|
)
|
|
33
34
|
from depscan.lib.audit import audit, risk_audit, risk_audit_map, type_audit_map
|
|
34
|
-
from depscan.lib.bom import
|
|
35
|
+
from depscan.lib.bom import (
|
|
36
|
+
create_bom,
|
|
37
|
+
get_pkg_by_type,
|
|
38
|
+
get_pkg_list,
|
|
39
|
+
submit_bom,
|
|
40
|
+
)
|
|
35
41
|
from depscan.lib.config import (
|
|
36
42
|
UNIVERSAL_SCAN_TYPE,
|
|
37
43
|
license_data_dir,
|
|
@@ -82,7 +88,15 @@ def build_args():
|
|
|
82
88
|
action="store_true",
|
|
83
89
|
default=False,
|
|
84
90
|
dest="cache",
|
|
85
|
-
help="Cache vulnerability information in platform specific "
|
|
91
|
+
help="Cache vulnerability information in platform specific "
|
|
92
|
+
"user_data_dir",
|
|
93
|
+
)
|
|
94
|
+
parser.add_argument(
|
|
95
|
+
"--csaf",
|
|
96
|
+
action="store_true",
|
|
97
|
+
default=False,
|
|
98
|
+
dest="csaf",
|
|
99
|
+
help="Generate a CSAF",
|
|
86
100
|
)
|
|
87
101
|
parser.add_argument(
|
|
88
102
|
"--sync",
|
|
@@ -97,12 +111,15 @@ def build_args():
|
|
|
97
111
|
action="store_true",
|
|
98
112
|
default=True,
|
|
99
113
|
dest="suggest",
|
|
100
|
-
help="DEPRECATED: Suggest is the default mode for determining fix "
|
|
114
|
+
help="DEPRECATED: Suggest is the default mode for determining fix "
|
|
115
|
+
"version.",
|
|
101
116
|
)
|
|
102
117
|
parser.add_argument(
|
|
103
118
|
"--risk-audit",
|
|
104
119
|
action="store_true",
|
|
105
|
-
default=True
|
|
120
|
+
default=True
|
|
121
|
+
if os.getenv("ENABLE_OSS_RISK", "") in ["true", "1"]
|
|
122
|
+
else False,
|
|
106
123
|
dest="risk_audit",
|
|
107
124
|
help="Perform package risk audit (slow operation). Npm only.",
|
|
108
125
|
)
|
|
@@ -142,7 +159,9 @@ def build_args():
|
|
|
142
159
|
)
|
|
143
160
|
parser.add_argument(
|
|
144
161
|
"--reports-dir",
|
|
145
|
-
default=os.getenv(
|
|
162
|
+
default=os.getenv(
|
|
163
|
+
"DEPSCAN_REPORTS_DIR", os.path.join(os.getcwd(), "reports")
|
|
164
|
+
),
|
|
146
165
|
dest="reports_dir",
|
|
147
166
|
help="Reports directory",
|
|
148
167
|
)
|
|
@@ -269,7 +288,9 @@ def scan(db, project_type, pkg_list, suggest_mode):
|
|
|
269
288
|
LOG.debug("Empty package search attempted!")
|
|
270
289
|
else:
|
|
271
290
|
LOG.debug("Scanning %d oss dependencies for issues", len(pkg_list))
|
|
272
|
-
results, pkg_aliases, purl_aliases = utils.search_pkgs(
|
|
291
|
+
results, pkg_aliases, purl_aliases = utils.search_pkgs(
|
|
292
|
+
db, project_type, pkg_list
|
|
293
|
+
)
|
|
273
294
|
# pkg_aliases is a dict that can be used to find the original vendor and
|
|
274
295
|
# package name This way we consistently use the same names used by the
|
|
275
296
|
# caller irrespective of how the result was obtained
|
|
@@ -326,7 +347,9 @@ def scan(db, project_type, pkg_list, suggest_mode):
|
|
|
326
347
|
"Re-checking our suggestion to ensure there are no further "
|
|
327
348
|
"vulnerabilities"
|
|
328
349
|
)
|
|
329
|
-
override_results, _, _ = utils.search_pkgs(
|
|
350
|
+
override_results, _, _ = utils.search_pkgs(
|
|
351
|
+
db, project_type, sug_pkg_list
|
|
352
|
+
)
|
|
330
353
|
if override_results:
|
|
331
354
|
new_sug_dict = suggest_version(override_results)
|
|
332
355
|
LOG.debug("Received override results: %s", new_sug_dict)
|
|
@@ -432,7 +455,7 @@ def summarise(
|
|
|
432
455
|
bom_data["services"] = []
|
|
433
456
|
bom_data["services"].insert(0, pservice)
|
|
434
457
|
with open(vex_file, mode="w", encoding="utf-8") as vexfp:
|
|
435
|
-
json.dump(bom_data, vexfp)
|
|
458
|
+
json.dump(bom_data, vexfp, indent=4)
|
|
436
459
|
LOG.info("VEX file %s generated successfully", vex_file)
|
|
437
460
|
except Exception:
|
|
438
461
|
LOG.warning("Unable to generate VEX file for this scan")
|
|
@@ -556,7 +579,8 @@ async def run_scan():
|
|
|
556
579
|
else:
|
|
557
580
|
return {
|
|
558
581
|
"error": "true",
|
|
559
|
-
"message": "Unable to generate SBoM. Check your input path or "
|
|
582
|
+
"message": "Unable to generate SBoM. Check your input path or "
|
|
583
|
+
"url.",
|
|
560
584
|
}, 500
|
|
561
585
|
|
|
562
586
|
|
|
@@ -567,7 +591,9 @@ def run_server(args):
|
|
|
567
591
|
:param args: Command line arguments passed to the function.
|
|
568
592
|
"""
|
|
569
593
|
print(at_logo)
|
|
570
|
-
console.print(
|
|
594
|
+
console.print(
|
|
595
|
+
f"Depscan server running on {args.server_host}:{args.server_port}"
|
|
596
|
+
)
|
|
571
597
|
app.config["CDXGEN_SERVER_URL"] = args.cdxgen_server
|
|
572
598
|
app.run(
|
|
573
599
|
host=args.server_host,
|
|
@@ -588,9 +614,24 @@ def main():
|
|
|
588
614
|
if not args.no_banner:
|
|
589
615
|
print(at_logo)
|
|
590
616
|
src_dir = args.src_dir_image
|
|
591
|
-
if not src_dir:
|
|
617
|
+
if not src_dir or src_dir == ".":
|
|
592
618
|
src_dir = os.getcwd()
|
|
593
619
|
reports_dir = args.reports_dir
|
|
620
|
+
if args.csaf:
|
|
621
|
+
toml_file_path = os.path.join(src_dir, "csaf.toml")
|
|
622
|
+
if not os.path.exists(toml_file_path):
|
|
623
|
+
LOG.info("CSAF toml not found, creating template in %s", src_dir)
|
|
624
|
+
write_toml(toml_file_path)
|
|
625
|
+
LOG.info(
|
|
626
|
+
"Please fill out the toml with your details and rerun depscan."
|
|
627
|
+
)
|
|
628
|
+
LOG.info("Check out our CSAF documentation for an explanation of "
|
|
629
|
+
"this feature. https://github.com/owasp-dep-scan/dep-scan"
|
|
630
|
+
"/blob/master/contrib/CSAF_README.md")
|
|
631
|
+
LOG.info("If you're just checking out how our generator works, "
|
|
632
|
+
"feel free to skip filling out the toml and just rerun "
|
|
633
|
+
"depscan.")
|
|
634
|
+
sys.exit(0)
|
|
594
635
|
# Detect the project types and perform the right type of scan
|
|
595
636
|
if args.project_type:
|
|
596
637
|
project_types_list = args.project_type.split(",")
|
|
@@ -628,7 +669,9 @@ def main():
|
|
|
628
669
|
for project_type in project_types_list:
|
|
629
670
|
results = []
|
|
630
671
|
report_file = areport_file.replace(".json", f"-{project_type}.json")
|
|
631
|
-
risk_report_file = areport_file.replace(
|
|
672
|
+
risk_report_file = areport_file.replace(
|
|
673
|
+
".json", f"-risk.{project_type}.json"
|
|
674
|
+
)
|
|
632
675
|
LOG.info("=" * 80)
|
|
633
676
|
if args.bom and os.path.exists(args.bom):
|
|
634
677
|
bom_file = args.bom
|
|
@@ -665,7 +708,9 @@ def main():
|
|
|
665
708
|
license_report_file = os.path.join(
|
|
666
709
|
reports_dir, "license-" + project_type + ".json"
|
|
667
710
|
)
|
|
668
|
-
analyse_licenses(
|
|
711
|
+
analyse_licenses(
|
|
712
|
+
project_type, licenses_results, license_report_file
|
|
713
|
+
)
|
|
669
714
|
if project_type in risk_audit_map:
|
|
670
715
|
if args.risk_audit:
|
|
671
716
|
console.print(
|
|
@@ -713,14 +758,16 @@ def main():
|
|
|
713
758
|
try:
|
|
714
759
|
audit_results = audit(project_type, pkg_list)
|
|
715
760
|
if audit_results:
|
|
716
|
-
LOG.debug(
|
|
761
|
+
LOG.debug(
|
|
762
|
+
"Remote audit yielded %d results", len(audit_results)
|
|
763
|
+
)
|
|
717
764
|
results = results + audit_results
|
|
718
765
|
except Exception as e:
|
|
719
766
|
LOG.error("Remote audit was not successful")
|
|
720
767
|
LOG.error(e)
|
|
721
768
|
results = []
|
|
722
|
-
# In case of docker, bom, or universal type, check if there are any
|
|
723
|
-
# audited remotely
|
|
769
|
+
# In case of docker, bom, or universal type, check if there are any
|
|
770
|
+
# npm packages that can be audited remotely
|
|
724
771
|
if project_type in ("podman", "docker", "oci", "bom", "universal"):
|
|
725
772
|
npm_pkg_list = get_pkg_by_type(pkg_list, "npm")
|
|
726
773
|
if npm_pkg_list:
|
|
@@ -739,15 +786,23 @@ def main():
|
|
|
739
786
|
if not db_lib.index_count(db["index_file"]):
|
|
740
787
|
run_cacher = True
|
|
741
788
|
else:
|
|
742
|
-
LOG.debug(
|
|
789
|
+
LOG.debug(
|
|
790
|
+
"Vulnerability database loaded from %s", config.vdb_bin_file
|
|
791
|
+
)
|
|
743
792
|
|
|
744
793
|
sources_list = [OSVSource(), NvdSource()]
|
|
745
794
|
if os.environ.get("GITHUB_TOKEN"):
|
|
746
795
|
sources_list.insert(0, GitHubSource())
|
|
747
796
|
if run_cacher:
|
|
797
|
+
LOG.debug(
|
|
798
|
+
"About to download vdb from %s. This might take a while ...",
|
|
799
|
+
vdb_database_url,
|
|
800
|
+
)
|
|
748
801
|
oras_client = oras.client.OrasClient()
|
|
749
|
-
paths_list = oras_client.pull(
|
|
750
|
-
|
|
802
|
+
paths_list = oras_client.pull(
|
|
803
|
+
target=vdb_database_url, outdir=data_dir
|
|
804
|
+
)
|
|
805
|
+
LOG.debug("VDB data is stored at: %s", paths_list)
|
|
751
806
|
run_cacher = False
|
|
752
807
|
elif args.sync:
|
|
753
808
|
for s in sources_list:
|
|
@@ -763,7 +818,12 @@ def main():
|
|
|
763
818
|
db, project_type, pkg_list, args.suggest
|
|
764
819
|
)
|
|
765
820
|
if vdb_results:
|
|
766
|
-
results
|
|
821
|
+
results += vdb_results
|
|
822
|
+
if args.csaf:
|
|
823
|
+
new_res = []
|
|
824
|
+
for r in results:
|
|
825
|
+
new_res.append(r.to_dict())
|
|
826
|
+
export_csaf(new_res, src_dir, reports_dir)
|
|
767
827
|
# Summarise and print results
|
|
768
828
|
summarise(
|
|
769
829
|
project_type,
|
depscan/lib/bom.py
CHANGED