You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tooling.apache.org by sb...@apache.org on 2025/12/15 15:48:58 UTC

(tooling-trusted-releases) branch main updated (a9ebf7a -> cf7e2f6)

This is an automated email from the ASF dual-hosted git repository.

sbp pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-releases.git


    from a9ebf7a  Use the script method to install syft
     new 86ca289  Link to vulnerability details from report, include more info in error model, don't error on missing PURL for files.
     new cf7e2f6  Remove unused JS configuration files and settings

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .gitignore                     |  1 -
 atr/get/sbom.py                | 17 +++++++++++------
 atr/models/results.py          |  2 +-
 atr/sbom/cli.py                |  3 ++-
 atr/sbom/conformance.py        | 14 ++++++++++++--
 atr/sbom/models/bom.py         |  2 ++
 atr/sbom/models/conformance.py |  1 +
 atr/sbom/osv.py                | 15 ++++++++-------
 atr/tasks/sbom.py              |  6 +++---
 eslint.config.mjs              | 37 -------------------------------------
 package.json                   | 11 -----------
 start-dev.sh                   |  2 +-
 12 files changed, 41 insertions(+), 70 deletions(-)
 delete mode 100644 eslint.config.mjs
 delete mode 100644 package.json


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tooling.apache.org
For additional commands, e-mail: commits-help@tooling.apache.org


(tooling-trusted-releases) 01/02: Link to vulnerability details from report, include more info in error model, don't error on missing PURL for files.

Posted by sb...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sbp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-releases.git

commit 86ca289242044fc9f3c7ae6a61dd0e76a806591d
Author: Alastair McFarlane <ar...@apache.org>
AuthorDate: Mon Dec 15 15:38:40 2025 +0000

    Link to vulnerability details from report, include more info in error model, don't error on missing PURL for files.
---
 atr/get/sbom.py                | 17 +++++++++++------
 atr/models/results.py          |  2 +-
 atr/sbom/cli.py                |  3 ++-
 atr/sbom/conformance.py        | 14 ++++++++++++--
 atr/sbom/models/bom.py         |  2 ++
 atr/sbom/models/conformance.py |  1 +
 atr/sbom/osv.py                | 15 ++++++++-------
 atr/tasks/sbom.py              |  6 +++---
 start-dev.sh                   |  2 +-
 9 files changed, 41 insertions(+), 21 deletions(-)

