-
-
Notifications
You must be signed in to change notification settings - Fork 291
Add KDE security advisory importer #2178
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Tarun-goswamii
wants to merge
1
commit into
aboutcode-org:main
from
Tarun-goswamii:feature/kde-security-advisories-1939
+348
−0
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,189 @@ | ||
| # | ||
| # Copyright (c) nexB Inc. and others. All rights reserved. | ||
| # VulnerableCode is a trademark of nexB Inc. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # See http://www.apache.org/licenses/LICENSE-2.0 for the license text. | ||
| # See https://github.com/aboutcode-org/vulnerablecode for support or download. | ||
| # See https://aboutcode.org for more information about nexB OSS projects. | ||
| # | ||
|
|
||
| import logging | ||
| import re | ||
| from typing import Iterable | ||
|
|
||
| import requests | ||
| from bs4 import BeautifulSoup | ||
|
|
||
| from vulnerabilities.importer import AdvisoryData | ||
| from vulnerabilities.importer import Importer | ||
| from vulnerabilities.importer import Reference | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| class KdeImporter(Importer): | ||
| spdx_license_expression = "LGPL-2.0-or-later" | ||
| license_url = "https://kde.org/community/whatiskde/licensing/" | ||
| importer_name = "KDE Importer" | ||
| url = "https://kde.org/info/security/" | ||
|
|
||
| def advisory_data(self) -> Iterable[AdvisoryData]: | ||
| advisory_urls = fetch_advisory_urls(self.url) | ||
| for advisory_url in advisory_urls: | ||
| try: | ||
| advisory_text = fetch_advisory_text(advisory_url) | ||
| advisory = parse_advisory(advisory_text, advisory_url) | ||
| if advisory: | ||
| yield advisory | ||
| except Exception as e: | ||
| logger.error(f"Error parsing advisory {advisory_url}: {e}") | ||
|
|
||
|
|
||
| def fetch_advisory_urls(index_url): | ||
| """ | ||
| Fetch all advisory URLs from the KDE security index page. | ||
|
|
||
| Returns: | ||
| List of full advisory URLs | ||
| """ | ||
| response = requests.get(index_url) | ||
| if response.status_code != 200: | ||
| logger.error(f"Failed to fetch {index_url}") | ||
| return [] | ||
|
|
||
| soup = BeautifulSoup(response.content, "html.parser") | ||
| advisory_urls = [] | ||
|
|
||
| # Find all links in the page | ||
| for link in soup.find_all("a"): | ||
| href = link.get("href", "") | ||
| # Advisory files end with .txt and start with advisory- or contain xpdf | ||
| if href.endswith(".txt") and ("advisory-" in href or "xpdf" in href): | ||
| # Convert relative URL to absolute | ||
| if href.startswith("./"): | ||
| href = href[2:] | ||
| full_url = f"https://kde.org/info/security/{href}" | ||
| advisory_urls.append(full_url) | ||
|
|
||
| return advisory_urls | ||
|
|
||
|
|
||
| def fetch_advisory_text(advisory_url): | ||
| """ | ||
| Fetch the text content of a KDE security advisory. | ||
|
|
||
| Returns: | ||
| Advisory text as string | ||
| """ | ||
| response = requests.get(advisory_url) | ||
| if response.status_code != 200: | ||
| logger.error(f"Failed to fetch {advisory_url}") | ||
| return None | ||
|
|
||
| return response.text | ||
|
|
||
|
|
||
| def parse_advisory(advisory_text, advisory_url): | ||
| """ | ||
| Parse a KDE security advisory and extract relevant information. | ||
|
|
||
| Args: | ||
| advisory_text: The full text content of the advisory | ||
| advisory_url: URL of the advisory | ||
|
|
||
| Returns: | ||
| AdvisoryData object or None | ||
| """ | ||
| if not advisory_text: | ||
| return None | ||
|
|
||
| # Extract CVE IDs (both CVE and old CAN format) | ||
| cve_pattern = r'C(?:VE|AN)-\d{4}-\d{4,7}' | ||
| cve_ids = re.findall(cve_pattern, advisory_text) | ||
|
|
||
| # Convert old CAN format to CVE format | ||
| aliases = [] | ||
| for cve_id in cve_ids: | ||
| if cve_id.startswith("CAN-"): | ||
| # CAN is old format, convert to CVE | ||
| cve_id = cve_id.replace("CAN-", "CVE-") | ||
| if cve_id not in aliases: | ||
| aliases.append(cve_id) | ||
|
|
||
| # Extract summary/title | ||
| summary = extract_summary(advisory_text) | ||
|
|
||
| # Extract references | ||
| references = extract_references(advisory_text, advisory_url, aliases) | ||
|
|
||
| # Only create advisory if we have CVE IDs or meaningful content | ||
| if not aliases and not summary: | ||
| logger.warning(f"No CVE IDs or summary found in {advisory_url}") | ||
| return None | ||
|
|
||
| return AdvisoryData( | ||
| aliases=aliases, | ||
| summary=summary, | ||
| references=references, | ||
| url=advisory_url, | ||
| ) | ||
|
|
||
|
|
||
| def extract_summary(advisory_text): | ||
| """ | ||
| Extract the summary/title from the advisory text. | ||
| """ | ||
| lines = advisory_text.split("\n") | ||
|
|
||
| # Try to find Title: field (new format) | ||
| for i, line in enumerate(lines): | ||
| if line.startswith("Title:"): | ||
| return line.replace("Title:", "").strip() | ||
|
|
||
| # Try to find KDE Security Advisory: line (old format) | ||
| for line in lines: | ||
| if "KDE Security Advisory:" in line: | ||
| return line.replace("KDE Security Advisory:", "").strip() | ||
|
|
||
| # Try to find first non-empty line after PGP header | ||
| skip_pgp = False | ||
| for line in lines: | ||
| if line.startswith("-----BEGIN PGP"): | ||
| skip_pgp = True | ||
| continue | ||
| if skip_pgp and line.strip() and not line.startswith("Hash:"): | ||
| skip_pgp = False | ||
| continue | ||
| if not skip_pgp and line.strip() and not line.startswith("---"): | ||
| # Return first meaningful line as summary | ||
| return line.strip() | ||
|
|
||
| return "" | ||
|
|
||
|
|
||
| def extract_references(advisory_text, advisory_url, aliases): | ||
| """ | ||
| Extract reference URLs from the advisory text. | ||
| """ | ||
| references = [] | ||
|
|
||
| # Add the advisory itself as a reference | ||
| references.append(Reference(url=advisory_url)) | ||
|
|
||
| # Add CVE references | ||
| for cve_id in aliases: | ||
| cve_url = f"https://cve.mitre.org/cgi-bin/cvename.cgi?name={cve_id}" | ||
| references.append(Reference(url=cve_url, reference_id=cve_id)) | ||
|
|
||
| # Extract URLs from text | ||
| url_pattern = r'https?://[^\s<>"\')]+[^\s<>"\')\.]' | ||
| urls = re.findall(url_pattern, advisory_text) | ||
|
|
||
| for url in urls: | ||
| # Skip if already added | ||
| if any(ref.url == url for ref in references): | ||
| continue | ||
| # Add unique URLs | ||
| references.append(Reference(url=url)) | ||
|
|
||
| return references | ||
50 changes: 50 additions & 0 deletions
50
vulnerabilities/tests/test_data/kde/advisory-20030916-1.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| -----BEGIN PGP SIGNED MESSAGE----- | ||
| Hash: SHA1 | ||
|
|
||
|
|
||
|
|
||
| KDE Security Advisory: KDM vulnerabilities | ||
| Original Release Date: 2003-09-16 | ||
| URL: http://www.kde.org/info/security/advisory-20030916-1.txt | ||
|
|
||
| 0. References | ||
| http://cert.uni-stuttgart.de/archive/suse/security/2002/12/msg00101.html | ||
| http://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2003-0690 | ||
| http://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2003-0692 | ||
|
|
||
|
|
||
| 1. Systems affected: | ||
|
|
||
| All versions of KDM as distributed with KDE up to and including | ||
| KDE 3.1.3. | ||
|
|
||
|
|
||
| 2. Overview: | ||
|
|
||
| Two issues have been discovered in KDM: | ||
|
|
||
| a) CAN-2003-0690: | ||
| Privilege escalation with specific PAM modules | ||
| b) CAN-2003-0692: | ||
| Session cookies generated by KDM are potentially insecure | ||
|
|
||
|
|
||
| 3. Impact: | ||
|
|
||
| If KDM is used in combination with the MIT pam_krb5 module and given | ||
| a valid username and password of an existing user, the login attempt | ||
| succeeds and establishes a session with excessive privileges. | ||
|
|
||
|
|
||
| 4. Solution: | ||
|
|
||
| Users of KDE 3.1.x are advised to upgrade to KDE 3.1.4. | ||
|
|
||
|
|
||
| -----BEGIN PGP SIGNATURE----- | ||
| Version: GnuPG v1.2.2-rc1-SuSE (GNU/Linux) | ||
|
|
||
| iD8DBQE/Z1fBvsXr+iuy1UoRAi02AJ90TqHxCeqzqGJrN3jS7mRSd9u5xQCg6/Do | ||
| LB3tubiwfy8TUy5rL7B8UFY= | ||
| =2tbX | ||
| -----END PGP SIGNATURE----- |
31 changes: 31 additions & 0 deletions
31
vulnerabilities/tests/test_data/kde/advisory-20260109-1.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| KDE Project Security Advisory | ||
| ============================= | ||
|
|
||
| Title: Smb4K: Major security issues in KAuth mount helper | ||
| Risk rating: Major | ||
| CVE: CVE-2025-66002, CVE-2025-66003 | ||
| Versions: Smb4K < 4.0.5 | ||
| Date: 9 January 2026 | ||
|
|
||
| Overview | ||
| ======== | ||
|
|
||
| The privileged KAuth mount helper of Smb4K runs with full root privileges and implements two KAuth actions accessible via D-Bus: mounting and unmounting a network share. | ||
|
|
||
|
|
||
| Impact | ||
| ====== | ||
|
|
||
| An attacker can exploit the shortcomings in the KAuth mount helper and perform arbitrary unmounts. | ||
|
|
||
|
|
||
| Solution | ||
| ======== | ||
|
|
||
| Update Smb4K to version 4.0.5 or later. | ||
|
|
||
|
|
||
| Credits | ||
| ======= | ||
|
|
||
| Thanks to Matthias Gerstner and the SUSE security team for reporting this issue. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| # | ||
| # Copyright (c) nexB Inc. and others. All rights reserved. | ||
| # VulnerableCode is a trademark of nexB Inc. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # See http://www.apache.org/licenses/LICENSE-2.0 for the license text. | ||
| # See https://github.com/aboutcode-org/vulnerablecode for support or download. | ||
| # See https://aboutcode.org for more information about nexB OSS projects. | ||
| # | ||
|
|
||
| import os | ||
| from unittest import TestCase | ||
|
|
||
| from vulnerabilities.importers.kde import extract_summary | ||
| from vulnerabilities.importers.kde import parse_advisory | ||
|
|
||
| BASE_DIR = os.path.dirname(os.path.abspath(__file__)) | ||
| TEST_DATA = os.path.join(BASE_DIR, "test_data/kde") | ||
|
|
||
|
|
||
| class TestKdeImporter(TestCase): | ||
| def test_parse_old_format_advisory(self): | ||
| """Test parsing old format PGP-signed advisory""" | ||
| with open(os.path.join(TEST_DATA, "advisory-20030916-1.txt"), "r") as f: | ||
| advisory_text = f.read() | ||
|
|
||
| advisory_url = "https://kde.org/info/security/advisory-20030916-1.txt" | ||
| result = parse_advisory(advisory_text, advisory_url) | ||
|
|
||
| # Check that CVE IDs were extracted and converted from CAN format | ||
| assert "CVE-2003-0690" in result.aliases | ||
| assert "CVE-2003-0692" in result.aliases | ||
| assert len(result.aliases) == 2 | ||
|
|
||
| # Check summary was extracted | ||
| assert "KDM vulnerabilities" in result.summary | ||
|
|
||
| # Check references include CVE URLs | ||
| cve_urls = [ref.url for ref in result.references if "cve.mitre.org" in ref.url] | ||
| assert len(cve_urls) == 2 | ||
|
|
||
| def test_parse_new_format_advisory(self): | ||
| """Test parsing new format advisory""" | ||
| with open(os.path.join(TEST_DATA, "advisory-20260109-1.txt"), "r") as f: | ||
| advisory_text = f.read() | ||
|
|
||
| advisory_url = "https://kde.org/info/security/advisory-20260109-1.txt" | ||
| result = parse_advisory(advisory_text, advisory_url) | ||
|
|
||
| # Check CVE IDs were extracted | ||
| assert "CVE-2025-66002" in result.aliases | ||
| assert "CVE-2025-66003" in result.aliases | ||
|
|
||
| # Check title was extracted | ||
| assert "Smb4K" in result.summary | ||
|
|
||
| def test_extract_summary_old_format(self): | ||
| """Test summary extraction from old format""" | ||
| advisory_text = """-----BEGIN PGP SIGNED MESSAGE----- | ||
| Hash: SHA1 | ||
|
|
||
|
|
||
|
|
||
| KDE Security Advisory: KDM vulnerabilities | ||
| Original Release Date: 2003-09-16""" | ||
|
|
||
| summary = extract_summary(advisory_text) | ||
| assert "KDM vulnerabilities" in summary | ||
|
|
||
| def test_extract_summary_new_format(self): | ||
| """Test summary extraction from new format""" | ||
| advisory_text = """KDE Project Security Advisory | ||
| ============================= | ||
|
|
||
| Title: Smb4K: Major security issues | ||
| Risk rating: Major""" | ||
|
|
||
| summary = extract_summary(advisory_text) | ||
| assert "Smb4K" in summary |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be V2 importer, not V1