Skip to content
Closed
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
cd79351
feat(output): display base image info on HTML output
hogo6002 Jan 10, 2025
231b7cd
revert unwanted change
hogo6002 Jan 10, 2025
6765819
add code
hogo6002 Jan 14, 2025
4f58aa8
Merge remote-tracking branch 'rexpan/base-image-queries' into base-image
hogo6002 Jan 14, 2025
a4ecee7
update html
hogo6002 Jan 14, 2025
eaf9f02
update style to handle long layer command
hogo6002 Jan 14, 2025
719994a
fix alpine and ubuntu
hogo6002 Jan 14, 2025
23161ee
update do scan
hogo6002 Jan 14, 2025
8b95e64
Merge remote-tracking branch 'rexpan/base-image-queries' into base-image
hogo6002 Jan 14, 2025
7b965ab
add installed binaries
hogo6002 Jan 15, 2025
27a3bd3
add more filter
hogo6002 Jan 15, 2025
cc1154a
Merge branch 'base-image-queries' into base-image
hogo6002 Jan 15, 2025
8785416
cleanup code
hogo6002 Jan 15, 2025
dd88b7d
fix porject scanning
hogo6002 Jan 16, 2025
5a45ae6
resolve conflict
hogo6002 Jan 16, 2025
0aed890
Merge remote-tracking branch 'upstream/base-image-queries' into base-…
hogo6002 Jan 16, 2025
b8a4d9a
style improve
hogo6002 Jan 16, 2025
14b8d9b
Revert "Revert docker hash to build the older version of alpine images"
another-rex Jan 17, 2025
e437c7e
merge from base_image_queries and resolve conflicts
hogo6002 Jan 17, 2025
3290b26
Merge branch 'base-image-queries' of github.com:another-rex/osv-scann…
hogo6002 Jan 20, 2025
e02c5a3
Merge remote-tracking branch 'upstream/base-image-queries' into base-…
hogo6002 Jan 20, 2025
c160b6a
add bsae image info to table output
hogo6002 Jan 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions internal/output/html.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ func uniqueIndex(index *int) func() int {
}
}

func formatSlice(slice []string) string {
return strings.Join(slice, ", ")
}

func formatRating(rating severity.Rating) string {
return strings.ToLower(string(rating))
}
Expand All @@ -45,6 +49,9 @@ func PrintHTMLResults(vulnResult *models.VulnerabilityResults, outputWriter io.W
return a + b
},
"getFilteredVulnReasons": getFilteredVulnReasons,
"getBaseImageNames": getBaseImageNames,
"formatSlice": formatSlice,
"formatLayerCommand": formatLayerCommand,
}

tmpl := template.Must(template.New("").Funcs(funcMap).ParseFS(templates, TemplateDir))
Expand Down
75 changes: 75 additions & 0 deletions internal/output/html/base_image_template.gohtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@

<div id="base-image-section">
<table id="base-image-table">
<tr>
<th></th>
<th class="base-image-title">OS version:</th>
<th>{{ .ImageInfo.OS }}</th>
</tr>
{{ $totalVuln := .VulnTypeSummary.All }}
{{ range .ImageInfo.AllBaseImages}}

<tr {{ if gt (len .AllLayers) 0}}
id="base-image-summary-{{ .Index }}"
class="base-image-summary"
onclick="showBaseImageLayer('{{ .Index }}')"
{{ end }}>
<td class="icon-td">
{{ if gt (len .AllLayers) 0}}
<div class="expand-icon">
<i class="material-icons">play_arrow</i>
</div>
{{ end }}
</td>
<td class="base-image-title">
{{ if eq .Index 0}}
Your image:
{{ else }}
Base image {{ .Index }}:
{{ end }}
</td>
<td>
{{ getBaseImageNames . }}<span class="base-image-title"> ({{ .Count.AnalysisCount.Regular }}/{{ $totalVuln }} vulnerabilities)</span>
</td>
</tr>