diff --git a/atr/get/sbom.py b/atr/get/sbom.py
index ce75a5a..c85d477 100644
--- a/atr/get/sbom.py
+++ b/atr/get/sbom.py
@@ -194,10 +194,12 @@ def _vulnerability_component_details(block: htm.Block, component: results.OSVCom
     for vuln in component.vulnerabilities:
         vuln_id = vuln.get("id", "Unknown")
         vuln_summary = vuln.get("summary", "No summary available")
+        vuln_refs = [r for r in vuln.get("references", []) if r.get("type", "") == "WEB"]
+        vuln_primary_ref = vuln_refs[0] if (len(vuln_refs) > 0) else {}
         vuln_modified = vuln.get("modified", "Unknown")
         vuln_severity = _extract_vulnerability_severity(vuln)
 
-        vuln_header = [htm.strong(".me-2")[vuln_id]]
+        vuln_header = [htm.a(href=vuln_primary_ref.get("url", ""), target="_blank")[htm.strong(".me-2")[vuln_id]]]
         if vuln_severity != "Unknown":
             vuln_header.append(htm.span(".badge.bg-warning.text-dark")[vuln_severity])
 
@@ -256,13 +258,15 @@ def _vulnerability_scan_results(block: htm.Block, task: sql.Task) -> None:
         return
 
     components = task_result.components
-    ignored_count = task_result.ignored_count
+    ignored = task_result.ignored
+    ignored_count = len(ignored)
 
     if not components:
         block.p["No vulnerabilities found."]
         if ignored_count > 0:
-            component_word = "component" if (ignored_count == 1) else "components"
-            block.p[f"{ignored_count} {component_word} were ignored due to missing PURL or version information."]
+            component_word = "component was" if (ignored_count == 1) else "components were"
+            block.p[f"{ignored_count} {component_word} ignored due to missing PURL or version information:"]
+            block.p[f"{','.join(ignored)}"]
         return
 
     block.p[f"Found vulnerabilities in {len(components)} components:"]
@@ -271,8 +275,9 @@ def _vulnerability_scan_results(block: htm.Block, task: sql.Task) -> None:
         _vulnerability_component_details(block, component)
 
     if ignored_count > 0:
-        component_word = "component" if (ignored_count == 1) else "components"
-        block.p[f"{ignored_count} {component_word} were ignored due to missing PURL or version information."]
+        component_word = "component was" if (ignored_count == 1) else "components were"
+        block.p[f"{ignored_count} {component_word} ignored due to missing PURL or version information:"]
+        block.p[f"{','.join(ignored)}"]
 
 
 def _vulnerability_scan_section(
diff --git a/atr/models/results.py b/atr/models/results.py
index d09a58a..9db1b55 100644
--- a/atr/models/results.py
+++ b/atr/models/results.py
@@ -58,7 +58,7 @@ class SBOMOSVScan(schema.Strict):
     revision_number: str = schema.description("Revision number")
     file_path: str = schema.description("Relative path to the scanned SBOM file")
     components: list[OSVComponent] = schema.description("Components with vulnerabilities")
-    ignored_count: int = schema.description("Number of components ignored")
+    ignored: list[str] = schema.description("Components ignored")
 
 
 class SbomQsScore(schema.Strict):
diff --git a/atr/sbom/cli.py b/atr/sbom/cli.py
index 4c8721f..4ef3bec 100644
--- a/atr/sbom/cli.py
+++ b/atr/sbom/cli.py
@@ -70,7 +70,8 @@ def command_missing(bundle: models.bundle.Bundle) -> None:
 
 
 def command_osv(bundle: models.bundle.Bundle) -> None:
-    results, ignored_count = asyncio.run(osv.scan_bundle(bundle))
+    results, ignored = asyncio.run(osv.scan_bundle(bundle))
+    ignored_count = len(ignored)
     if ignored_count > 0:
         print(f"Warning: {ignored_count} components ignored (missing purl or version)")
     for component_result in results:
diff --git a/atr/sbom/conformance.py b/atr/sbom/conformance.py
index f3e868a..ae39e1c 100644
--- a/atr/sbom/conformance.py
+++ b/atr/sbom/conformance.py
@@ -289,7 +289,8 @@ def ntia_2021_issues(
             cpe_is_none = bom_value.metadata.component.cpe is None
             purl_is_none = bom_value.metadata.component.purl is None
             swid_is_none = bom_value.metadata.component.swid is None
-            if cpe_is_none and purl_is_none and swid_is_none:
+            type_is_file = bom_value.metadata.component.type == "file"
+            if cpe_is_none and purl_is_none and swid_is_none and (not type_is_file):
                 warnings.append(
                     models.conformance.MissingComponentProperty(
                         property=models.conformance.ComponentProperty.IDENTIFIER
@@ -307,11 +308,16 @@ def ntia_2021_issues(
         errors.append(models.conformance.MissingProperty(property=models.conformance.Property.METADATA))
 
     for index, component in enumerate(bom_value.components or []):
+        component_type = component.type
+        component_friendly_name = component.name
+        if component_type is not None:
+            component_friendly_name = f"{component_type}: {component_friendly_name}"
         if component.supplier is None:
             errors.append(
                 models.conformance.MissingComponentProperty(
                     property=models.conformance.ComponentProperty.SUPPLIER,
                     index=index,
+                    component=component_friendly_name,
                 )
             )
 
@@ -320,6 +326,7 @@ def ntia_2021_issues(
                 models.conformance.MissingComponentProperty(
                     property=models.conformance.ComponentProperty.NAME,
                     index=index,
+                    component=component_friendly_name,
                 )
             )
 
@@ -328,17 +335,20 @@ def ntia_2021_issues(
                 models.conformance.MissingComponentProperty(
                     property=models.conformance.ComponentProperty.VERSION,
                     index=index,
+                    component=component_friendly_name,
                 )
             )
 
         component_cpe_is_none = component.cpe is None
         component_purl_is_none = component.purl is None
         component_swid_is_none = component.swid is None
-        if component_cpe_is_none and component_purl_is_none and component_swid_is_none:
+        component_type_is_file = component_type == "file"
+        if component_cpe_is_none and component_purl_is_none and component_swid_is_none and (not component_type_is_file):
             warnings.append(
                 models.conformance.MissingComponentProperty(
                     property=models.conformance.ComponentProperty.IDENTIFIER,
                     index=index,
+                    component=component_friendly_name,
                 )
             )
 
diff --git a/atr/sbom/models/bom.py b/atr/sbom/models/bom.py
index b5c0a4b..60c872f 100644
--- a/atr/sbom/models/bom.py
+++ b/atr/sbom/models/bom.py
@@ -28,6 +28,7 @@ class Swid(Lax):
 
 class Supplier(Lax):
     name: str | None = None
+    url: str | None = None
 
 
 class License(Lax):
@@ -51,6 +52,7 @@ class Component(Lax):
     swid: Swid | None = None
     licenses: list[LicenseChoice] | None = None
     scope: str | None = None
+    type: str | None = None
 
 
 class ToolComponent(Lax):
diff --git a/atr/sbom/models/conformance.py b/atr/sbom/models/conformance.py
index 95faaa1..2d14a04 100644
--- a/atr/sbom/models/conformance.py
+++ b/atr/sbom/models/conformance.py
@@ -57,6 +57,7 @@ class MissingProperty(Strict):
 class MissingComponentProperty(Strict):
     kind: Literal["missing_component_property"] = "missing_component_property"
     property: ComponentProperty
+    component: str | None = None
     index: int | None = None
 
     def __str__(self) -> str:
diff --git a/atr/sbom/osv.py b/atr/sbom/osv.py
index f6b80cc..fc84892 100644
--- a/atr/sbom/osv.py
+++ b/atr/sbom/osv.py
@@ -28,11 +28,12 @@ _DEBUG: bool = os.environ.get("DEBUG_SBOM_TOOL") == "1"
 _OSV_API_BASE: str = "https://api.osv.dev/v1"
 
 
-async def scan_bundle(bundle: models.bundle.Bundle) -> tuple[list[models.osv.ComponentVulnerabilities], int]:
+async def scan_bundle(bundle: models.bundle.Bundle) -> tuple[list[models.osv.ComponentVulnerabilities], list[str]]:
     components = bundle.bom.components or []
-    queries, ignored_count = _scan_bundle_build_queries(components)
+    queries, ignored = _scan_bundle_build_queries(components)
     if _DEBUG:
         print(f"[DEBUG] Scanning {len(queries)} components for vulnerabilities")
+        ignored_count = len(ignored)
         if ignored_count > 0:
             print(f"[DEBUG] {ignored_count} components ignored (missing purl or version)")
     async with aiohttp.ClientSession() as session:
@@ -43,7 +44,7 @@ async def scan_bundle(bundle: models.bundle.Bundle) -> tuple[list[models.osv.Com
     result: list[models.osv.ComponentVulnerabilities] = []
     for purl, vulns in component_vulns_map.items():
         result.append(models.osv.ComponentVulnerabilities(purl=purl, vulnerabilities=vulns))
-    return result, ignored_count
+    return result, ignored
 
 
 def _component_purl_with_version(component: models.bom.Component) -> str | None:
@@ -125,17 +126,17 @@ async def _paginate_query(
 
 def _scan_bundle_build_queries(
     components: list[models.bom.Component],
-) -> tuple[list[tuple[str, dict[str, Any]]], int]:
+) -> tuple[list[tuple[str, dict[str, Any]]], list[str]]:
     queries: list[tuple[str, dict[str, Any]]] = []
-    ignored_count = 0
+    ignored = []
     for component in components:
         purl_with_version = _component_purl_with_version(component)
         if purl_with_version is None:
-            ignored_count += 1
+            ignored.append(component.name)
             continue
         query = {"package": {"purl": purl_with_version}}
         queries.append((purl_with_version, query))
-    return queries, ignored_count
+    return queries, ignored
 
 
 async def _scan_bundle_fetch_vulnerabilities(
diff --git a/atr/tasks/sbom.py b/atr/tasks/sbom.py
index 9503e65..e837a87 100644
--- a/atr/tasks/sbom.py
+++ b/atr/tasks/sbom.py
@@ -139,7 +139,7 @@ async def osv_scan(args: FileArgs) -> results.Results | None:
     if not (full_path.endswith(".cdx.json") and os.path.isfile(full_path)):
         raise SBOMScanningError("SBOM file does not exist", {"file_path": args.file_path})
     bundle = sbom.utilities.path_to_bundle(pathlib.Path(full_path))
-    vulnerabilities, ignored_count = await sbom.osv.scan_bundle(bundle)
+    vulnerabilities, ignored = await sbom.osv.scan_bundle(bundle)
     components = [results.OSVComponent(purl=v.purl, vulnerabilities=v.vulnerabilities) for v in vulnerabilities]
     return results.SBOMOSVScan(
         kind="sbom_osv_scan",
@@ -148,7 +148,7 @@ async def osv_scan(args: FileArgs) -> results.Results | None:
         revision_number=args.revision_number,
         file_path=args.file_path,
         components=components,
-        ignored_count=ignored_count,
+        ignored=ignored,
     )
 
 
@@ -256,7 +256,7 @@ async def _generate_cyclonedx_core(artifact_path: str, output_path: str) -> dict
         log.info(f"Using root directory: {extract_dir}")
 
         # Run syft to generate the CycloneDX SBOM
-        syft_command = ["syft", extract_dir, "-o", "cyclonedx-json"]
+        syft_command = ["syft", extract_dir, "-o", "cyclonedx-json", "--base-path", f"{temp_dir!s}"]
         log.info(f"Running syft: {' '.join(syft_command)}")
 
         try:
diff --git a/start-dev.sh b/start-dev.sh
index c9bba96..ae7a915 100755
--- a/start-dev.sh
+++ b/start-dev.sh
@@ -13,4 +13,4 @@ fi
 
 echo "Starting hypercorn on ${BIND}" >> /opt/atr/state/hypercorn.log
 exec hypercorn --reload --bind "${BIND}" \
-  --keyfile key.pem --certfile cert.pem atr.server:app >> /opt/atr/state/hypercorn.log 2>&1
+  --keyfile key.pem --certfile cert.pem atr.server:app | tee /opt/atr/state/hypercorn.log 2>&1


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tooling.apache.org
For additional commands, e-mail: commits-help@tooling.apache.org


(tooling-trusted-releases) 02/02: Remove unused JS configuration files and settings

Posted by sb...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sbp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-releases.git

commit cf7e2f6e4a7e29ec374f8ef27694abd87749358b
Author: Sean B. Palmer <se...@miscoranda.com>
AuthorDate: Mon Dec 15 15:44:27 2025 +0000

    Remove unused JS configuration files and settings
---
 .gitignore        |  1 -
 eslint.config.mjs | 37 -------------------------------------
 package.json      | 11 -----------
 3 files changed, 49 deletions(-)

diff --git a/.gitignore b/.gitignore
index 1a13f0a..f2a2641 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,5 +15,4 @@ bootstrap/build/
 dev/
 /docs/
 node_modules/
-package-lock.json
 state/
diff --git a/eslint.config.mjs b/eslint.config.mjs
deleted file mode 100644
index a72c229..0000000
--- a/eslint.config.mjs
+++ /dev/null
@@ -1,37 +0,0 @@
-// eslint.config.mjs
-import eslint from "@eslint/js";
-import tseslint from "typescript-eslint";
-import globals from "globals";
-
-export default tseslint.config(
-  {
-    ignores: [
-      "atr/static/js/**/*.js",
-      "node_modules/",
-      "dist/",
-      "build/",
-      "coverage/",
-      ".venv/",
-      "eslint.config.mjs"
-    ]
-  },
-  eslint.configs.recommended,
-  ...tseslint.configs.recommended,
-  ...tseslint.configs.recommendedTypeChecked,
-  {
-    languageOptions: {
-      parserOptions: { project: true, tsconfigRootDir: import.meta.dirname },
-      globals: { ...globals.browser }
-    },
-    rules: {
-      "no-console": "warn",
-      "no-debugger": "warn",
-      "@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }],
-      "@typescript-eslint/no-explicit-any": "warn",
-      "@typescript-eslint/explicit-function-return-type": "error",
-      "@typescript-eslint/explicit-module-boundary-types": "error",
-      "@typescript-eslint/no-floating-promises": "error",
-      "@typescript-eslint/consistent-type-imports": "error"
-    }
-  }
-);
diff --git a/package.json b/package.json
deleted file mode 100644
index 8db2c6d..0000000
--- a/package.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "scripts": {
-    "lint": "eslint . --ext .js,.jsx,.ts,.tsx"
-  },
-  "devDependencies": {
-    "eslint": "^9.0.0",
-    "globals": "^15.0.0",
-    "typescript": "^5.0.0",
-    "typescript-eslint": "latest"
-  }
-}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tooling.apache.org
For additional commands, e-mail: commits-help@tooling.apache.org