Skip to content

Commit 4ade695

Browse files
authored
Merge pull request #2118 from ziadhany/glibc_importer
Add support for glib importer
2 parents 6871324 + a4fc3fe commit 4ade695

9 files changed

Lines changed: 448 additions & 0 deletions

File tree

vulnerabilities/importers/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
from vulnerabilities.pipelines.v2_importers import gentoo_importer as gentoo_importer_v2
5757
from vulnerabilities.pipelines.v2_importers import github_osv_importer as github_osv_importer_v2
5858
from vulnerabilities.pipelines.v2_importers import gitlab_importer as gitlab_importer_v2
59+
from vulnerabilities.pipelines.v2_importers import glibc_importer as glibc_importer_v2
5960
from vulnerabilities.pipelines.v2_importers import istio_importer as istio_importer_v2
6061
from vulnerabilities.pipelines.v2_importers import mattermost_importer as mattermost_importer_v2
6162
from vulnerabilities.pipelines.v2_importers import mozilla_importer as mozilla_importer_v2
@@ -111,6 +112,7 @@
111112
nginx_importer_v2.NginxImporterPipeline,
112113
debian_importer_v2.DebianImporterPipeline,
113114
mattermost_importer_v2.MattermostImporterPipeline,
115+
glibc_importer_v2.GlibcImporterPipeline,
114116
apache_tomcat_v2.ApacheTomcatImporterPipeline,
115117
suse_score_importer_v2.SUSESeverityScoreImporterPipeline,
116118
retiredotnet_importer_v2.RetireDotnetImporterPipeline,
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
#
2+
# Copyright (c) nexB Inc. and others. All rights reserved.
3+
# VulnerableCode is a trademark of nexB Inc.
4+
# SPDX-License-Identifier: Apache-2.0
5+
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
6+
# See https://github.com/aboutcode-org/vulnerablecode for support or download.
7+
# See https://aboutcode.org for more information about nexB OSS projects.
8+
#
9+
10+
from pathlib import Path
11+
12+
import dateparser
13+
from fetchcode.vcs import fetch_via_vcs
14+
from packageurl import PackageURL
15+
from pytz import UTC
16+
from univers.version_range import GenericVersionRange
17+
from univers.versions import InvalidVersion
18+
19+
from vulnerabilities.importer import AdvisoryDataV2
20+
from vulnerabilities.importer import AffectedPackageV2
21+
from vulnerabilities.importer import PackageCommitPatchData
22+
from vulnerabilities.importer import logger
23+
from vulnerabilities.pipelines import VulnerableCodeBaseImporterPipelineV2
24+
from vulnerabilities.utils import build_description
25+
26+
27+
class GlibcImporterPipeline(VulnerableCodeBaseImporterPipelineV2):
28+
"""
29+
Pipeline to collect glibc advisories:
30+
"""
31+
32+
pipeline_id = "glibc_importer_v2"
33+
spdx_license_expression = "LGPL-2.1-only"
34+
license_url = "https://sourceware.org/git/?p=glibc.git;a=blob_plain;f=LICENSES"
35+
repo_url = "git+https://sourceware.org/git/glibc.git"
36+
37+
precedence = 200
38+
39+
@classmethod
40+
def steps(cls):
41+
return (
42+
cls.clone,
43+
cls.collect_and_store_advisories,
44+
cls.clean_downloads,
45+
)
46+
47+
def clone(self):
48+
self.log(f"Cloning `{self.repo_url}`")
49+
self.vcs_response = fetch_via_vcs(self.repo_url)
50+
51+
def advisories_count(self):
52+
root = Path(self.vcs_response.dest_dir) / "advisories"
53+
return sum(1 for _ in root.rglob("*"))
54+
55+
def collect_advisories(self):
56+
base_path = Path(self.vcs_response.dest_dir) / "advisories"
57+
for file_path in base_path.rglob("*"):
58+
if not file_path.name.startswith("GLIBC-SA"):
59+
continue
60+
61+
with open(file_path) as f:
62+
vulnerability_data = f.read()
63+
64+
parsed_items = self.parse_advisory_text(vulnerability_data)
65+
fixed_commits, fixed_versions, affected_commits, affected_versions = [], [], [], []
66+
advisory_id = file_path.name
67+
cve_id = None
68+
summary = None
69+
description = None
70+
date_published = None
71+
for item in parsed_items:
72+
name = item.get("name")
73+
if name == "summary":
74+
summary = item.get("value")
75+
elif name == "description":
76+
description = item.get("value")
77+
elif name == "CVE-Id":
78+
cve_id = item.get("value")
79+
elif name == "Public-Date":
80+
date_published_value = item.get("value")
81+
date_published = dateparser.parse(date_published_value).replace(tzinfo=UTC)
82+
elif name == "Vulnerable-Commit":
83+
fix_commit = item.get("commit")
84+
affected_commits.append(fix_commit)
85+
86+
fixed_version = item.get("version")
87+
affected_versions.append(fixed_version)
88+
elif name == "Fix-Commit":
89+
fix_commit = item.get("commit")
90+
fixed_commits.append(fix_commit)
91+
92+
fixed_version = item.get("version")
93+
fixed_versions.append(fixed_version)
94+
95+
affected_packages = []
96+
purl = PackageURL(
97+
type="sid",
98+
namespace="gnu.org",
99+
name="glibc",
100+
)
101+
102+
affected_version_range = None
103+
try:
104+
affected_version_range = GenericVersionRange.from_versions(affected_versions)
105+
except InvalidVersion as e:
106+
logger.error(
107+
f"InvalidVersion while parsing affected_version_range: {affected_versions} error: {e}"
108+
)
109+
110+
fixed_version_range = None
111+
try:
112+
fixed_version_range = GenericVersionRange.from_versions(fixed_versions)
113+
except InvalidVersion as e:
114+
logger.error(
115+
f"InvalidVersion while parsing fixed_version_range: {fixed_versions} error: {e}"
116+
)
117+
118+
fixed_by_commit_patches = [
119+
PackageCommitPatchData(
120+
vcs_url="https://sourceware.org/git/glibc.git", commit_hash=fixed_commit
121+
)
122+
for fixed_commit in fixed_commits
123+
]
124+
introduced_by_commit_patches = [
125+
PackageCommitPatchData(
126+
vcs_url="https://sourceware.org/git/glibc.git", commit_hash=affected_commit
127+
)
128+
for affected_commit in affected_commits
129+
]
130+
131+
if (
132+
affected_version_range
133+
or fixed_version_range
134+
or introduced_by_commit_patches
135+
or fixed_by_commit_patches
136+
):
137+
affected_packages.append(
138+
AffectedPackageV2(
139+
package=purl,
140+
affected_version_range=affected_version_range,
141+
fixed_version_range=fixed_version_range,
142+
introduced_by_commit_patches=introduced_by_commit_patches,
143+
fixed_by_commit_patches=fixed_by_commit_patches,
144+
)
145+
)
146+
147+
yield AdvisoryDataV2(
148+
advisory_id=advisory_id,
149+
aliases=[cve_id] if cve_id else [],
150+
summary=build_description(summary, description),
151+
affected_packages=affected_packages,
152+
date_published=date_published,
153+
url="https://sourceware.org/git/glibc.git",
154+
)
155+
156+
def parse_advisory_text(self, text):
157+
summary, _, tail = text.partition("\n\n")
158+
description, _, metadata = tail.partition("\n\n")
159+
160+
parsed = [
161+
{"name": "summary", "value": summary},
162+
{"name": "description", "value": description},
163+
]
164+
165+
for line in metadata.splitlines():
166+
name, _, value = line.partition(": ")
167+
if name.endswith(
168+
(
169+
"Commit",
170+
"Backport",
171+
)
172+
):
173+
commit, _, version = value.partition(" ")
174+
parsed.append({"name": name, "commit": commit, "version": version.strip(")(")})
175+
else:
176+
parsed.append({"name": name, "value": value})
177+
return parsed
178+
179+
def clean_downloads(self):
180+
"""Cleanup any temporary repository data."""
181+
if self.vcs_response:
182+
self.log(f"Removing cloned repository")
183+
self.vcs_response.delete()
184+
185+
def on_failure(self):
186+
"""Ensure cleanup is always performed on failure."""
187+
self.clean_downloads()
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#
2+
# Copyright (c) nexB Inc. and others. All rights reserved.
3+
# VulnerableCode is a trademark of nexB Inc.
4+
# SPDX-License-Identifier: Apache-2.0
5+
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
6+
# See https://github.com/aboutcode-org/vulnerablecode for support or download.
7+
# See https://aboutcode.org for more information about nexB OSS projects.
8+
#
9+
10+
from pathlib import Path
11+
from unittest.mock import Mock
12+
from unittest.mock import patch
13+
14+
import pytest
15+
16+
from vulnerabilities.pipelines.v2_importers.glibc_importer import GlibcImporterPipeline
17+
from vulnerabilities.tests import util_tests
18+
19+
TEST_DATA = Path(__file__).parent.parent.parent / "test_data" / "glibc"
20+
21+
TEST_CVE_FILES = [
22+
TEST_DATA / "advisories" / "GLIBC-SA-2023-0001",
23+
TEST_DATA / "advisories" / "GLIBC-SA-2025-0004",
24+
TEST_DATA / "advisories" / "GLIBC-SA-2026-0002",
25+
]
26+
27+
28+
@pytest.mark.django_db
29+
@pytest.mark.parametrize("glibc_file", TEST_CVE_FILES)
30+
def test_glibc_advisories_per_file(glibc_file):
31+
pipeline = GlibcImporterPipeline()
32+
pipeline.vcs_response = Mock(dest_dir=TEST_DATA)
33+
34+
with patch.object(Path, "rglob", return_value=[glibc_file]):
35+
result = [adv.to_dict() for adv in pipeline.collect_advisories()]
36+
37+
expected_file = glibc_file.with_name(glibc_file.stem + "-expected.json")
38+
util_tests.check_results_against_json(result, expected_file)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
printf: incorrect output for integers with thousands separator and width field
2+
3+
When the printf family of functions is called with a format specifier
4+
that uses an <apostrophe> (enable grouping) and a minimum width
5+
specifier, the resulting output could be larger than reasonably expected
6+
by a caller that computed a tight bound on the buffer size. The
7+
resulting larger than expected output could result in a buffer overflow
8+
in the printf family of functions.
9+
10+
CVE-Id: CVE-2023-25139
11+
Public-Date: 2023-02-02
12+
Vulnerable-Commit: e88b9f0e5cc50cab57a299dc7efe1a4eb385161d (2.37)
13+
Fix-Commit: c980549cc6a1c03c23cc2fe3e7b0fe626a0364b0 (2.38)
14+
Fix-Commit: 07b9521fc6369d000216b96562ff7c0ed32a16c4 (2.37-4)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
[
2+
{
3+
"advisory_id": "GLIBC-SA-2023-0001",
4+
"aliases": [
5+
"CVE-2023-25139"
6+
],
7+
"summary": "printf: incorrect output for integers with thousands separator and width field\nWhen the printf family of functions is called with a format specifier\nthat uses an <apostrophe> (enable grouping) and a minimum width\nspecifier, the resulting output could be larger than reasonably expected\nby a caller that computed a tight bound on the buffer size. The\nresulting larger than expected output could result in a buffer overflow\nin the printf family of functions.",
8+
"affected_packages": [
9+
{
10+
"package": {
11+
"type": "sid",
12+
"namespace": "gnu.org",
13+
"name": "glibc",
14+
"version": "",
15+
"qualifiers": "",
16+
"subpath": ""
17+
},
18+
"affected_version_range": "vers:generic/2.37.0",
19+
"fixed_version_range": "vers:generic/2.37.0-4|2.38.0",
20+
"introduced_by_commit_patches": [
21+
{
22+
"vcs_url": "https://sourceware.org/git/glibc.git",
23+
"commit_hash": "e88b9f0e5cc50cab57a299dc7efe1a4eb385161d",
24+
"patch_text": null,
25+
"patch_checksum": null
26+
}
27+
],
28+
"fixed_by_commit_patches": [
29+
{
30+
"vcs_url": "https://sourceware.org/git/glibc.git",
31+
"commit_hash": "c980549cc6a1c03c23cc2fe3e7b0fe626a0364b0",
32+
"patch_text": null,
33+
"patch_checksum": null
34+
},
35+
{
36+
"vcs_url": "https://sourceware.org/git/glibc.git",
37+
"commit_hash": "07b9521fc6369d000216b96562ff7c0ed32a16c4",
38+
"patch_text": null,
39+
"patch_checksum": null
40+
}
41+
]
42+
}
43+
],
44+
"references": [],
45+
"patches": [],
46+
"severities": [],
47+
"date_published": "2023-02-02T00:00:00+00:00",
48+
"weaknesses": [],
49+
"url": "https://sourceware.org/git/glibc.git"
50+
}
51+
]
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
power10: strncmp fails to save and restore nonvolatile vector registers
2+
3+
The Power 10 implementation of strncmp in
4+
sysdeps/powerpc/powerpc64/le/power10/strncmp.S failed to save/restore
5+
nonvolatile vector registers in the 32-byte aligned loop path. This
6+
results in callers reading content from those registers in a different
7+
context, potentially altering program logic.
8+
9+
There could be a program context where a user controlled string could
10+
leak through strncmp into program code, thus altering its logic. There
11+
is also a potential for sensitive strings passed into strncmp leaking
12+
through the clobbered registers into parts of the calling program that
13+
should otherwise not have had access to those strings.
14+
15+
The impact of this flaw is limited to applications running on Power 10
16+
hardware that use the nonvolatile vector registers, i.e. v20 to v31
17+
assuming that they have been treated in accordance with the OpenPower
18+
psABI. It is possible to work around the issue for those specific
19+
applications by setting the glibc.cpu.hwcaps tunable to "-arch_3_1" like
20+
so:
21+
22+
export GLIBC_TUNABLES=glibc.cpu.hwcaps=-arch_3_1
23+
24+
CVE-Id: CVE-2025-5745
25+
Public-Date: 2025-06-05
26+
Vulnerable-Commit: 23f0d81608d0ca6379894ef81670cf30af7fd081 (2.40)
27+
Fix-Commit: 63c60101ce7c5eac42be90f698ba02099b41b965 (2.42)
28+
Fix-Commit: 84bdbf8a6f2fdafd3661489dbb7f79835a52da82 (2.41-57)
29+
Fix-Commit: 42a5a940c974d02540c8da26d6374c744d148cb9 (2.40-136)
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
[
2+
{
3+
"advisory_id": "GLIBC-SA-2025-0004",
4+
"aliases": [
5+
"CVE-2025-5745"
6+
],
7+
"summary": "power10: strncmp fails to save and restore nonvolatile vector registers\nThe Power 10 implementation of strncmp in\nsysdeps/powerpc/powerpc64/le/power10/strncmp.S failed to save/restore\nnonvolatile vector registers in the 32-byte aligned loop path. This\nresults in callers reading content from those registers in a different\ncontext, potentially altering program logic.",
8+
"affected_packages": [
9+
{
10+
"package": {
11+
"type": "sid",
12+
"namespace": "gnu.org",
13+
"name": "glibc",
14+
"version": "",
15+
"qualifiers": "",
16+
"subpath": ""
17+
},
18+
"affected_version_range": "vers:generic/2.40.0",
19+
"fixed_version_range": "vers:generic/2.40.0-136|2.41.0-57|2.42.0",
20+
"introduced_by_commit_patches": [
21+
{
22+
"vcs_url": "https://sourceware.org/git/glibc.git",
23+
"commit_hash": "23f0d81608d0ca6379894ef81670cf30af7fd081",
24+
"patch_text": null,
25+
"patch_checksum": null
26+
}
27+
],
28+
"fixed_by_commit_patches": [
29+
{
30+
"vcs_url": "https://sourceware.org/git/glibc.git",
31+
"commit_hash": "63c60101ce7c5eac42be90f698ba02099b41b965",
32+
"patch_text": null,
33+
"patch_checksum": null
34+
},
35+
{
36+
"vcs_url": "https://sourceware.org/git/glibc.git",
37+
"commit_hash": "84bdbf8a6f2fdafd3661489dbb7f79835a52da82",
38+
"patch_text": null,
39+
"patch_checksum": null
40+
},
41+
{
42+
"vcs_url": "https://sourceware.org/git/glibc.git",
43+
"commit_hash": "42a5a940c974d02540c8da26d6374c744d148cb9",
44+
"patch_text": null,
45+
"patch_checksum": null
46+
}
47+
]
48+
}
49+
],
50+
"references": [],
51+
"patches": [],
52+
"severities": [],
53+
"date_published": "2025-06-05T00:00:00+00:00",
54+
"weaknesses": [],
55+
"url": "https://sourceware.org/git/glibc.git"
56+
}
57+
]

0 commit comments

Comments
 (0)