Skip to content

Commit

Permalink
feat(wrlinux): Add Wind River Linux vulnerability data (#177)
Browse files Browse the repository at this point in the history
Signed-off-by: Sakib Sajal <[email protected]>
  • Loading branch information
sajal-wr committed Nov 9, 2022
1 parent ea064da commit 0b161fc
Show file tree
Hide file tree
Showing 6 changed files with 385 additions and 2 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/update.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ jobs:
name: CBL-Mariner Vulnerability Data
run: ./vuln-list-update -target mariner

- if: always()
name: WindRiver CVE Tracker
run: ./vuln-list-update -target wrlinux

- if: always()
name: OSV Database
run: ./vuln-list-update -target osv
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ https://github.com/aquasecurity/vuln-list/
$ vuln-list-update -h
Usage of vuln-list-update:
-target string
update target (nvd, alpine, alpine-unfixed, redhat, redhat-oval, debian, debian-oval, ubuntu, amazon, oracle-oval, suse-cvrf, photon, arch-linux, ghsa, glad, cwe, osv, go-vulndb, mariner, kevc)
update target (nvd, alpine, alpine-unfixed, redhat, redhat-oval, debian, debian-oval, ubuntu, amazon, oracle-oval, suse-cvrf, photon, arch-linux, ghsa, glad, cwe, osv, go-vulndb, mariner, kevc, wrlinux)
-years string
update years (only redhat)
```
Expand Down
8 changes: 7 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import (
susecvrf "github.com/aquasecurity/vuln-list-update/suse/cvrf"
"github.com/aquasecurity/vuln-list-update/ubuntu"
"github.com/aquasecurity/vuln-list-update/utils"
"github.com/aquasecurity/vuln-list-update/wrlinux"
)

const (
Expand All @@ -48,7 +49,7 @@ const (

var (
target = flag.String("target", "", "update target (nvd, alpine, alpine-unfixed, redhat, redhat-oval, "+
"debian, debian-oval, ubuntu, amazon, oracle-oval, suse-cvrf, photon, arch-linux, ghsa, glad, cwe, osv, go-vulndb, mariner, kevc)")
"debian, debian-oval, ubuntu, amazon, oracle-oval, suse-cvrf, photon, arch-linux, ghsa, glad, cwe, osv, go-vulndb, mariner, kevc, wrlinux)")
years = flag.String("years", "", "update years (only redhat)")
targetUri = flag.String("target-uri", "", "alternative repository URI (only glad)")
targetBranch = flag.String("target-branch", "", "alternative repository branch (only glad)")
Expand Down Expand Up @@ -228,6 +229,11 @@ func run() error {
return xerrors.Errorf("Known Exploited Vulnerability Catalog update error: %w", err)
}
commitMsg = "Known Exploited Vulnerability Catalog"
case "wrlinux":
if err := wrlinux.Update(); err != nil {
return xerrors.Errorf("WRLinux update error: %w", err)
}
commitMsg = "Wind River CVE Tracker"
default:
return xerrors.New("unknown target")
}
Expand Down
18 changes: 18 additions & 0 deletions wrlinux/testdata/golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Candidate: CVE-2020-24241
PublicDate: 2020-08-25
Description:
In Netwide Assembler (NASM) 2.15rc10, there is heap use-after-free
in saa_wbytes in nasmlib/saa.c.
Notes:
Priority: medium
Bugs:
LINCD-2974
LIN1019-5289
LIN1018-6614
LIN10-7689

Patches_nasm:
10.20.6.0_nasm: not-affected
10.19.45.1_nasm: pending
10.18.44.1_nasm: ignored
10.17.41.1_nasm: released (10.17.41.22)
273 changes: 273 additions & 0 deletions wrlinux/wrlinux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
/*
* Copyright (c) 2022 Wind River Systems, Inc.
*
* The right to copy, distribute, modify, or otherwise make use
* of this software may be licensed only pursuant to the terms
* of an applicable Wind River license agreement.
*/

package wrlinux

import (
"io"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"time"

"github.com/aquasecurity/vuln-list-update/git"
"github.com/araddon/dateparse"
"golang.org/x/xerrors"
"github.com/aquasecurity/vuln-list-update/utils"
)

const (
cveTrackerDir = "windriver-cve-tracker"
windriverDir = "wrlinux"
)

var (
repoURLs = []string{
"https://distro.windriver.com/git/windriver-cve-tracker.git",
}
targets = []string{
"active",
}
statuses = []string{
"released",
"pending",
"not-affected",
"ignored",
}
)

type Vulnerability struct {
Candidate string
PublicDate time.Time
Description string
References []string
Notes []string
Priority string
Bugs []string
Patches map[Package]Statuses
}

type Package string

type Release string

type Statuses map[Release]Status

type Status struct {
Status string
Note string
}

func Update() error {
var err error
gc := git.Config{}
dir := filepath.Join(utils.CacheDir(), cveTrackerDir)
for _, url := range repoURLs {
_, err = gc.CloneOrPull(url, dir, "master", false)
if err == nil {
break
}
log.Printf("failed to clone or pull: %s: %v", url, err)
log.Printf("removing %s directory", cveTrackerDir)
if err := os.RemoveAll(dir); err != nil {
return xerrors.Errorf("failed to remove %s directory: %w", cveTrackerDir, err)
}
}
if err != nil {
return xerrors.Errorf("failed to clone or pull: %w", err)
}

dst := filepath.Join(utils.VulnListDir(), windriverDir)
log.Printf("removing windriver directory %s", dst)
if err := os.RemoveAll(dst); err != nil {
return xerrors.Errorf("failed to remove windriver directory: %w", err)
}

log.Println("walking windriver-cve-tracker ...")
for _, target := range targets {
if err := walkDir(filepath.Join(dir, target)); err != nil {
return err
}
}

return nil
}

func walkDir(root string) error {
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
if err != nil {
return xerrors.Errorf("file walk error: %w", err)
}
if info.IsDir() {
return nil
}

base := filepath.Base(path)
if !strings.HasPrefix(base, "CVE-") {
return nil
}

f, err := os.Open(path)
if err != nil {
return xerrors.Errorf("error in file open: %w", err)
}

vuln, err := parse(f)
if err != nil {
return xerrors.Errorf("error in parse: %w", err)
}

if err = utils.SaveCVEPerYear(filepath.Join(utils.VulnListDir(), windriverDir), vuln.Candidate, vuln); err != nil {
return xerrors.Errorf("error in save: %w", err)
}

return nil
})

if err != nil {
return xerrors.Errorf("error in walk: %w", err)
}
return nil
}

func parse(r io.Reader) (vuln *Vulnerability, err error) {
vuln = &Vulnerability{}
vuln.Patches = map[Package]Statuses{}

all, err := ioutil.ReadAll(r)
if err != nil {
return nil, err
}
lines := strings.Split(string(all), "\n")

for i := 0; i < len(lines); i++ {
line := lines[i]

// Skip
if strings.HasPrefix(line, "#") || line == "" {
continue
}

// Parse Candidate
if strings.HasPrefix(line, "Candidate:") {
line = strings.TrimPrefix(line, "Candidate:")
vuln.Candidate = strings.TrimSpace(line)
continue
}

// Parse PublicDate
if strings.HasPrefix(line, "PublicDate:") {
line = strings.TrimPrefix(line, "PublicDate:")
line = strings.TrimSpace(line)
vuln.PublicDate, _ = dateparse.ParseAny(line)
continue
}

// Parse Description
if strings.HasPrefix(line, "Description:") {
var description []string
for strings.HasPrefix(lines[i+1], " ") {
i++
line = strings.TrimSpace(lines[i])
description = append(description, line)
}
vuln.Description = strings.Join(description, " ")
continue
}

// Parse References
if strings.HasPrefix(line, "References:") {
for strings.HasPrefix(lines[i+1], " ") {
i++
line = strings.TrimSpace(lines[i])
vuln.References = append(vuln.References, line)
}
continue
}

// Parse Notes
if strings.HasPrefix(line, "Notes:") {
for strings.HasPrefix(lines[i+1], " ") {
i++
line = strings.TrimSpace(lines[i])
note := []string{line}
for strings.HasPrefix(lines[i+1], " ") {
i++
l := strings.TrimSpace(lines[i])
note = append(note, l)
}
vuln.Notes = append(vuln.Notes, strings.Join(note, " "))
}
continue
}

// Parse Priority
if strings.HasPrefix(line, "Priority:") {
line = strings.TrimPrefix(line, "Priority:")
vuln.Priority = strings.TrimSpace(line)
continue
}

// Parse Bugs
if strings.HasPrefix(line, "Bugs:") {
for strings.HasPrefix(lines[i+1], " ") {
i++
line = strings.TrimSpace(lines[i])
vuln.Bugs = append(vuln.Bugs, line)
}
continue
}

// Parse Patches
// e.g. trusty/esm_vnc4: needs-triage
s := strings.SplitN(line, ":", 2)
if len(s) < 2 {
continue
}

status := strings.TrimSpace(s[1])

// Some advisories have status with "Patches_" prefix and it should be skipped
// e.g. Patches_qtwebkit-opensource-src: needs-triage
if isPatch(status) && !strings.HasPrefix(s[0], "Patches_") {
pkgRel := strings.SplitN(s[0], "_", 2)
release := Release(pkgRel[0])
pkgName := Package(strings.Trim(pkgRel[1], ":"))

fields := strings.Fields(status)
status := Status{
Status: fields[0],
}
if len(fields) > 1 {
note := strings.Join(fields[1:], " ")
status.Note = strings.Trim(note, "()")
}

if existingStatuses, ok := vuln.Patches[pkgName]; ok {
existingStatuses[release] = status
vuln.Patches[pkgName] = existingStatuses
} else {
statuses := Statuses{}
statuses[release] = status
vuln.Patches[pkgName] = statuses
}
}
}
return vuln, nil
}

func isPatch(s string) bool {
for _, status := range statuses {
if strings.HasPrefix(s, status) {
return true
}
}
return false
}
Loading

0 comments on commit 0b161fc

Please sign in to comment.