Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions conan/api/subapi/audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import os
import base64

from conan.api.output import ConanOutput
from conan.internal.api.audit.providers import ConanCenterProvider, PrivateProvider
from conan.errors import ConanException
from conan.internal.api.remotes.encrypt import encode, decode
Expand All @@ -28,12 +29,14 @@ def __init__(self, conan_api):
}

@staticmethod
def scan(deps_graph, provider):
def scan(deps_graph, provider, context=None):
"""
Scan a given recipe for vulnerabilities in its dependencies.
"""
refs = sorted(set(RecipeReference.loads(f"{node.ref.name}/{node.ref.version}")
for node in deps_graph.nodes[1:]), key=lambda ref: ref.name)
for node in deps_graph.nodes[1:]
if context is None or node.context == context),
key=lambda ref: ref.name)
return provider.get_cves(refs)

@staticmethod
Expand Down
5 changes: 4 additions & 1 deletion conan/cli/commands/audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ def audit_scan(conan_api: ConanAPI, parser, subparser, *args) -> dict:
help="Set threshold for severity level to raise an error. "
"By default raises an error for any critical CVSS (9.0 or higher). "
" Use 100.0 to disable it.")
subparser.add_argument("--context", help="Context to scan, by default both contexts are scanned "
"if not specified",
choices=["host", "build"], default=None)

_add_provider_arg(subparser)
args = parser.parse_args(*args)
Expand Down Expand Up @@ -97,7 +100,7 @@ def audit_scan(conan_api: ConanAPI, parser, subparser, *args) -> dict:

provider = conan_api.audit.get_provider(args.provider or CONAN_CENTER_AUDIT_PROVIDER_NAME)

scan_result = conan_api.audit.scan(deps_graph, provider)
scan_result = conan_api.audit.scan(deps_graph, provider, args.context)
_parse_error_threshold(scan_result, args.severity_level)
return scan_result

Expand Down
20 changes: 20 additions & 0 deletions test/integration/command/test_audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -472,3 +472,23 @@ def test_parse_error_crash_when_no_edges():
assert "conan_error" in scan_result
assert "zlib/1.2.11" in scan_result["conan_error"]
assert "7.0" in scan_result["conan_error"]


@pytest.mark.parametrize("package_context", ["build", "host"])
@pytest.mark.parametrize("filter_context", ["build", "host", None])
def test_audit_scan_context_filter(package_context, filter_context):
tc = TestClient(light=True)

tc.save({"conanfile.py": GenConanfile("zlib", "1.2.11")})
tc.run("export .")
tc.run("audit provider auth conancenter --token=valid_token")

requires = "requires" if package_context == "host" else "tool-requires"
context = "" if filter_context is None else f"--context={filter_context}"

with proxy_response(200, {}):
tc.run(f"audit scan --{requires}=zlib/1.2.11 {context}")
if filter_context is None or filter_context == package_context:
assert "Requesting vulnerability info for: zlib/1.2.11" in tc.out
else:
assert "Requesting vulnerability info for: zlib/1.2.11" not in tc.out
Loading