mirror of
https://github.com/rancher-sandbox/rancher-desktop.git
synced 2021-10-13 00:04:06 +03:00
Add a command to use trivy to scan images for vulnerabilities
* Install trivy in download-resources
* On Windows, we run trivy via wsl because there's no windows port
* But... to speed things up, we want wsl commands to hit the linux mount, not the windows mount
- So we move the files from the windows mount to the linux once we know the
rancher-desktop subsystem is available.
- And to simplify this work, provide a resources function `wslify` to convert full windows
paths into wsl paths in the windows mount.
Signed-off-by: Eric Promislow <epromislow@suse.com>
This commit is contained in:
21
resources/templates/trivy.tpl
Normal file
21
resources/templates/trivy.tpl
Normal file
@@ -0,0 +1,21 @@
|
||||
[
|
||||
{{ $firstVulSet := true }}{{ range . }}{{ if $firstVulSet}} {{ $firstVulSet = false}} {{ else }}, {{end}}
|
||||
{
|
||||
"Target": "{{.Target}}",
|
||||
"Vulnerabilities": [
|
||||
{{ $firstVul := true }}{{ range .Vulnerabilities }}{{ if $firstVul}} {{ $firstVul = false}} {{ else }}, {{end}}{
|
||||
"Package": "{{.PkgName | js}}",
|
||||
"Severity": "{{.Severity | js}}",
|
||||
"Title": "{{.Title | js}}",
|
||||
"VulnerabilityID": "{{.VulnerabilityID | js}}",
|
||||
"InstalledVersion": "{{.InstalledVersion | js}}",
|
||||
"FixedVersion": "{{.FixedVersion | js}}",
|
||||
"PrimaryURL": "{{.PrimaryURL | js}}",
|
||||
"Description": "{{.Description | js}}"
|
||||
}
|
||||
{{ end }}
|
||||
]
|
||||
}
|
||||
{{ end }}
|
||||
]
|
||||
|
||||
@@ -39,6 +39,12 @@ if ($Step -eq "InstallLinuxUpdatePackage-03") {
|
||||
Invoke-WebRequest -Uri https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi -OutFile $wslMsiFile
|
||||
msiexec /norestart /i$wslMsiFile /passive
|
||||
wsl --set-default-version 2
|
||||
|
||||
Write-Information 'about to install trivy after installing wsl'
|
||||
$thisScript = $myInvocation.MyCommand.Definition
|
||||
$thisDir = Split-Path -parent $thisScript
|
||||
. (Join-Path $thisDir "install-trivy-in-wsl.ps1")
|
||||
|
||||
Write-Host -NoNewLine 'WSL is now installed - press any key to continue'
|
||||
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown');
|
||||
}
|
||||
|
||||
@@ -20,16 +20,6 @@
|
||||
@input="handleShowAllCheckbox"
|
||||
/>
|
||||
</template>
|
||||
<template #row-actions="{ row }">
|
||||
<!-- We want to use the defalut rowActions from the SortableTable;
|
||||
- so just replace it with a dummy if we _don't_ want it on this row
|
||||
-->
|
||||
<i
|
||||
v-if="!hasDropdownActions(row)"
|
||||
disabled
|
||||
class="btn btn-sm icon icon-actions actions role-multi-action role-link select-all-check"
|
||||
/>
|
||||
</template>
|
||||
</SortableTable>
|
||||
|
||||
<Card :show-highlight-border="false" :show-actions="false">
|
||||
@@ -139,7 +129,7 @@ export default {
|
||||
|
||||
data() {
|
||||
return {
|
||||
kimRunningCommand: null,
|
||||
currentCommand: null,
|
||||
headers: [
|
||||
{
|
||||
name: 'imageName',
|
||||
@@ -198,6 +188,12 @@ export default {
|
||||
enabled: this.isDeletable(image),
|
||||
icon: 'icon icon-delete',
|
||||
},
|
||||
{
|
||||
label: 'Scan...',
|
||||
action: 'scanImage',
|
||||
enabled: true,
|
||||
icon: 'icon icon-info',
|
||||
},
|
||||
].filter(x => x.enabled);
|
||||
}
|
||||
// ActionMenu callbacks - SortableTable assumes that these methods live
|
||||
@@ -208,15 +204,18 @@ export default {
|
||||
if (!image.deleteImage) {
|
||||
image.deleteImage = this.deleteImage.bind(this, image);
|
||||
}
|
||||
if (!image.scanImage) {
|
||||
image.scanImage = this.scanImage.bind(this, image);
|
||||
}
|
||||
}
|
||||
|
||||
return this.filteredImages;
|
||||
},
|
||||
showImageManagerOutput() {
|
||||
return !!this.kimRunningCommand || this.keepImageManagerOutputWindowOpen;
|
||||
return !!this.currentCommand || this.keepImageManagerOutputWindowOpen;
|
||||
},
|
||||
imageManagerProcessIsFinished() {
|
||||
return !this.kimRunningCommand;
|
||||
return !this.currentCommand;
|
||||
},
|
||||
imageToBuildButtonDisabled() {
|
||||
return this.showImageManagerOutput || !this.imageToBuild.includes(':');
|
||||
@@ -256,6 +255,11 @@ export default {
|
||||
value: row,
|
||||
});
|
||||
}
|
||||
items.push({
|
||||
label: `Scan...`,
|
||||
action: this.scanImage,
|
||||
value: row,
|
||||
});
|
||||
|
||||
return items;
|
||||
},
|
||||
@@ -283,27 +287,34 @@ export default {
|
||||
}
|
||||
},
|
||||
deleteImage(obj) {
|
||||
this.kimRunningCommand = `delete ${ obj.imageName }:${ obj.tag }`;
|
||||
this.currentCommand = `delete ${ obj.imageName }:${ obj.tag }`;
|
||||
this.startRunningCommand('delete');
|
||||
ipcRenderer.send('confirm-do-image-deletion', obj.imageName.trim(), obj.imageID.trim());
|
||||
},
|
||||
doPush(obj) {
|
||||
this.kimRunningCommand = `push ${ obj.imageName }:${ obj.tag }`;
|
||||
this.currentCommand = `push ${ obj.imageName }:${ obj.tag }`;
|
||||
this.startRunningCommand('push');
|
||||
ipcRenderer.send('do-image-push', obj.imageName.trim(), obj.imageID.trim(), obj.tag.trim());
|
||||
},
|
||||
doBuildAnImage() {
|
||||
this.kimRunningCommand = `build ${ this.imageToBuild }`;
|
||||
this.currentCommand = `build ${ this.imageToBuild }`;
|
||||
this.fieldToClear = 'imageToBuild';
|
||||
this.startRunningCommand('build');
|
||||
ipcRenderer.send('do-image-build', this.imageToBuild.trim());
|
||||
},
|
||||
doPullAnImage() {
|
||||
this.kimRunningCommand = `pull ${ this.imageToPull }`;
|
||||
this.currentCommand = `pull ${ this.imageToPull }`;
|
||||
this.fieldToClear = 'imageToPull';
|
||||
this.startRunningCommand('pull');
|
||||
ipcRenderer.send('do-image-pull', this.imageToPull.trim());
|
||||
},
|
||||
scanImage(obj) {
|
||||
const taggedImageName = `${ obj.imageName.trim() }:${ obj.tag.trim() }`;
|
||||
|
||||
this.currentCommand = `scan image ${ taggedImageName }`;
|
||||
this.startRunningCommand('trivy-image');
|
||||
ipcRenderer.send('do-image-scan', taggedImageName);
|
||||
},
|
||||
handleProcessCancelled() {
|
||||
this.closeOutputWindow(null);
|
||||
},
|
||||
@@ -316,10 +327,10 @@ export default {
|
||||
// Don't know what would make this null, but it happens on windows sometimes
|
||||
this.imageManagerOutput = this.imageOutputCuller.getProcessedData();
|
||||
}
|
||||
if (this.kimRunningCommand?.startsWith('delete') && this.imageManagerOutput === '') {
|
||||
if (this.currentCommand?.startsWith('delete') && this.imageManagerOutput === '') {
|
||||
this.closeOutputWindow(null);
|
||||
}
|
||||
this.kimRunningCommand = null;
|
||||
this.currentCommand = null;
|
||||
},
|
||||
isDeletable(row) {
|
||||
return row.imageName !== 'moby/buildkit' && !row.imageName.startsWith('rancher/');
|
||||
|
||||
@@ -3,6 +3,7 @@ import { spawn } from 'child_process';
|
||||
import { Console } from 'console';
|
||||
import { EventEmitter } from 'events';
|
||||
import net from 'net';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import timers from 'timers';
|
||||
import tls from 'tls';
|
||||
@@ -125,8 +126,25 @@ class Kim extends EventEmitter {
|
||||
return this._isReady;
|
||||
}
|
||||
|
||||
async runCommand(args: string[], sendNotifications = true): Promise<childResultType> {
|
||||
const child = spawn(resources.executable('kim'), args);
|
||||
async runKimCommand(args: string[], sendNotifications = true): Promise<childResultType> {
|
||||
return await this.runCommand(resources.executable('kim'), args, sendNotifications);
|
||||
}
|
||||
|
||||
async runTrivyCommand(args: string[], sendNotifications = true): Promise<childResultType> {
|
||||
let command;
|
||||
|
||||
if (os.platform().startsWith('win')) {
|
||||
command = 'wsl';
|
||||
args = ['-d', 'rancher-desktop', 'trivy'].concat(args);
|
||||
} else {
|
||||
command = resources.executable('trivy');
|
||||
}
|
||||
|
||||
return await this.runCommand(command, args, sendNotifications);
|
||||
}
|
||||
|
||||
async runCommand(command: string, args: string[], sendNotifications: boolean): Promise<childResultType> {
|
||||
const child = spawn(command, args);
|
||||
const result = { stdout: '', stderr: '' };
|
||||
|
||||
return await new Promise((resolve, reject) => {
|
||||
@@ -368,23 +386,30 @@ class Kim extends EventEmitter {
|
||||
args.push(taggedImageName);
|
||||
args.push(dirPart);
|
||||
|
||||
return await this.runCommand(args);
|
||||
return await this.runKimCommand(args);
|
||||
}
|
||||
|
||||
async deleteImage(imageID: string): Promise<childResultType> {
|
||||
return await this.runCommand(['rmi', imageID]);
|
||||
return await this.runKimCommand(['rmi', imageID]);
|
||||
}
|
||||
|
||||
async pullImage(taggedImageName: string): Promise<childResultType> {
|
||||
return await this.runCommand(['pull', taggedImageName, '--debug']);
|
||||
return await this.runKimCommand(['pull', taggedImageName, '--debug']);
|
||||
}
|
||||
|
||||
async pushImage(taggedImageName: string): Promise<childResultType> {
|
||||
return await this.runCommand(['push', taggedImageName, '--debug']);
|
||||
return await this.runKimCommand(['push', taggedImageName, '--debug']);
|
||||
}
|
||||
|
||||
async getImages(): Promise<childResultType> {
|
||||
return await this.runCommand(['images', '--all'], false);
|
||||
return await this.runKimCommand(['images', '--all'], false);
|
||||
}
|
||||
|
||||
async scanImage(taggedImageName: string): Promise<childResultType> {
|
||||
const templatePath = os.platform().startsWith('win') ? '/var/lib/trivy.tpl' : resources.get('templates', 'trivy.tpl');
|
||||
|
||||
return await this.runTrivyCommand(['image', '--no-progress', '--format', 'template',
|
||||
'--template', `@${ templatePath }`, taggedImageName]);
|
||||
}
|
||||
|
||||
parse(data: string): imageType[] {
|
||||
|
||||
@@ -244,6 +244,36 @@ export default class WSLBackend extends events.EventEmitter implements K8s.Kuber
|
||||
}
|
||||
}
|
||||
|
||||
protected async installTrivy() {
|
||||
// download-resources.sh installed trivy into the ubuntu wsl windows mount area
|
||||
// This function moves it and the trivy.tpl into /usr/local/bin/ and /var/lib/
|
||||
// respectively so when trivy is invoked to run through wsl, it runs faster.
|
||||
|
||||
console.log('Installing trivy into /usr/local/bin/...');
|
||||
// No bash on the rd wsl either
|
||||
let trivyMvArgs = ['-d', 'rancher-desktop', 'sh', '-c',
|
||||
'if [ ! -f /usr/local/bin/trivy ] ; then mv work/trivy /usr/local/bin/ && rmdir work ; fi'];
|
||||
const { stdout } = await childProcess.spawnFile('wsl.exe', trivyMvArgs, {
|
||||
stdio: ['ignore', 'pipe', await Logging.wsl.fdStream],
|
||||
windowsHide: true
|
||||
});
|
||||
|
||||
console.log(stdout);
|
||||
console.log('Installing trivy.tpl into /var/lib/...');
|
||||
|
||||
// And put the trivy image template on the wsl partition
|
||||
const trivyPath = resources.wslify(resources.get('templates', 'trivy.tpl'));
|
||||
|
||||
trivyMvArgs = ['-d', 'rancher-desktop', 'sh', '-c',
|
||||
`if [ ! -f /var/lib/trivy.tpl ] ; then mv "${ trivyPath }" /var/lib/ ; fi`];
|
||||
const moveOutput = await childProcess.spawnFile('wsl.exe', trivyMvArgs, {
|
||||
stdio: ['ignore', 'pipe', await Logging.wsl.fdStream],
|
||||
windowsHide: true
|
||||
});
|
||||
|
||||
console.log(moveOutput.stdout);
|
||||
}
|
||||
|
||||
/**
|
||||
* execCommand runs the given command in the K3s WSL environment and returns
|
||||
* the standard output.
|
||||
@@ -343,6 +373,7 @@ export default class WSLBackend extends events.EventEmitter implements K8s.Kuber
|
||||
|
||||
await Promise.all([
|
||||
this.ensureDistroRegistered(),
|
||||
this.installTrivy(),
|
||||
this.k3sHelper.ensureK3sImages(desiredVersion),
|
||||
]);
|
||||
// We have no good estimate for the rest of the steps, go indeterminate.
|
||||
|
||||
@@ -147,6 +147,26 @@ export function setupKim() {
|
||||
event.reply('kim-process-ended', code);
|
||||
});
|
||||
|
||||
Electron.ipcMain.on('do-image-scan', async(event, imageName) => {
|
||||
let taggedImageName = imageName;
|
||||
let code;
|
||||
|
||||
if (!imageName.includes(':')) {
|
||||
taggedImageName += ':latest';
|
||||
}
|
||||
try {
|
||||
code = (await imageManager.scanImage(taggedImageName)).code;
|
||||
await imageManager.refreshImages();
|
||||
} catch (err) {
|
||||
code = err.code;
|
||||
Electron.dialog.showMessageBox({
|
||||
message: `Error trying to scan ${ taggedImageName }:\n\n ${ err.stderr } `,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
event.reply('kim-process-ended', code);
|
||||
});
|
||||
|
||||
Electron.ipcMain.on('do-image-push', async(event, imageName, imageID, tag) => {
|
||||
const taggedImageName = `${ imageName }:${ tag }`;
|
||||
let code;
|
||||
|
||||
@@ -8,6 +8,7 @@ const adjustNameWithDir = {
|
||||
helm: path.join('bin', 'helm'),
|
||||
kim: path.join('bin', 'kim'),
|
||||
kubectl: path.join('bin', 'kubectl'),
|
||||
trivy: path.join('bin', 'trivy'),
|
||||
};
|
||||
|
||||
function fixedSourceName(name) {
|
||||
@@ -37,4 +38,17 @@ function _executable(name) {
|
||||
}
|
||||
const executable = memoize(_executable);
|
||||
|
||||
module.exports = { get, executable };
|
||||
function _wslify(path) {
|
||||
const m = /^(\w):(.+)$/.exec(path);
|
||||
|
||||
if (!m) {
|
||||
return path;
|
||||
}
|
||||
|
||||
return `/mnt/${ m[1].toLowerCase() }${ m[2].replace(/\\/g, '/') }`;
|
||||
}
|
||||
const wslify = memoize(_wslify);
|
||||
|
||||
module.exports = {
|
||||
get, executable, wslify
|
||||
};
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
import KimNonBuildOutputCuller from '~/utils/processOutputInterpreters/kim-non-build-output';
|
||||
import KimBuildOutputCuller from '~/utils/processOutputInterpreters/kim-build-output';
|
||||
import TrivyScanImageOutputCuller from '~/utils/processOutputInterpreters/trivy-image-output';
|
||||
|
||||
const cullersByName = {
|
||||
build: KimBuildOutputCuller,
|
||||
'trivy-image': TrivyScanImageOutputCuller
|
||||
};
|
||||
|
||||
export default function getImageOutputCuller(command) {
|
||||
const klass = command === 'build' ? KimBuildOutputCuller : KimNonBuildOutputCuller;
|
||||
const klass = cullersByName[command] || KimNonBuildOutputCuller;
|
||||
|
||||
return new klass();
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
,ericp,chirico.local,09.07.2021 16:14,file:///Users/ericp/Library/Application%20Support/OpenOffice/4;
|
||||
@@ -0,0 +1,8 @@
|
||||
2021-07-09T15:58:24.556-0700 [34mINFO[0m Detected OS: debian
|
||||
2021-07-09T15:58:24.557-0700 [34mINFO[0m Detecting Debian vulnerabilities...
|
||||
2021-07-09T15:58:24.559-0700 [34mINFO[0m Number of PL dependency files: 0
|
||||
|
||||
rancher/metrics-server:v0.3.6 (debian 9.9)
|
||||
==========================================
|
||||
Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
INFO Detected OS: debian
|
||||
INFO Detecting Debian vulnerabilities...
|
||||
INFO Number of PL dependency files: 0
|
||||
|
||||
rancher/metrics-server:v0.3.6 (debian 9.9)
|
||||
==========================================
|
||||
Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0)
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
2021-07-13T13:49:11.694-0700 [34mINFO[0m Detected OS: debian
|
||||
2021-07-13T13:49:11.694-0700 [34mINFO[0m Detecting Debian vulnerabilities...
|
||||
2021-07-13T13:49:11.705-0700 [34mINFO[0m Number of PL dependency files: 0
|
||||
[
|
||||
{
|
||||
|
||||
|
||||
|
||||
"Target": "postgres (debian 10.10)",
|
||||
"Vulnerabilities": [
|
||||
|
||||
|
||||
|
||||
{
|
||||
"Package": "apt",
|
||||
"Severity": "LOW",
|
||||
"Title": "",
|
||||
"VulnerabilityID": "CVE-2011-3374",
|
||||
"InstalledVersion": "1.8.2.3",
|
||||
"FixedVersion": "",
|
||||
"PrimaryURL": "https://avd.aquasec.com/nvd/cve-2011-3374",
|
||||
"Description": "It was found that apt-key in apt, all versions, do not correctly validate gpg keys with the master keyring, leading to a potential man-in-the-middle attack."
|
||||
}
|
||||
|
||||
,
|
||||
{
|
||||
"Package": "bash",
|
||||
"Severity": "LOW",
|
||||
"Title": "bash: when effective UID is not equal to its real UID the saved UID is not dropped",
|
||||
"VulnerabilityID": "CVE-2019-18276",
|
||||
"InstalledVersion": "5.0-4",
|
||||
"FixedVersion": "5.0-5",
|
||||
"PrimaryURL": "https://avd.aquasec.com/nvd/cve-2019-18276",
|
||||
"Description": "An issue was discovered in disable_priv_mode in shell.c in GNU Bash through 5.0 patch 11. By default, if Bash is run with its effective UID not equal to its real UID, it will drop privileges by setting its effective UID to its real UID. However, it does so incorrectly. On Linux and other systems that support \"saved UID\" functionality, the saved UID is not dropped. An attacker with command execution in the shell can use \"enable -f\" for runtime loading of a new builtin, which can be a shared object that calls setuid() and therefore regains privileges. However, binaries running with an effective UID of 0 are unaffected."
|
||||
}
|
||||
|
||||
,
|
||||
{
|
||||
"Package": "bash",
|
||||
"Severity": "LOW",
|
||||
"Title": "",
|
||||
"VulnerabilityID": "TEMP-0841856-B18BAF",
|
||||
"InstalledVersion": "5.0-4",
|
||||
"FixedVersion": "",
|
||||
"PrimaryURL": "https://security-tracker.debian.org/tracker/TEMP-0841856-B18BAF",
|
||||
"Description": ""
|
||||
}
|
||||
|
||||
|
||||
,
|
||||
{
|
||||
"Package": "libc-bin",
|
||||
"Severity": "CRITICAL",
|
||||
"Title": "glibc: mq_notify does not handle separately allocated thread attributes",
|
||||
"VulnerabilityID": "CVE-2021-33574",
|
||||
"InstalledVersion": "2.28-10",
|
||||
"FixedVersion": "",
|
||||
"PrimaryURL": "https://avd.aquasec.com/nvd/cve-2021-33574",
|
||||
"Description": "The mq_notify function in the GNU C Library (aka glibc) versions 2.32 and 2.33 has a use-after-free. It may use the notification thread attributes object (passed through its struct sigevent parameter) after it has been freed by the caller, leading to a denial of service (application crash) or possibly unspecified other impact."
|
||||
}
|
||||
|
||||
,
|
||||
{
|
||||
"Package": "libc-bin",
|
||||
"Severity": "HIGH",
|
||||
"Title": "glibc: array overflow in backtrace functions for powerpc",
|
||||
"VulnerabilityID": "CVE-2020-1751",
|
||||
"InstalledVersion": "2.28-10",
|
||||
"FixedVersion": "",
|
||||
"PrimaryURL": "https://avd.aquasec.com/nvd/cve-2020-1751",
|
||||
"Description": "An out-of-bounds write vulnerability was found in glibc before 2.31 when handling signal trampolines on PowerPC. Specifically, the backtrace function did not properly check the array bounds when storing the frame address, resulting in a denial of service or potential code execution. The highest threat from this vulnerability is to system availability."
|
||||
}
|
||||
|
||||
,
|
||||
{
|
||||
"Package": "libc-bin",
|
||||
"Severity": "HIGH",
|
||||
"Title": "glibc: use-after-free in glob() function when expanding ~user",
|
||||
"VulnerabilityID": "CVE-2020-1752",
|
||||
"InstalledVersion": "2.28-10",
|
||||
"FixedVersion": "",
|
||||
"PrimaryURL": "https://avd.aquasec.com/nvd/cve-2020-1752",
|
||||
"Description": "A use-after-free vulnerability introduced in glibc upstream version 2.14 was found in the way the tilde expansion was carried out. Directory paths containing an initial tilde followed by a valid username were affected by this issue. A local attacker could exploit this flaw by creating a specially crafted path that, when processed by the glob function, would potentially lead to arbitrary code execution. This was fixed in version 2.32."
|
||||
}
|
||||
|
||||
|
||||
,
|
||||
{
|
||||
"Package": "libc-bin",
|
||||
"Severity": "MEDIUM",
|
||||
"Title": "glibc: buffer over-read in iconv when processing invalid multi-byte input sequences in the EUC-KR encoding",
|
||||
"VulnerabilityID": "CVE-2019-25013",
|
||||
"InstalledVersion": "2.28-10",
|
||||
"FixedVersion": "",
|
||||
"PrimaryURL": "https://avd.aquasec.com/nvd/cve-2019-25013",
|
||||
"Description": "The iconv feature in the GNU C Library (aka glibc or libc6) through 2.32, when processing invalid multi-byte input sequences in the EUC-KR encoding, may have a buffer over-read."
|
||||
}
|
||||
|
||||
,
|
||||
{
|
||||
"Package": "libc-bin",
|
||||
"Severity": "MEDIUM",
|
||||
"Title": "glibc: stack corruption from crafted input in cosl, sinl, sincosl, and tanl functions",
|
||||
"VulnerabilityID": "CVE-2020-10029",
|
||||
"InstalledVersion": "2.28-10",
|
||||
"FixedVersion": "",
|
||||
"PrimaryURL": "https://avd.aquasec.com/nvd/cve-2020-10029",
|
||||
"Description": "The GNU C Library (aka glibc or libc6) before 2.32 could overflow an on-stack buffer during range reduction if an input to an 80-bit long double function contains a non-canonical bit pattern, a seen when passing a 0x5d414141414141410000 value to sinl on x86 targets. This is related to sysdeps/ieee754/ldbl-96/e_rem_pio2l.c."
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,66 @@
|
||||
INFO Detected OS: debian
|
||||
INFO Detecting Debian vulnerabilities...
|
||||
INFO Number of PL dependency files: 0
|
||||
Target: postgres (debian 10.10)
|
||||
|
||||
Package: libc-bin
|
||||
VulnerabilityID: CVE-2021-33574
|
||||
Severity: CRITICAL
|
||||
Title: glibc: mq_notify does not handle separately allocated thread attributes
|
||||
InstalledVersion: 2.28-10
|
||||
Description: The mq_notify function in the GNU C Library (aka glibc) versions 2.32 and 2.33 has a use-after-free. It may use the notification thread attributes object (passed through its struct sigevent parameter) after it has been freed by the caller, leading to a denial of service (application crash) or possibly unspecified other impact.
|
||||
PrimaryURL: https://avd.aquasec.com/nvd/cve-2021-33574
|
||||
|
||||
Package: libc-bin
|
||||
VulnerabilityID: CVE-2020-1751
|
||||
Severity: HIGH
|
||||
Title: glibc: array overflow in backtrace functions for powerpc
|
||||
InstalledVersion: 2.28-10
|
||||
Description: An out-of-bounds write vulnerability was found in glibc before 2.31 when handling signal trampolines on PowerPC. Specifically, the backtrace function did not properly check the array bounds when storing the frame address, resulting in a denial of service or potential code execution. The highest threat from this vulnerability is to system availability.
|
||||
PrimaryURL: https://avd.aquasec.com/nvd/cve-2020-1751
|
||||
|
||||
Package: libc-bin
|
||||
VulnerabilityID: CVE-2020-1752
|
||||
Severity: HIGH
|
||||
Title: glibc: use-after-free in glob() function when expanding ~user
|
||||
InstalledVersion: 2.28-10
|
||||
Description: A use-after-free vulnerability introduced in glibc upstream version 2.14 was found in the way the tilde expansion was carried out. Directory paths containing an initial tilde followed by a valid username were affected by this issue. A local attacker could exploit this flaw by creating a specially crafted path that, when processed by the glob function, would potentially lead to arbitrary code execution. This was fixed in version 2.32.
|
||||
PrimaryURL: https://avd.aquasec.com/nvd/cve-2020-1752
|
||||
|
||||
Package: libc-bin
|
||||
VulnerabilityID: CVE-2019-25013
|
||||
Severity: MEDIUM
|
||||
Title: glibc: buffer over-read in iconv when processing invalid multi-byte input sequences in the EUC-KR encoding
|
||||
InstalledVersion: 2.28-10
|
||||
Description: The iconv feature in the GNU C Library (aka glibc or libc6) through 2.32, when processing invalid multi-byte input sequences in the EUC-KR encoding, may have a buffer over-read.
|
||||
PrimaryURL: https://avd.aquasec.com/nvd/cve-2019-25013
|
||||
|
||||
Package: libc-bin
|
||||
VulnerabilityID: CVE-2020-10029
|
||||
Severity: MEDIUM
|
||||
Title: glibc: stack corruption from crafted input in cosl, sinl, sincosl, and tanl functions
|
||||
InstalledVersion: 2.28-10
|
||||
Description: The GNU C Library (aka glibc or libc6) before 2.32 could overflow an on-stack buffer during range reduction if an input to an 80-bit long double function contains a non-canonical bit pattern, a seen when passing a 0x5d414141414141410000 value to sinl on x86 targets. This is related to sysdeps/ieee754/ldbl-96/e_rem_pio2l.c.
|
||||
PrimaryURL: https://avd.aquasec.com/nvd/cve-2020-10029
|
||||
|
||||
Package: apt
|
||||
VulnerabilityID: CVE-2011-3374
|
||||
Severity: LOW
|
||||
InstalledVersion: 1.8.2.3
|
||||
Description: It was found that apt-key in apt, all versions, do not correctly validate gpg keys with the master keyring, leading to a potential man-in-the-middle attack.
|
||||
PrimaryURL: https://avd.aquasec.com/nvd/cve-2011-3374
|
||||
|
||||
Package: bash
|
||||
VulnerabilityID: CVE-2019-18276
|
||||
Severity: LOW
|
||||
Title: bash: when effective UID is not equal to its real UID the saved UID is not dropped
|
||||
InstalledVersion: 5.0-4
|
||||
FixedVersion: 5.0-5
|
||||
Description: An issue was discovered in disable_priv_mode in shell.c in GNU Bash through 5.0 patch 11. By default, if Bash is run with its effective UID not equal to its real UID, it will drop privileges by setting its effective UID to its real UID. However, it does so incorrectly. On Linux and other systems that support "saved UID" functionality, the saved UID is not dropped. An attacker with command execution in the shell can use "enable -f" for runtime loading of a new builtin, which can be a shared object that calls setuid() and therefore regains privileges. However, binaries running with an effective UID of 0 are unaffected.
|
||||
PrimaryURL: https://avd.aquasec.com/nvd/cve-2019-18276
|
||||
|
||||
Package: bash
|
||||
VulnerabilityID: TEMP-0841856-B18BAF
|
||||
Severity: LOW
|
||||
InstalledVersion: 5.0-4
|
||||
PrimaryURL: https://security-tracker.debian.org/tracker/TEMP-0841856-B18BAF
|
||||
@@ -0,0 +1,42 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
import resources from '@/resources';
|
||||
import TrivyScanImageOutputCuller from '@/utils/processOutputInterpreters/trivy-image-output';
|
||||
|
||||
describe('trivy image output', () => {
|
||||
it('echoes a zero-vul image back', () => {
|
||||
const inputPath = path.join('./src/utils/processOutputInterpreters/__tests__/assets', 'trivy-image-metric-server-input.txt');
|
||||
const outputPath = path.join('./src/utils/processOutputInterpreters/__tests__/assets', 'trivy-image-metric-server-output.txt');
|
||||
const inputData = fs.readFileSync(inputPath).toString();
|
||||
const expectedOutputData = fs.readFileSync(outputPath).toString().replace(/\r/g, '');
|
||||
const culler = new TrivyScanImageOutputCuller();
|
||||
|
||||
culler.addData(inputData);
|
||||
const processedData = culler.getProcessedData();
|
||||
|
||||
expect(expectedOutputData).toEqual(processedData);
|
||||
});
|
||||
|
||||
it('converts lines to records and handles inherited cells', () => {
|
||||
const inputPath = path.join('./src/utils/processOutputInterpreters/__tests__/assets', 'trivy-image-postgres-input.txt');
|
||||
const outputPath = path.join('./src/utils/processOutputInterpreters/__tests__/assets', 'trivy-image-postgres-output.txt');
|
||||
const inputData = fs.readFileSync(inputPath).toString();
|
||||
const expectedOutputData = fs.readFileSync(outputPath).toString().replace(/\r/g, '');
|
||||
const culler = new TrivyScanImageOutputCuller();
|
||||
|
||||
culler.addData(inputData);
|
||||
const processedData = culler.getProcessedData();
|
||||
|
||||
expect(expectedOutputData).toEqual(processedData);
|
||||
});
|
||||
|
||||
it('converts windows paths into wsl paths', () => {
|
||||
const windowsPath = 'd:\\we\\really\\like\\backslash\\separators.tpl';
|
||||
const expectedWindowsPath = '/mnt/d/we/really/like/backslash/separators.tpl';
|
||||
const normalPath = '/hey,/no/problem/here';
|
||||
|
||||
expect(resources.wslify(windowsPath)).toBe(expectedWindowsPath);
|
||||
expect(resources.wslify(normalPath)).toBe(normalPath);
|
||||
});
|
||||
});
|
||||
106
src/utils/processOutputInterpreters/trivy-image-output.ts
Normal file
106
src/utils/processOutputInterpreters/trivy-image-output.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
const LineSplitter = /\r?\n/;
|
||||
const dateHeader = /^[-\d]+T[-:.\d]+Z?\s+\033\[\d+m([A-Z]+)\033\[\d+m\s+(.*)$/;
|
||||
const borderPattern = /^\+(?:-+\+){6}\s*$/;
|
||||
const internalBorderPattern = /^\+(?:(?:-+|\s+)\+){6}\s*$/;
|
||||
const rowPattern = /^(?:\|[^|]+){6}\|\s*$/;
|
||||
|
||||
const CVEKeys = ['Package', 'VulnerabilityID', 'Severity', 'Title', 'InstalledVersion', 'FixedVersion', 'Description', 'PrimaryURL'];
|
||||
const severityRatings: Record<string, number> = {
|
||||
LOW: 1,
|
||||
MEDIUM: 2,
|
||||
HIGH: 3,
|
||||
CRITICAL: 4
|
||||
};
|
||||
|
||||
type finalVulType = Record<string, string>;
|
||||
|
||||
export default class TrivyScanImageOutputCuller {
|
||||
prelimLines: Array<string>;
|
||||
JSONLines: Array<string>;
|
||||
inJSON = false;
|
||||
|
||||
constructor() {
|
||||
this.prelimLines = [];
|
||||
this.JSONLines = [];
|
||||
}
|
||||
|
||||
fixLines(lines: Array<string>) {
|
||||
// "key": "value with an escaped \' single quote isn't valid json"
|
||||
return lines.map(line => line.replace(/\\'/g, "'"));
|
||||
}
|
||||
|
||||
addData(data: string): void {
|
||||
if (this.inJSON) {
|
||||
this.JSONLines.push(data.replace(/\\'/g, "'"));
|
||||
|
||||
return;
|
||||
}
|
||||
const lines = data.split(LineSplitter);
|
||||
const jsonStartIndex = lines.indexOf('[');
|
||||
|
||||
if (jsonStartIndex >= 0) {
|
||||
this.prelimLines = this.prelimLines.concat(lines.slice(0, jsonStartIndex));
|
||||
this.inJSON = true;
|
||||
this.JSONLines = this.fixLines(lines.slice(jsonStartIndex));
|
||||
} else {
|
||||
this.prelimLines = this.prelimLines.concat(lines);
|
||||
}
|
||||
}
|
||||
|
||||
getProcessedData() {
|
||||
const prelimLines = this.prelimLines.map(line => line.replace(dateHeader, '$1 $2'));
|
||||
|
||||
if (!this.inJSON) {
|
||||
// No JSON, just so return the lines we have
|
||||
return prelimLines.join('\n');
|
||||
}
|
||||
let core;
|
||||
|
||||
try {
|
||||
core = JSON.parse(this.JSONLines.join(''));
|
||||
} catch (e) {
|
||||
console.log(`Error json parsing ${ this.JSONLines.join('') }`);
|
||||
|
||||
return prelimLines.join('\n');
|
||||
}
|
||||
const detailLines: Array<string> = [];
|
||||
|
||||
core.forEach((targetWithVuls: { [x: string]: any; }) => {
|
||||
const target = targetWithVuls['Target'];
|
||||
const sourceVulnerabilities = targetWithVuls['Vulnerabilities'];
|
||||
|
||||
if (!sourceVulnerabilities.length) {
|
||||
return;
|
||||
}
|
||||
detailLines.push(`Target: ${ target }`, '');
|
||||
|
||||
const processedVulnerabilities: Array<finalVulType> = sourceVulnerabilities.map((v: any) => {
|
||||
const record: finalVulType = {};
|
||||
|
||||
CVEKeys.forEach((key) => {
|
||||
if (v[key]) {
|
||||
record[key] = v[key];
|
||||
}
|
||||
});
|
||||
|
||||
return record;
|
||||
});
|
||||
|
||||
processedVulnerabilities.sort();
|
||||
processedVulnerabilities.sort((a, b) => {
|
||||
return severityRatings[b['Severity']] - severityRatings[a['Severity']];
|
||||
});
|
||||
|
||||
processedVulnerabilities.forEach((vul) => {
|
||||
CVEKeys.forEach((key) => {
|
||||
if (key in vul) {
|
||||
detailLines.push(`${ key }: ${ vul[key] }`);
|
||||
}
|
||||
});
|
||||
detailLines.push('');
|
||||
});
|
||||
});
|
||||
|
||||
return prelimLines.concat(detailLines).join('\n');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user