Skip to content

Commit

Permalink
EPSS-CISA Data
Browse files Browse the repository at this point in the history
  • Loading branch information
fatihtokus committed Feb 1, 2025
1 parent 48d50ae commit 4de40c8
Show file tree
Hide file tree
Showing 13 changed files with 204 additions and 83 deletions.
8 changes: 0 additions & 8 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,6 @@
"mode": "debug",
"program": "${workspaceFolder}",
"args": ["image", "--scanners", "vuln", "ruby:3.1", "interactive_report.html"]
},
{
"name": "Debug scan2htmlBash",
"type": "bashdb",
"request": "launch",
"program": "${workspaceFolder}/scan2html",
"args": ["trivy", "scan2html", "image", "--format", "spdx", "ghcr.io/zalando/spilo-15:3.0-p1", "test-report.html"]
//"args": ["test/assets/app-template-test.html", "test/data/default/results.json", "test-report.html"]
}
]
}
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,10 @@ Examples:
# Scan and generate SBOM(spdx) report
trivy scan2html image --format spdx alpine:3.15 --scan2html-flags --output interactive_report.html

# Generate a report from multiple json scan results - experimental
# Generate a report from multiple json scan results
trivy scan2html generate --scan2html-flags --output interactive_report.html --from vulnerabilities.json,misconfigs.json,secrets.json

# Generate report with EPSS scores from multiple scan results - experimental
# Generate report with EPSS scores from multiple scan results
trivy scan2html generate --scan2html-flags --with-epss --output interactive_report.html --from vulnerabilities.json,misconfigs.json,secrets.json