<tr>
<td></td>
<td colspan="100%">
<div id="base-image-details-{{ .Index }}" class="base-image-details">
{{ range .AllLayers }}
{{ $index := .Index }}
{{ $originalCommand := .LayerMetadata.Command }}
{{ $commandSet := formatLayerCommand $originalCommand }}
{{ $command := index $commandSet 0 }}
{{ $commandDetail := index $commandSet 1 }}
{{ $diffID := .LayerMetadata.DiffID }}
{{ $longCommand := false }}
{{ if gt (len $command) 109 }}
{{ $longCommand = true }}
{{ end }}
{{ $hasVuln := false }}
{{ if gt .Count.AnalysisCount.Regular 0 }}
{{ $hasVuln = true }}
{{ end }}
<div title="{{ $diffID }}" class="layer-entry {{ if $hasVuln }}clickable clickable-layer{{ end }}" {{ if $hasVuln }}onclick="quickFilterByLayer('{{ $diffID }}', {{ $command }})"{{ end }}>
<div {{ if $longCommand }} class="tooltip" {{ end }}>
<p class="layer-command"><span class="base-image-title">{{ .Index }}</span> {{ $command }}</p>
{{ if $longCommand }}
<span class="tooltiptext layer-tooltiptext">{{ $originalCommand }}</span>
{{ end }}
</div>
{{ if $hasVuln }}
{{ template "severity_summary_template.gohtml".Count.SeverityCount }}
{{ end }}
</div>
{{ end }}
</div>
</td>
</tr>

{{ end }}

</table>

</div>
24 changes: 21 additions & 3 deletions internal/output/html/filter_template.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,30 @@
<p>All layers ({{ .VulnCount.AnalysisCount.Regular }})</p>
{{ template "severity_summary_template.gohtml" .VulnCount.SeverityCount }}
</div>
{{ range .AllLayers }}
<div title="{{ .LayerID}}" class="filter-option layer-filter-option">
<p>{{ .Index }} {{ .LayerCommand }}</p>
{{ range .ImageInfo.AllLayers }}
{{ $index := .Index }}
{{ $originalCommand := .LayerMetadata.Command }}
{{ $commandSet := formatLayerCommand $originalCommand }}
{{ $command := index $commandSet 0 }}
{{ $commandDetail := index $commandSet 1 }}
{{ $diffID := .LayerMetadata.DiffID }}
{{ $longCommand := false }}
{{ if gt (len $command) 109 }}
{{ $longCommand = true }}
{{ end }}

{{ if gt .Count.AnalysisCount.Regular 0 }}
<div title="{{ $diffID }}" class="filter-option layer-filter-option">
<div {{ if $longCommand }} class="tooltip" {{ end }}>
<p class="layer-command">{{ $index }} {{ $command }}</p>
{{ if $longCommand }}
<span class="tooltiptext layer-tooltiptext">{{ $originalCommand }}</span>
{{ end }}
</div>
{{ template "severity_summary_template.gohtml".Count.SeverityCount }}
</div>
{{ end }}
{{ end }}
</div>
</div>
{{ end }}
Expand Down
47 changes: 38 additions & 9 deletions internal/output/html/package_table_template.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
{{ range $rowIndex, $element := . }}
{{ $index := uniqueID }}
<tr class="table-tr package-tr {{if $element.LayerDetail }}has-layer-info"
data-layer="{{ $element.LayerDetail.LayerID }}{{ end }}" id="table-tr-{{ $index }}" onclick="showPackageDetails('{{ $index }}')">
data-layer="{{ $element.LayerDetail.LayerInfo.LayerMetadata.DiffID }}{{ end }}" id="table-tr-{{ $index }}" onclick="showPackageDetails('{{ $index }}')">
<td class="icon-td">
<div class="expand-icon">
<i class="material-icons">play_arrow</i>
Expand Down Expand Up @@ -55,19 +55,48 @@
<tr>
<td colspan="100%">
<div id="table-tr-{{ $index }}-details" class="package-details">
{{ if and $element.LayerDetail (not (eq $element.LayerDetail.LayerID "")) }}
{{ if and $element.LayerDetail.LayerInfo.LayerMetadata (not (eq $element.LayerDetail.LayerInfo.LayerMetadata.Command "")) }}
{{ $index := $element.LayerDetail.LayerIndex }}
{{ $diffID := $element.LayerDetail.LayerInfo.LayerMetadata.DiffID }}
{{ $baseImageIndex := $element.LayerDetail.LayerInfo.LayerMetadata.BaseImageIndex }}
{{ $originalCommand := $element.LayerDetail.LayerInfo.LayerMetadata.Command }}
{{ $commandSet := formatLayerCommand $originalCommand }}
{{ $command := index $commandSet 0 }}
{{ $commandDetail := index $commandSet 1 }}
{{ $longCommand := false }}
{{ if gt (len $command) 109 }}
{{ $longCommand = true }}
{{ end }}
{{ $binaries := formatSlice $element.OSPackageNames }}
{{ if not (eq $binaries "") }}
<p><span class="package-detail-title">Installed binaries:</span> {{ $binaries }}</p>
{{ end }}
<div class="layer-command-container">
<p><span class="package-detail-title">Layer introduced in:&nbsp;</span></p>
<div class="tooltip">
<p># {{ $index }} layer</p>
<span class="tooltiptext">Diff ID: {{ $diffID }}</span>
</div>
</div>
<div class="layer-command-container">
<span class="package-detail-title">Layer introduced in:</span>
{{ if ne $element.LayerDetail.LayerCommandDetailed "" }}
<div class="tooltip">{{ $element.LayerDetail.LayerCommand }}
<span class="tooltiptext">{{ $element.LayerDetail.LayerCommandDetailed }}</span>
{{ if $longCommand }}
<p class="package-detail-title">Layer command:&nbsp;</p>
<div class="tooltip">
<p class="layer-command">{{ $command }}</p>
<span class="tooltiptext layer-tooltiptext">{{ $originalCommand }}</span>
</div>
{{ else if ne $commandDetail "" }}
<p class="package-detail-title">Layer command:&nbsp;</p>
<div class="tooltip">
<p class="layer-command">{{ $command }}</p>
<span class="tooltiptext">{{ $commandDetail }}</span>
</div>
{{ else }}
<div>{{ $element.LayerDetail.LayerCommand }}</div>
<p class="package-detail-title">Layer command:&nbsp;</p>
<p class="layer-command">{{ $command }}</p>
{{ end }}
</div>
<p><span class="package-detail-title">Layer ID:</span> {{ $element.LayerDetail.LayerID }}</p>
<p><span class="package-detail-title">In base image:</span> {{ $element.LayerDetail.InBaseImage }}</p>
<p><span class="package-detail-title">In base image:</span> {{ if eq $baseImageIndex 0 }} False {{ else }} True: {{ getBaseImageNames $element.LayerDetail.BaseImageInfo }}{{ end }}</p>
{{ end }}
{{ template "vuln_table_template.gohtml" $element }}
</div>
Expand Down
4 changes: 4 additions & 0 deletions internal/output/html/report_template.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
<div id="summary-tab" class="tab">
{{ template "filter_template.gohtml" .}}

