From 29aefbf64a58b70d5eeb25356f9ae28346c1eb51 Mon Sep 17 00:00:00 2001 From: Mark Gregory Date: Thu, 22 Oct 2026 18:32:03 +0100 Subject: [PATCH] Updates to scanner with CVE saving and auto update --- PHPGuard/ContentView.swift | 75 ++++++++++++++++++++++++++++++++++++++ PHPGuard/SSHScanner.swift | 16 ++++++++ 2 files changed, 91 insertions(+) diff --git a/PHPGuard/ContentView.swift b/PHPGuard/ContentView.swift index f875cbb..e4e41e3 100644 --- a/PHPGuard/ContentView.swift +++ b/PHPGuard/ContentView.swift @@ -230,6 +230,81 @@ struct ContentView: View { .background(.quaternary.opacity(0.22), in: RoundedRectangle(cornerRadius: 10)) } } + // Repository matching and binary verification are + // separate from vendor CVE verification. + VStack(alignment: .leading, spacing: 10) { + Text("Package provenance") + .font(.title2.bold()) + + let ubuntuMatches = result.packageOrigins.filter { + $0.hasPrefix("UBUNTU_REPOSITORY_MATCH|") + }.count + + let otherMatches = result.packageOrigins.filter { + $0.hasPrefix("OTHER_REPOSITORY_MATCH|") + }.count + + let totalMatches = ubuntuMatches + otherMatches + + if totalMatches > 0 { + Label( + "\(ubuntuMatches) PHP packages match official Ubuntu repository versions", + systemImage: "checkmark.circle.fill" + ) + .foregroundStyle(.green) + + if otherMatches > 0 { + Label( + "\(otherMatches) packages match other repository versions", + systemImage: "exclamationmark.triangle.fill" + ) + .foregroundStyle(.orange) + } else { + Label( + "No third-party repository matches detected", + systemImage: "checkmark.circle" + ) + .foregroundStyle(.secondary) + } + } else { + Label( + "No repository version matches collected", + systemImage: "questionmark.circle" + ) + .foregroundStyle(.orange) + } + + Label( + "Installed binary integrity: Not independently verified", + systemImage: "shield.lefthalf.filled" + ) + .foregroundStyle(.orange) + + let verifiedCVEs = result.cveAssessments.filter { + ["Vulnerable", "Patched", "Not affected"] + .contains($0.vendorStatus ?? "") + }.count + + Text( + "CVE assessment: \(result.cveAssessments.count) candidates; " + + "\(verifiedCVEs) vendor-verified" + ) + .font(.subheadline) + + Text( + "Repository version matches do not establish binary integrity " + + "or whether a particular CVE affects the installed packages." + ) + .font(.caption) + .foregroundStyle(.secondary) + } + .padding(12) + .frame(maxWidth: .infinity, alignment: .leading) + .background( + .quaternary.opacity(0.22), + in: RoundedRectangle(cornerRadius: 10) + ) + HStack { Text("Security findings").font(.title2.bold()) Spacer() diff --git a/PHPGuard/SSHScanner.swift b/PHPGuard/SSHScanner.swift index f912aec..5919e23 100644 --- a/PHPGuard/SSHScanner.swift +++ b/PHPGuard/SSHScanner.swift @@ -506,6 +506,22 @@ enum SSHScanner { .map { String($0.dropFirst("VERSION_CODENAME=".count)) } ?? "" result.availableUpdates = fields["UPDATES"] ?? [] result.packageOrigins = fields["PACKAGE_ORIGINS"] ?? [] + + let ubuntuMatchCount = result.packageOrigins.filter { + $0.hasPrefix("UBUNTU_REPOSITORY_MATCH|") + }.count + + let otherMatchCount = result.packageOrigins.filter { + $0.hasPrefix("OTHER_REPOSITORY_MATCH|") + }.count + + NSLog( + "PHPGuard provenance: host=%@ ubuntuMatches=%d otherMatches=%d totalOrigins=%d", + result.hostname, + ubuntuMatchCount, + otherMatchCount, + result.packageOrigins.count + ) result.recentPHPFiles = (fields["RECENT_PHP_FILES"] ?? []).filter { $0 != "Web root unavailable" } let nginxLines = fields["WEB_ERROR_SIGNALS"] ?? []