```
3 changes: 2 additions & 1 deletion internal/common/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ package common

import (
"fmt"
"scan2html/internal/logger"
"os"
"scan2html/internal/logger"
)

var AvailableFlags = map[string]bool{
// name : is boolean
"--scan2html-flags": true,
"--output": false,
"--with-epss": true,
"--with-exploits": true,
"--report-title": false,
"generate": true,
"--from": false,
Expand Down
32 changes: 32 additions & 0 deletions internal/exploit/downloader.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package exploit

import (
"fmt"
"os"
"path/filepath"
"scan2html/internal/epss"
"scan2html/internal/logger"
)

// PrepareExploitData downloads the CISA dataset, saves it as a temporary file,
func PrepareExploitData() (string, error) {
const (
cisaURL = "https://www.cisa.gov/sites/default/files/feeds"
cisaFileName = "known_exploited_vulnerabilities.json"
)

// Define paths
tmpCisaFilepath := filepath.Join(os.TempDir(), cisaFileName)
cisaDownloadUrl := fmt.Sprintf("%s/%s", cisaURL, cisaFileName)
logger.Logger.Infof("Downloading Exploit data from: %s\n", cisaDownloadUrl)

if err := epss.DownloadFile(cisaDownloadUrl, tmpCisaFilepath); err != nil {
return "", err
}
logger.Logger.Infof("Exploit data downloaded to: %s\n", tmpCisaFilepath)

stats, _ := os.Stat(tmpCisaFilepath)
logger.Logger.Infof("File decompressed successfully to %s with size of: %d bytes\n", tmpCisaFilepath, stats.Size())

return tmpCisaFilepath, nil
}
98 changes: 66 additions & 32 deletions internal/report/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"path/filepath"
"scan2html/internal/common"
"scan2html/internal/epss"
"scan2html/internal/exploit"
"scan2html/internal/logger"
"strings"
"time"
Expand All @@ -25,10 +26,12 @@ func GenerateHtmlReport(pluginFlags common.Flags, version string) error {

reportName := pluginFlags["--output"]
_, withEpss := pluginFlags["--with-epss"]
_, withExploits := pluginFlags["--with-exploits"]
reportTitle := pluginFlags["--report-title"]
// Log input parameters for clarity
logger.Logger.Infof("Base Directory: %s\n", baseDir)
logger.Logger.Infof("With EPSS: %t\n", withEpss)
logger.Logger.Infof("With Exploits: %t\n", withExploits)
logger.Logger.Infof("Report Title: %s\n", reportTitle)
logger.Logger.Infof("Report Name: %s\n", reportName)

Expand Down Expand Up @@ -57,26 +60,58 @@ func GenerateHtmlReport(pluginFlags common.Flags, version string) error {
}

// Handle EPSS data if enabled
// replaceTextByFile "$report_name" "\"TEMP_EPSS_DATA\"" "$epss_data"
// Schedule deletion of the EPSS data file upon function exit
shouldReturn, returnValue := handleEPSS(withEpss, reportName)
if shouldReturn {
return returnValue
}

shouldReturn, returnValue = handleExploit(withExploits, reportName)
if shouldReturn {
return returnValue
}

logger.Logger.Infof("%s has been created successfully!\n", reportName)
return nil
}

func handleEPSS(withEpss bool, reportName string) (bool, error) {
if withEpss {
logger.Logger.Infoln("EPSS enabled!")
var epssDataFile, err = epss.PrepareEpssData()
if err != nil {
return fmt.Errorf("failed to prepare EPSS data: %v", err)
return true, fmt.Errorf("failed to prepare EPSS data: %v", err)
}

// replaceTextByFile "$report_name" "\"TEMP_EPSS_DATA\"" "$epss_data"
if err := replaceTextByFile(reportName, "\"TEMP_EPSS_DATA\"", epssDataFile); err != nil {
return fmt.Errorf("failed to replace EPSS data in %s: %v", reportName, err)
return true, fmt.Errorf("failed to replace EPSS data in %s: %v", reportName, err)
}

logger.Logger.Infoln("EPSS data imported!")

// Schedule deletion of the EPSS data file upon function exit
defer os.Remove(epssDataFile)
}
return false, nil
}

logger.Logger.Infof("%s has been created successfully!\n", reportName)
return nil
func handleExploit(withExploits bool, reportName string) (bool, error) {
if withExploits {
logger.Logger.Infoln("Exploits enabled!")
var exploitDataFile, err = exploit.PrepareExploitData()
if err != nil {
return true, fmt.Errorf("failed to prepare Exploits data: %v", err)
}

if err := replaceTextByFile(reportName, "{TEMP_EXPLOITS:0}", exploitDataFile); err != nil {
return true, fmt.Errorf("failed to replace Exploits data in %s: %v", reportName, err)
}

logger.Logger.Infoln("Exploits data imported!")

defer os.Remove(exploitDataFile)
}
return false, nil
}

// replaceTextByText replaces occurrences of search_text in the input file with replace_content.
Expand Down Expand Up @@ -119,36 +154,35 @@ func replaceTextByText(inputFile, searchText, replaceContent string) error {
return fmt.Errorf("error writing to temp file: %v", err)
}


return copyAndRemove(tempFile.Name(), inputFile)
}

func copyAndRemove(src, dst string) error {
// Open the source file
sourceFile, err := os.Open(src)
if err != nil {
return err
}
defer sourceFile.Close()

// Create the destination file
destFile, err := os.Create(dst)
if err != nil {
return err
}
defer destFile.Close()

// Copy the contents
if _, err := io.Copy(destFile, sourceFile); err != nil {
return err
}

// Close files before removal
sourceFile.Close()
destFile.Close()

// Remove the source file
return os.Remove(src)
// Open the source file
sourceFile, err := os.Open(src)
if err != nil {
return err
}
defer sourceFile.Close()

// Create the destination file
destFile, err := os.Create(dst)
if err != nil {
return err
}
defer destFile.Close()

// Copy the contents
if _, err := io.Copy(destFile, sourceFile); err != nil {
return err
}

// Close files before removal
sourceFile.Close()
destFile.Close()

// Remove the source file
return os.Remove(src)
}

// replaceTextByFile replaces occurrences of search_text in the input file with content from replace_file.
Expand Down
24 changes: 12 additions & 12 deletions release-candidate/plugin.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: "scan2html"
version: "0.3.15-rc.1"
version: "0.3.16-rc.1"
maintainer: fatihtokus
repository: github.com/fatihtokus/scan2html
summary: A Trivy plugin that scans and outputs the results to a single page app.
Expand All @@ -12,58 +12,58 @@ platforms:
- selector:
os: linux
arch: amd64
uri: https://github.com/fatihtokus/scan2html/releases/download/v0.3.15-rc.1/scan2html_0.3.15-rc.1_linux-amd64.tar.gz
uri: https://github.com/fatihtokus/scan2html/releases/download/v0.3.16-rc.1/scan2html_0.3.16-rc.1_linux-amd64.tar.gz
bin: ./scan2html
- selector:
os: linux
arch: arm
uri: https://github.com/fatihtokus/scan2html/releases/download/v0.3.15-rc.1/scan2html_0.3.15-rc.1_linux-arm.tar.gz
uri: https://github.com/fatihtokus/scan2html/releases/download/v0.3.16-rc.1/scan2html_0.3.16-rc.1_linux-arm.tar.gz
bin: ./scan2html
- selector:
os: linux
arch: arm64
uri: https://github.com/fatihtokus/scan2html/releases/download/v0.3.15-rc.1/scan2html_0.3.15-rc.1_linux-arm64.tar.gz
uri: https://github.com/fatihtokus/scan2html/releases/download/v0.3.16-rc.1/scan2html_0.3.16-rc.1_linux-arm64.tar.gz
bin: ./scan2html
- selector:
os: linux
arch: s390x
uri: https://github.com/fatihtokus/scan2html/releases/download/v0.3.15-rc.1/scan2html_0.3.15-rc.1_linux-s390x.tar.gz
uri: https://github.com/fatihtokus/scan2html/releases/download/v0.3.16-rc.1/scan2html_0.3.16-rc.1_linux-s390x.tar.gz
bin: ./scan2html
- selector:
os: linux
arch: ppc64le
uri: https://github.com/fatihtokus/scan2html/releases/download/v0.3.15-rc.1/scan2html_0.3.15-rc.1_linux-ppc64le.tar.gz
uri: https://github.com/fatihtokus/scan2html/releases/download/v0.3.16-rc.1/scan2html_0.3.16-rc.1_linux-ppc64le.tar.gz
bin: ./scan2html
- selector:
os: linux
arch: 386
uri: https://github.com/fatihtokus/scan2html/releases/download/v0.3.15-rc.1/scan2html_0.3.15-rc.1_linux-386.tar.gz
uri: https://github.com/fatihtokus/scan2html/releases/download/v0.3.16-rc.1/scan2html_0.3.16-rc.1_linux-386.tar.gz
bin: ./scan2html

- selector:
os: darwin
arch: amd64
uri: https://github.com/fatihtokus/scan2html/releases/download/v0.3.15-rc.1/scan2html_0.3.15-rc.1_darwin-amd64.tar.gz
uri: https://github.com/fatihtokus/scan2html/releases/download/v0.3.16-rc.1/scan2html_0.3.16-rc.1_darwin-amd64.tar.gz
bin: ./scan2html
- selector:
os: darwin
arch: arm64
uri: https://github.com/fatihtokus/scan2html/releases/download/v0.3.15-rc.1/scan2html_0.3.15-rc.1_darwin-arm64.tar.gz
uri: https://github.com/fatihtokus/scan2html/releases/download/v0.3.16-rc.1/scan2html_0.3.16-rc.1_darwin-arm64.tar.gz
bin: ./scan2html

- selector:
os: freebsd
arch: 386
uri: https://github.com/fatihtokus/scan2html/releases/download/v0.3.15-rc.1/scan2html_0.3.15-rc.1_freebsd-386.tar.gz
uri: https://github.com/fatihtokus/scan2html/releases/download/v0.3.16-rc.1/scan2html_0.3.16-rc.1_freebsd-386.tar.gz
bin: ./scan2html
- selector:
os: freebsd
arch: amd64
uri: https://github.com/fatihtokus/scan2html/releases/download/v0.3.15-rc.1/scan2html_0.3.15-rc.1_freebsd-amd64.tar.gz
uri: https://github.com/fatihtokus/scan2html/releases/download/v0.3.16-rc.1/scan2html_0.3.16-rc.1_freebsd-amd64.tar.gz
bin: ./scan2html

- selector:
os: windows
arch: amd64
uri: https://github.com/fatihtokus/scan2html/releases/download/v0.3.15-rc.1/scan2html_0.3.15-rc.1_windows-amd64.zip
uri: https://github.com/fatihtokus/scan2html/releases/download/v0.3.16-rc.1/scan2html_0.3.16-rc.1_windows-amd64.zip
bin: ./scan2html
7 changes: 6 additions & 1 deletion src/frontend-app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,20 @@ import Papa, { ParseResult } from "papaparse";
import TrivyReport from "./components/trivy-report/TrivyReport";
import TableTitle from "./components/shared/TableTitle";
import defaultData from "./data/results.json";
import knownExploitedVulnerabilitiesData from "./data/cisa-known-exploited-vulnerabilities.json";
import defaultEPSSData from "./data/epss.cvs?raw";
import defaultResultMetaData from "./data/result-metadata.json";
import { NormalizedResultForDataTable, UploadInfo } from "./types";
import { EPSSPerVulnerability } from "./types/external/epss";
import { CisaExploit } from "./types/external/cisaExploit";
import { getSecrets, getLicenses, getMisconfigurationSummary, getK8sClusterSummaryForInfraAssessment, getK8sClusterSummaryForRBACAssessment, getMisconfigurations, getVulnerabilities, getSupplyChainSBOM } from "./utils/index";
import { FileProtectOutlined, UploadOutlined, LockOutlined, ExclamationCircleOutlined, SettingOutlined, ClusterOutlined, ProfileOutlined, MenuFoldOutlined, MenuUnfoldOutlined, BugOutlined } from "@ant-design/icons";
import "./App.css";
import type { MenuProps } from "antd";


const knownExploitedVulnerabilities: CisaExploit[] = knownExploitedVulnerabilitiesData as CisaExploit[];

type MenuItem = {
key: string;
icon: any;
Expand Down Expand Up @@ -112,7 +117,7 @@ function App() {

useEffect(() => {
console.log(`loadedData.length ${loadedData.length}`);
setVulnerabilities(getVulnerabilities(loadedData, epssData));
setVulnerabilities(getVulnerabilities(loadedData, epssData, knownExploitedVulnerabilities));
setSecrets(getSecrets(loadedData));
setLicenses(getLicenses(loadedData));
setMisconfigurations(getMisconfigurations(loadedData));
Expand Down
32 changes: 32 additions & 0 deletions src/frontend-app/src/components/shared/Exploit.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

import { Tag, Tooltip } from "antd";
import { SafetyCertificateOutlined, LinkOutlined } from "@ant-design/icons";

const Exploit = ({ vulnerabilityID }: { vulnerabilityID: string }) => {
return (
<div style={{ display: "flex", gap: "-2px" }}>
<Tooltip title="View details" placement="top">
<Tag
icon={<SafetyCertificateOutlined />}
style={{
display: "flex",
alignItems: "center",
borderRadius: "-2px",
cursor: "pointer",
fontSize: "10px",
backgroundColor: "#FFA500",
color: '#000', // Set text color to black
fontWeight: "bold", // Make text bold
}}

onClick={() => window.open("https://nvd.nist.gov/vuln/detail/" + vulnerabilityID, "_blank")}
>
CISA KEV
<LinkOutlined style={{ marginLeft: "0px" }} />
</Tag>
</Tooltip>
</div>
);
};

export default Exploit;
Loading

0 comments on commit 4de40c8

Please sign in to comment.