{{ if .IsContainerScanning }}
{{ template "base_image_template.gohtml" .}}
{{end}}

<div class="search-box">
<div class="search-icon">
<i class="material-icons">search</i>
Expand Down
38 changes: 35 additions & 3 deletions internal/output/html/script.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,34 @@
<script>

let selectedTypeFilterValue = new Set();
selectedTypeFilterValue.add("all");
let selectedLayer = "all";

function quickFilterByLayer(DiffID, layerCommand) {
resetFilterText();
applyFilters(selectedTypeFilterValue, DiffID)
selectedDisplay = document.getElementById("layer-filter-selected");
selectedDisplay.textContent = layerCommand;
}

function showBaseImageLayer(imageID) {
var detailElementID = "base-image-details-" + imageID
var detailsElement = document.getElementById(detailElementID);

const icon = document.querySelector(
`#base-image-summary-${imageID} .material-icons`
); // Select the icon within the row
if (detailsElement.style.display !== "block") {
detailsElement.style.display = "block";
icon.style.transform = "rotate(90deg)"; // Rotate 90 degrees
icon.style.transition = "transform 0.2s ease"; // Add smooth transition
} else {
detailsElement.style.display = "none";
icon.style.transform = "rotate(0deg)"; // Rotate back to 0 degrees
icon.style.transition = "transform 0.2s ease"; // Add smooth transition
}
}

function showPackageDetails(detailsId) {
var detailsElement = document.getElementById(
"table-tr-" + detailsId + "-details"
Expand Down Expand Up @@ -318,6 +348,10 @@
selectedCount += parseInt(uncalledTypeVulnCount, 10);
}

if (allTypeCheckbox && allTypeCheckbox.checked && (uncalledTypeCheckbox && !uncalledTypeCheckbox.checked)) {
selectedText = "Default"
}

typeSelected.textContent = selectedText;
selectedVulnCount.textContent = selectedCount;
}
Expand Down Expand Up @@ -389,9 +423,7 @@
document.addEventListener("DOMContentLoaded", function () {
resetFilterText();
showAndHideParentSections();
let selectedTypeFilterValue = new Set();
selectedTypeFilterValue.add("all");
let selectedLayer = "all";


// Implement filter for vulnerability types
const typeFilterOptions = document.getElementById(
Expand Down
Loading