Add Alpine security advisory importer#2203
Add Alpine security advisory importer#2203NucleiAv wants to merge 3 commits intoaboutcode-org:mainfrom
Conversation
4e049cb to
2d68893
Compare
ziadhany
left a comment
There was a problem hiding this comment.
@NucleiAv Fetching JSON-LD is a good idea instead of parsing the HTML. We have a similar importer for Alpine
see: alpine_linux_importer_v2.AlpineLinuxImporterPipeline.
However, the alpine_linux_importer_v2 importer misses some data there, which is why I think we need this importer.
| @@ -0,0 +1 @@ | |||
| {"@context":"https://security.alpinelinux.org/static/context.jsonld","cpeMatch":[{"@context":"https://security.alpinelinux.org/static/context.jsonld","cpeUri":"","id":"https://security.alpinelinux.org/vuln/CVE-2025-46836#cpeMatch/940449","maximumVersion":"2.10","maximumVersionOp":"<=","minimumVersion":"0","minimumVersionOp":">=","package":"https://security.alpinelinux.org/srcpkg/net-tools","type":"CPEMatch","vuln":"https://security.alpinelinux.org/vuln/CVE-2025-46836"}],"cvss3":{"score":6.6,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:H"},"description":"net-tools is a collection of programs that form the base set of the NET-3 networking distribution for the Linux operating system. Inn versions up to and including 2.10, the Linux network utilities (like ifconfig) from the net-tools package do not properly validate the structure of /proc files when showing interfaces. `get_name()` in `interface.c` copies interface labels from `/proc/net/dev` into a fixed 16-byte stack buffer without bounds checking, leading to possible arbitrary code execution or crash. The known attack path does not require privilege but also does not provide privilege escalation in this scenario. A patch is available and expected to be part of version 2.20.","id":"https://security.alpinelinux.org/vuln/CVE-2025-46836","ref":[{"@context":"https://security.alpinelinux.org/static/context.jsonld","id":"https://security.alpinelinux.org/vuln/CVE-2025-46836#ref/588613","referenceType":"MISC","rel":"https://github.com/ecki/net-tools/commit/7a8f42fb20013a1493d8cae1c43436f85e656f2d","type":"Reference"},{"@context":"https://security.alpinelinux.org/static/context.jsonld","id":"https://security.alpinelinux.org/vuln/CVE-2025-46836#ref/588614","referenceType":"CONFIRM","rel":"https://github.com/ecki/net-tools/security/advisories/GHSA-pfwf-h6m3-63wf","type":"Reference"},{"@context":"https://security.alpinelinux.org/static/context.jsonld","id":"https://security.alpinelinux.org/vuln/CVE-2025-46836#ref/593944","referenceType":"af854a3a-2127-422b-91ae-364da2661108","rel":"https://lists.debian.org/debian-lts-announce/2025/05/msg00053.html","type":"Reference"}],"state":[{"@context":"https://security.alpinelinux.org/static/context.jsonld","fixed":false,"id":"https://security.alpinelinux.org/vuln/CVE-2025-46836#state/108203","packageVersion":"https://security.alpinelinux.org/srcpkg/net-tools/2.10-r3","repo":"edge-main","type":"VulnerabilityState","vuln":"https://security.alpinelinux.org/vuln/CVE-2025-46836"},{"@context":"https://security.alpinelinux.org/static/context.jsonld","fixed":false,"id":"https://security.alpinelinux.org/vuln/CVE-2025-46836#state/415014","packageVersion":"https://security.alpinelinux.org/srcpkg/net-tools/2.10-r3","repo":"3.23-main","type":"VulnerabilityState","vuln":"https://security.alpinelinux.org/vuln/CVE-2025-46836"},{"@context":"https://security.alpinelinux.org/static/context.jsonld","fixed":false,"id":"https://security.alpinelinux.org/vuln/CVE-2025-46836#state/125956","packageVersion":"https://security.alpinelinux.org/srcpkg/net-tools/2.10-r3","repo":"3.22-main","type":"VulnerabilityState","vuln":"https://security.alpinelinux.org/vuln/CVE-2025-46836"},{"@context":"https://security.alpinelinux.org/static/context.jsonld","fixed":false,"id":"https://security.alpinelinux.org/vuln/CVE-2025-46836#state/127510","packageVersion":"https://security.alpinelinux.org/srcpkg/net-tools/2.10-r3","repo":"3.21-main","type":"VulnerabilityState","vuln":"https://security.alpinelinux.org/vuln/CVE-2025-46836"},{"@context":"https://security.alpinelinux.org/static/context.jsonld","fixed":false,"id":"https://security.alpinelinux.org/vuln/CVE-2025-46836#state/127996","packageVersion":"https://security.alpinelinux.org/srcpkg/net-tools/2.10-r3","repo":"3.20-main","type":"VulnerabilityState","vuln":"https://security.alpinelinux.org/vuln/CVE-2025-46836"},{"@context":"https://security.alpinelinux.org/static/context.jsonld","fixed":false,"id":"https://security.alpinelinux.org/vuln/CVE-2025-46836#state/128449","packageVersion":"https://security.alpinelinux.org/srcpkg/net-tools/2.10-r3","repo":"3.19-main","type":"VulnerabilityState","vuln":"https://security.alpinelinux.org/vuln/CVE-2025-46836"}],"type":"Vulnerability"} | |||
There was a problem hiding this comment.
Can you use a pretty format to make this JSON-LD more readable?
| "references": [ | ||
| { | ||
| "reference_id": "", | ||
| "reference_type": "", |
There was a problem hiding this comment.
We are missing reference_type
| "reference_type": "", | |
| "reference_type": "patch", |
There was a problem hiding this comment.
Fixed, reference_type is now mapped directly from the referenceType field in each ref entry.
| cvss3 = data.get("cvss3") or {} | ||
| cvss_score = cvss3.get("score") | ||
| cvss_vector = cvss3.get("vector") or "" | ||
| if cvss_vector and cvss_score: | ||
| if cvss_vector.startswith("CVSS:3.1/"): | ||
| system = SCORING_SYSTEMS["cvssv3.1"] | ||
| else: | ||
| system = SCORING_SYSTEMS["cvssv3"] | ||
| severities.append( | ||
| VulnerabilitySeverity( | ||
| system=system, | ||
| value=str(cvss_score), | ||
| scoring_elements=cvss_vector, | ||
| ) | ||
| ) |
There was a problem hiding this comment.
Are you sure we only have CVSS3 ?
There was a problem hiding this comment.
Yes. I sampled 20+ live advisories across multiple branches and the API only ever returns a cvss3 key at the top level. No cvss2 or cvss4 fields exist in the JSON-LD schema for this endpoint.
| for ref in data.get("ref") or []: | ||
| ref_url = ref.get("rel") or "" | ||
| if ref_url: | ||
| references.append(ReferenceV2(url=ref_url)) |
There was a problem hiding this comment.
cpe uri should be stored as a reference
"cpeUri": "cpe:2.3:a:perl:perl:*:*:*:*:*:*:*:*",
"id": "https://security.alpinelinux.org/vuln/CVE-2024-56406#cpeMatch/917070",
```l
There was a problem hiding this comment.
Done, non-empty cpeUri entries are now added as references with reference_id=cpe_uri and url=cpe_id.
| resp = requests.get(url, headers=ADVISORY_HEADERS, timeout=30) | ||
| resp.raise_for_status() | ||
| data = resp.json() | ||
| except Exception as e: |
There was a problem hiding this comment.
please avoid general exception
There was a problem hiding this comment.
Fixed, replaced bare except Exception with (requests.RequestException, ValueError) in all catch sites.
Signed-off-by: Anmol Vats <anmolvats2003@gmail.com>
Signed-off-by: Anmol Vats <anmolvats2003@gmail.com>
2d68893 to
a5e8b61
Compare
|
@ziadhany On it! Also, the feedback you gave on my ZDI PR has already been applied across all my other PRs as well (dateparser instead of strptime, find_all_cve from utils, no seen_ids, no repo_url). Pipeline logs are included in all of them too. |
Adds AlpineSecurityImporterPipeline to collect advisories from https://security.alpinelinux.org via its JSON-LD API.
Active branches are discovered dynamically from the root endpoint so new branches are picked up automatically without code changes. HISTORICAL_BRANCHES covers EOL branches that still have data but no longer appear in the root index (3.10 through 3.18, 3.22-community). Branches 3.13 through 3.16 are excluded as the API returns 0 items.
Each advisory is parsed for CVE id, CVSS 3.x severity (version detected from the vector prefix), reference URLs, and fixed package versions as apk PURLs with distroversion and reponame qualifiers. Tests use real API fixture data and cover CVSS parsing, fixed states, missing advisory id, malformed package URLs, and unfixed states.