fix(app-scan): exclude OpenSSL FIPS builds (FP) + per-asset app re-scan button
- OpenSSL FIPS provider builds (e.g. Veeam's 'OpenSSL v3.0.0 FIPS') were matched against OpenSSL CVEs, but the advisories explicitly carve the FIPS modules OUT (vulnerable code is outside the FIPS boundary) and they carry a separate 4-part build version — pure false positive (CVE-2025-15467). Exclude via negative lookahead 'openssl(?!.*fips)'. Existing FP self-heals: next scan no longer detects it -> auto-resolve marks it patched (now audit-logged). - Add an 'App CVE re-scan' action button on asset rows (Wazuh- or Intune-backed assets) that hits the existing POST /vulnerabilities/app-cve-scan?asset_id=, analogous to the Wazuh rescan button.
This commit is contained in:
@@ -71,7 +71,12 @@ _REGISTRY: List[tuple] = [
|
||||
_cpe(r"(?<!\w)putty", "putty:putty"),
|
||||
_cpe(r"winscp", "winscp:winscp"),
|
||||
_cpe(r"wireshark", "wireshark:wireshark"),
|
||||
_cpe(r"openssl", "openssl:openssl"),
|
||||
# Exclude the FIPS provider/module builds (e.g. Veeam ships "OpenSSL v3.0.0
|
||||
# FIPS"): OpenSSL advisories explicitly carve the FIPS modules OUT of most
|
||||
# CVEs (the vulnerable code is outside the FIPS boundary), and they carry a
|
||||
# separate 4-part build version that doesn't map to NVD's ranges anyway →
|
||||
# matching them is a false positive (tester: CVE-2025-15467).
|
||||
_cpe(r"openssl(?!.*fips)", "openssl:openssl"),
|
||||
_cpe(r"openvpn", "openvpn:openvpn"),
|
||||
_cpe(r"node\.?js", "nodejs:node.js"),
|
||||
_cpe(r"(?<!\w)python(?!.*launcher)", "python:python"),
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useEffect, useState } from 'react';
|
||||
import api from '../../lib/api';
|
||||
import { Asset, UserInfo, Group } from '../../types';
|
||||
import Link from 'next/link';
|
||||
import { PencilSquareIcon, TrashIcon, ArrowPathIcon, UserGroupIcon, ChevronDownIcon } from '@heroicons/react/24/outline';
|
||||
import { PencilSquareIcon, TrashIcon, ArrowPathIcon, UserGroupIcon, ChevronDownIcon, MagnifyingGlassIcon } from '@heroicons/react/24/outline';
|
||||
import { UserCircleIcon } from '@heroicons/react/24/solid';
|
||||
|
||||
export default function AssetsPage() {
|
||||
@@ -14,6 +14,7 @@ export default function AssetsPage() {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [rescanLoading, setRescanLoading] = useState<number | null>(null);
|
||||
const [nessusRescanLoading, setNessusRescanLoading] = useState<number | null>(null);
|
||||
const [appScanLoading, setAppScanLoading] = useState<number | null>(null);
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const [searchText, setSearchText] = useState('');
|
||||
const [showInactive, setShowInactive] = useState(false);
|
||||
@@ -223,6 +224,20 @@ export default function AssetsPage() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleAppRescan = async (asset: Asset) => {
|
||||
setAppScanLoading(asset.id);
|
||||
try {
|
||||
const res = await api.post(`/api/v1/vulnerabilities/app-cve-scan?asset_id=${asset.id}`);
|
||||
const d = res.data || {};
|
||||
alert(`App CVE re-scan done for ${asset.hostname}: ${d.findings ?? 0} findings (${d.new ?? 0} new, ${d.resolved ?? 0} auto-resolved).`);
|
||||
fetchAssets();
|
||||
} catch (error: any) {
|
||||
alert(error.response?.data?.detail || 'App re-scan failed.');
|
||||
} finally {
|
||||
setAppScanLoading(null);
|
||||
}
|
||||
};
|
||||
|
||||
const handleNessusRescan = async (asset: Asset) => {
|
||||
if (!asset.ip_address) {
|
||||
alert('Asset has no IP address — Nessus cannot target it.');
|
||||
@@ -717,6 +732,18 @@ export default function AssetsPage() {
|
||||
}
|
||||
</button>
|
||||
)}
|
||||
{(asset.wazuh_agent_id || asset.intune_device_id) && (
|
||||
<button
|
||||
onClick={() => handleAppRescan(asset)}
|
||||
disabled={appScanLoading === asset.id}
|
||||
title="App CVE re-scan — match this asset's installed software to CVEs (curated + cvelistV5)"
|
||||
className={`${appScanLoading === asset.id ? 'text-gray-300' : 'text-emerald-600 hover:text-emerald-800'}`}
|
||||
>
|
||||
{appScanLoading === asset.id
|
||||
? <ArrowPathIcon className="h-5 w-5 animate-spin" />
|
||||
: <MagnifyingGlassIcon className="h-5 w-5" />}
|
||||
</button>
|
||||
)}
|
||||
{(asset.wazuh_agent_id || asset.nessus_host_uuid) && (
|
||||
<button
|
||||
onClick={() => handleCoverageGap(asset)}
|
||||
|
||||
Reference in New Issue
Block a user