Compare commits
	
		
			8 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					91ed318c5d | ||
| 
						 | 
					bfc3828ce1 | ||
| 
						 | 
					c7eac4e7fe | ||
| 
						 | 
					cc63a0eccf | ||
| 
						 | 
					fd18df1dd4 | ||
| 
						 | 
					8775b5efdf | ||
| 
						 | 
					a9f29a6c5d | ||
| 
						 | 
					05fdde48f9 | 
							
								
								
									
										2
									
								
								.github/workflows/golangci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/golangci.yml
									
									
									
									
										vendored
									
									
								
							@@ -16,7 +16,7 @@ jobs:
 | 
			
		||||
        uses: golangci/golangci-lint-action@v2
 | 
			
		||||
        with:
 | 
			
		||||
          # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
 | 
			
		||||
          version: v1.42
 | 
			
		||||
          version: v1.45
 | 
			
		||||
          args: --timeout=10m
 | 
			
		||||
          
 | 
			
		||||
          # Optional: working directory, useful for monorepos
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								.github/workflows/goreleaser.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/goreleaser.yml
									
									
									
									
										vendored
									
									
								
							@@ -19,7 +19,7 @@ jobs:
 | 
			
		||||
        name: Set up Go
 | 
			
		||||
        uses: actions/setup-go@v2
 | 
			
		||||
        with:
 | 
			
		||||
          go-version: 1.16
 | 
			
		||||
          go-version: 1.18
 | 
			
		||||
      -
 | 
			
		||||
        name: Run GoReleaser
 | 
			
		||||
        uses: goreleaser/goreleaser-action@v2
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							@@ -11,7 +11,7 @@ jobs:
 | 
			
		||||
    - name: Set up Go 1.x
 | 
			
		||||
      uses: actions/setup-go@v2
 | 
			
		||||
      with:
 | 
			
		||||
        go-version: 1.16.x
 | 
			
		||||
        go-version: 1.18.x
 | 
			
		||||
      id: go
 | 
			
		||||
 | 
			
		||||
    - name: Check out code into the Go module directory
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,9 @@
 | 
			
		||||
name: golang-ci
 | 
			
		||||
 | 
			
		||||
run:
 | 
			
		||||
  timeout: 10m
 | 
			
		||||
  go: '1.18'
 | 
			
		||||
  
 | 
			
		||||
linters-settings:
 | 
			
		||||
  revive:
 | 
			
		||||
    # see https://github.com/mgechev/revive#available-rules for details.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										25
									
								
								GNUmakefile
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								GNUmakefile
									
									
									
									
									
								
							@@ -23,12 +23,9 @@ CGO_UNABLED := CGO_ENABLED=0 go
 | 
			
		||||
GO_OFF := GO111MODULE=off go
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
all: b
 | 
			
		||||
all: build test
 | 
			
		||||
 | 
			
		||||
build: ./cmd/vuls/main.go pretest fmt
 | 
			
		||||
	$(GO) build -a -ldflags "$(LDFLAGS)" -o vuls ./cmd/vuls
 | 
			
		||||
 | 
			
		||||
b: ./cmd/vuls/main.go 
 | 
			
		||||
build: ./cmd/vuls/main.go
 | 
			
		||||
	$(GO) build -a -ldflags "$(LDFLAGS)" -o vuls ./cmd/vuls
 | 
			
		||||
 | 
			
		||||
install: ./cmd/vuls/main.go
 | 
			
		||||
@@ -41,13 +38,14 @@ install-scanner: ./cmd/scanner/main.go
 | 
			
		||||
	$(CGO_UNABLED) install -tags=scanner -ldflags "$(LDFLAGS)" ./cmd/scanner
 | 
			
		||||
 | 
			
		||||
lint:
 | 
			
		||||
	$(GO_OFF) get -u github.com/mgechev/revive
 | 
			
		||||
	$(GO) install github.com/mgechev/revive@latest
 | 
			
		||||
	revive -config ./.revive.toml -formatter plain $(PKGS)
 | 
			
		||||
 | 
			
		||||
vet:
 | 
			
		||||
	echo $(PKGS) | xargs env $(GO) vet || exit;
 | 
			
		||||
 | 
			
		||||
golangci:
 | 
			
		||||
	$(GO) install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
 | 
			
		||||
	golangci-lint run
 | 
			
		||||
 | 
			
		||||
fmt:
 | 
			
		||||
@@ -59,9 +57,9 @@ mlint:
 | 
			
		||||
fmtcheck:
 | 
			
		||||
	$(foreach file,$(SRCS),gofmt -s -d $(file);)
 | 
			
		||||
 | 
			
		||||
pretest: lint vet fmtcheck golangci
 | 
			
		||||
pretest: lint vet fmtcheck
 | 
			
		||||
 | 
			
		||||
test: 
 | 
			
		||||
test: pretest
 | 
			
		||||
	$(GO) test -cover -v ./... || exit;
 | 
			
		||||
 | 
			
		||||
unused:
 | 
			
		||||
@@ -76,13 +74,12 @@ clean:
 | 
			
		||||
	echo $(PKGS) | xargs go clean || exit;
 | 
			
		||||
 | 
			
		||||
# trivy-to-vuls
 | 
			
		||||
build-trivy-to-vuls: pretest fmt
 | 
			
		||||
	$(GO) build -a -ldflags "$(LDFLAGS)" -o trivy-to-vuls contrib/trivy/cmd/*.go
 | 
			
		||||
build-trivy-to-vuls: ./contrib/trivy/cmd/main.go
 | 
			
		||||
	$(GO) build -a -ldflags "$(LDFLAGS)" -o trivy-to-vuls ./contrib/trivy/cmd
 | 
			
		||||
 | 
			
		||||
# future-vuls
 | 
			
		||||
build-future-vuls: pretest fmt
 | 
			
		||||
	$(GO) build -a -ldflags "$(LDFLAGS)" -o future-vuls contrib/future-vuls/cmd/*.go
 | 
			
		||||
 | 
			
		||||
build-future-vuls: ./contrib/future-vuls/cmd/main.go
 | 
			
		||||
	$(GO) build -a -ldflags "$(LDFLAGS)" -o future-vuls ./contrib/future-vuls/cmd
 | 
			
		||||
 | 
			
		||||
# integration-test
 | 
			
		||||
BASE_DIR := '${PWD}/integration/results'
 | 
			
		||||
@@ -91,7 +88,7 @@ NOW=$(shell date --iso-8601=seconds)
 | 
			
		||||
NOW_JSON_DIR := '${BASE_DIR}/$(NOW)'
 | 
			
		||||
ONE_SEC_AFTER=$(shell date -d '+1 second' --iso-8601=seconds)
 | 
			
		||||
ONE_SEC_AFTER_JSON_DIR := '${BASE_DIR}/$(ONE_SEC_AFTER)'
 | 
			
		||||
LIBS := 'bundler' 'pip' 'pipenv' 'poetry' 'composer' 'npm' 'yarn' 'cargo' 'gomod' 'gobinary' 'jar' 'pom' 'nuget-lock' 'nuget-config' 'nvd_exact' 'nvd_rough' 'nvd_vendor_product' 'nvd_match_no_jvn' 'jvn_vendor_product' 'jvn_vendor_product_nover'
 | 
			
		||||
LIBS := 'bundler' 'pip' 'pipenv' 'poetry' 'composer' 'npm' 'yarn' 'cargo' 'gomod' 'gosum' 'gobinary' 'jar' 'pom' 'nuget-lock' 'nuget-config' 'nvd_exact' 'nvd_rough' 'nvd_vendor_product' 'nvd_match_no_jvn' 'jvn_vendor_product' 'jvn_vendor_product_nover'
 | 
			
		||||
 | 
			
		||||
diff:
 | 
			
		||||
	# git clone git@github.com:vulsio/vulsctl.git
 | 
			
		||||
 
 | 
			
		||||
@@ -136,15 +136,20 @@ func GetEOL(family, release string) (eol EOL, found bool) {
 | 
			
		||||
			"19.10": {Ended: true},
 | 
			
		||||
			"20.04": {
 | 
			
		||||
				StandardSupportUntil: time.Date(2025, 4, 1, 23, 59, 59, 0, time.UTC),
 | 
			
		||||
				ExtendedSupportUntil: time.Date(2030, 4, 1, 23, 59, 59, 0, time.UTC),
 | 
			
		||||
			},
 | 
			
		||||
			"20.10": {
 | 
			
		||||
				StandardSupportUntil: time.Date(2021, 7, 22, 23, 59, 59, 0, time.UTC),
 | 
			
		||||
			},
 | 
			
		||||
			"21.04": {
 | 
			
		||||
				StandardSupportUntil: time.Date(2022, 1, 22, 23, 59, 59, 0, time.UTC),
 | 
			
		||||
				StandardSupportUntil: time.Date(2022, 1, 20, 23, 59, 59, 0, time.UTC),
 | 
			
		||||
			},
 | 
			
		||||
			"21.10": {
 | 
			
		||||
				StandardSupportUntil: time.Date(2022, 7, 1, 23, 59, 59, 0, time.UTC),
 | 
			
		||||
				StandardSupportUntil: time.Date(2022, 7, 14, 23, 59, 59, 0, time.UTC),
 | 
			
		||||
			},
 | 
			
		||||
			"22.04": {
 | 
			
		||||
				StandardSupportUntil: time.Date(2027, 4, 1, 23, 59, 59, 0, time.UTC),
 | 
			
		||||
				ExtendedSupportUntil: time.Date(2032, 4, 1, 23, 59, 59, 0, time.UTC),
 | 
			
		||||
			},
 | 
			
		||||
		}[release]
 | 
			
		||||
	case constant.OpenSUSE:
 | 
			
		||||
 
 | 
			
		||||
@@ -204,28 +204,12 @@ func TestEOL_IsStandardSupportEnded(t *testing.T) {
 | 
			
		||||
		},
 | 
			
		||||
		//Ubuntu
 | 
			
		||||
		{
 | 
			
		||||
			name:     "Ubuntu 18.04 supported",
 | 
			
		||||
			fields:   fields{family: Ubuntu, release: "18.04"},
 | 
			
		||||
			name:     "Ubuntu 12.10 not found",
 | 
			
		||||
			fields:   fields{family: Ubuntu, release: "12.10"},
 | 
			
		||||
			now:      time.Date(2021, 1, 6, 23, 59, 59, 0, time.UTC),
 | 
			
		||||
			found:    false,
 | 
			
		||||
			stdEnded: false,
 | 
			
		||||
			extEnded: false,
 | 
			
		||||
			found:    true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:     "Ubuntu 18.04 ext supported",
 | 
			
		||||
			fields:   fields{family: Ubuntu, release: "18.04"},
 | 
			
		||||
			now:      time.Date(2025, 1, 6, 23, 59, 59, 0, time.UTC),
 | 
			
		||||
			stdEnded: true,
 | 
			
		||||
			extEnded: false,
 | 
			
		||||
			found:    true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:     "Ubuntu 16.04 supported",
 | 
			
		||||
			fields:   fields{family: Ubuntu, release: "18.04"},
 | 
			
		||||
			now:      time.Date(2021, 1, 6, 23, 59, 59, 0, time.UTC),
 | 
			
		||||
			stdEnded: false,
 | 
			
		||||
			extEnded: false,
 | 
			
		||||
			found:    true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:     "Ubuntu 14.04 eol",
 | 
			
		||||
@@ -244,12 +228,44 @@ func TestEOL_IsStandardSupportEnded(t *testing.T) {
 | 
			
		||||
			found:    true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:     "Ubuntu 12.10 not found",
 | 
			
		||||
			fields:   fields{family: Ubuntu, release: "12.10"},
 | 
			
		||||
			name:     "Ubuntu 16.04 supported",
 | 
			
		||||
			fields:   fields{family: Ubuntu, release: "18.04"},
 | 
			
		||||
			now:      time.Date(2021, 1, 6, 23, 59, 59, 0, time.UTC),
 | 
			
		||||
			found:    false,
 | 
			
		||||
			stdEnded: false,
 | 
			
		||||
			extEnded: false,
 | 
			
		||||
			found:    true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:     "Ubuntu 18.04 supported",
 | 
			
		||||
			fields:   fields{family: Ubuntu, release: "18.04"},
 | 
			
		||||
			now:      time.Date(2021, 1, 6, 23, 59, 59, 0, time.UTC),
 | 
			
		||||
			stdEnded: false,
 | 
			
		||||
			extEnded: false,
 | 
			
		||||
			found:    true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:     "Ubuntu 18.04 ext supported",
 | 
			
		||||
			fields:   fields{family: Ubuntu, release: "18.04"},
 | 
			
		||||
			now:      time.Date(2025, 1, 6, 23, 59, 59, 0, time.UTC),
 | 
			
		||||
			stdEnded: true,
 | 
			
		||||
			extEnded: false,
 | 
			
		||||
			found:    true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:     "Ubuntu 20.04 supported",
 | 
			
		||||
			fields:   fields{family: Ubuntu, release: "20.04"},
 | 
			
		||||
			now:      time.Date(2021, 5, 1, 23, 59, 59, 0, time.UTC),
 | 
			
		||||
			found:    true,
 | 
			
		||||
			stdEnded: false,
 | 
			
		||||
			extEnded: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:     "Ubuntu 20.04 ext supported",
 | 
			
		||||
			fields:   fields{family: Ubuntu, release: "20.04"},
 | 
			
		||||
			now:      time.Date(2025, 5, 1, 23, 59, 59, 0, time.UTC),
 | 
			
		||||
			found:    true,
 | 
			
		||||
			stdEnded: true,
 | 
			
		||||
			extEnded: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:     "Ubuntu 20.10 supported",
 | 
			
		||||
@@ -267,6 +283,22 @@ func TestEOL_IsStandardSupportEnded(t *testing.T) {
 | 
			
		||||
			stdEnded: false,
 | 
			
		||||
			extEnded: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:     "Ubuntu 21.10 supported",
 | 
			
		||||
			fields:   fields{family: Ubuntu, release: "21.10"},
 | 
			
		||||
			now:      time.Date(2021, 1, 6, 23, 59, 59, 0, time.UTC),
 | 
			
		||||
			found:    true,
 | 
			
		||||
			stdEnded: false,
 | 
			
		||||
			extEnded: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:     "Ubuntu 22.04 supported",
 | 
			
		||||
			fields:   fields{family: Ubuntu, release: "22.04"},
 | 
			
		||||
			now:      time.Date(2022, 5, 1, 23, 59, 59, 0, time.UTC),
 | 
			
		||||
			found:    true,
 | 
			
		||||
			stdEnded: false,
 | 
			
		||||
			extEnded: false,
 | 
			
		||||
		},
 | 
			
		||||
		//Debian
 | 
			
		||||
		{
 | 
			
		||||
			name:     "Debian 9 supported",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ RUN apk add --no-cache \
 | 
			
		||||
        make \
 | 
			
		||||
        gcc \
 | 
			
		||||
        musl-dev
 | 
			
		||||
RUN go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.45.0
 | 
			
		||||
 | 
			
		||||
ENV REPOSITORY github.com/future-architect/vuls
 | 
			
		||||
COPY . $GOPATH/src/$REPOSITORY
 | 
			
		||||
@@ -27,6 +26,7 @@ RUN apk add --no-cache \
 | 
			
		||||
    && mkdir -p $WORKDIR $LOGDIR
 | 
			
		||||
 | 
			
		||||
COPY --from=builder /go/bin/vuls /go/bin/trivy-to-vuls /go/bin/future-vuls /usr/local/bin/
 | 
			
		||||
COPY --from=aquasec/trivy:latest /usr/local/bin/trivy /usr/local/bin/trivy
 | 
			
		||||
 | 
			
		||||
VOLUME ["$WORKDIR", "$LOGDIR"]
 | 
			
		||||
WORKDIR $WORKDIR
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@ package v2
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/aquasecurity/trivy/pkg/types"
 | 
			
		||||
@@ -34,35 +35,28 @@ func (p ParserV2) Parse(vulnJSON []byte) (result *models.ScanResult, err error)
 | 
			
		||||
	return scanResult, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func setScanResultMeta(scanResult *models.ScanResult, report *types.Report) error {
 | 
			
		||||
	const trivyTarget = "trivy-target"
 | 
			
		||||
	for _, r := range report.Results {
 | 
			
		||||
		if pkg.IsTrivySupportedOS(r.Type) {
 | 
			
		||||
			scanResult.Family = r.Type
 | 
			
		||||
			scanResult.ServerName = r.Target
 | 
			
		||||
			scanResult.Optional = map[string]interface{}{
 | 
			
		||||
				trivyTarget: r.Target,
 | 
			
		||||
			}
 | 
			
		||||
		} else if pkg.IsTrivySupportedLib(r.Type) {
 | 
			
		||||
			if scanResult.Family == "" {
 | 
			
		||||
				scanResult.Family = constant.ServerTypePseudo
 | 
			
		||||
			}
 | 
			
		||||
			if scanResult.ServerName == "" {
 | 
			
		||||
				scanResult.ServerName = "library scan by trivy"
 | 
			
		||||
			}
 | 
			
		||||
			if _, ok := scanResult.Optional[trivyTarget]; !ok {
 | 
			
		||||
				scanResult.Optional = map[string]interface{}{
 | 
			
		||||
					trivyTarget: r.Target,
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		scanResult.ScannedAt = time.Now()
 | 
			
		||||
		scanResult.ScannedBy = "trivy"
 | 
			
		||||
		scanResult.ScannedVia = "trivy"
 | 
			
		||||
	}
 | 
			
		||||
var dockerTagPattern = regexp.MustCompile(`:.+$`)
 | 
			
		||||
 | 
			
		||||
	if _, ok := scanResult.Optional[trivyTarget]; !ok {
 | 
			
		||||
func setScanResultMeta(scanResult *models.ScanResult, report *types.Report) error {
 | 
			
		||||
	if len(report.Results) == 0 {
 | 
			
		||||
		return xerrors.Errorf("scanned images or libraries are not supported by Trivy. see https://aquasecurity.github.io/trivy/dev/vulnerability/detection/os/, https://aquasecurity.github.io/trivy/dev/vulnerability/detection/language/")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	scanResult.ServerName = report.ArtifactName
 | 
			
		||||
	if report.ArtifactType == "container_image" && !dockerTagPattern.MatchString(scanResult.ServerName) {
 | 
			
		||||
		scanResult.ServerName += ":latest" // Complement if the tag is omitted
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if report.Metadata.OS != nil {
 | 
			
		||||
		scanResult.Family = report.Metadata.OS.Family
 | 
			
		||||
		scanResult.Release = report.Metadata.OS.Name
 | 
			
		||||
	} else {
 | 
			
		||||
		scanResult.Family = constant.ServerTypePseudo
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	scanResult.ScannedAt = time.Now()
 | 
			
		||||
	scanResult.ScannedBy = "trivy"
 | 
			
		||||
	scanResult.ScannedVia = "trivy"
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -203,8 +203,9 @@ var redisTrivy = []byte(`
 | 
			
		||||
`)
 | 
			
		||||
var redisSR = &models.ScanResult{
 | 
			
		||||
	JSONVersion: 4,
 | 
			
		||||
	ServerName:  "redis (debian 10.10)",
 | 
			
		||||
	ServerName:  "redis:latest",
 | 
			
		||||
	Family:      "debian",
 | 
			
		||||
	Release:     "10.10",
 | 
			
		||||
	ScannedBy:   "trivy",
 | 
			
		||||
	ScannedVia:  "trivy",
 | 
			
		||||
	ScannedCves: models.VulnInfos{
 | 
			
		||||
@@ -262,9 +263,7 @@ var redisSR = &models.ScanResult{
 | 
			
		||||
			BinaryNames: []string{"bsdutils", "pkgA"},
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	Optional: map[string]interface{}{
 | 
			
		||||
		"trivy-target": "redis (debian 10.10)",
 | 
			
		||||
	},
 | 
			
		||||
	Optional: nil,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var strutsTrivy = []byte(`
 | 
			
		||||
@@ -373,7 +372,7 @@ var strutsTrivy = []byte(`
 | 
			
		||||
 | 
			
		||||
var strutsSR = &models.ScanResult{
 | 
			
		||||
	JSONVersion: 4,
 | 
			
		||||
	ServerName:  "library scan by trivy",
 | 
			
		||||
	ServerName:  "/data/struts-1.2.7/lib",
 | 
			
		||||
	Family:      "pseudo",
 | 
			
		||||
	ScannedBy:   "trivy",
 | 
			
		||||
	ScannedVia:  "trivy",
 | 
			
		||||
@@ -459,9 +458,7 @@ var strutsSR = &models.ScanResult{
 | 
			
		||||
	},
 | 
			
		||||
	Packages:    models.Packages{},
 | 
			
		||||
	SrcPackages: models.SrcPackages{},
 | 
			
		||||
	Optional: map[string]interface{}{
 | 
			
		||||
		"trivy-target": "Java",
 | 
			
		||||
	},
 | 
			
		||||
	Optional:    nil,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var osAndLibTrivy = []byte(`
 | 
			
		||||
@@ -633,8 +630,9 @@ var osAndLibTrivy = []byte(`
 | 
			
		||||
 | 
			
		||||
var osAndLibSR = &models.ScanResult{
 | 
			
		||||
	JSONVersion: 4,
 | 
			
		||||
	ServerName:  "quay.io/fluentd_elasticsearch/fluentd:v2.9.0 (debian 10.2)",
 | 
			
		||||
	ServerName:  "quay.io/fluentd_elasticsearch/fluentd:v2.9.0",
 | 
			
		||||
	Family:      "debian",
 | 
			
		||||
	Release:     "10.2",
 | 
			
		||||
	ScannedBy:   "trivy",
 | 
			
		||||
	ScannedVia:  "trivy",
 | 
			
		||||
	ScannedCves: models.VulnInfos{
 | 
			
		||||
@@ -720,9 +718,7 @@ var osAndLibSR = &models.ScanResult{
 | 
			
		||||
			BinaryNames: []string{"libgnutls30"},
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	Optional: map[string]interface{}{
 | 
			
		||||
		"trivy-target": "quay.io/fluentd_elasticsearch/fluentd:v2.9.0 (debian 10.2)",
 | 
			
		||||
	},
 | 
			
		||||
	Optional: nil,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestParseError(t *testing.T) {
 | 
			
		||||
 
 | 
			
		||||
@@ -4,8 +4,6 @@ import (
 | 
			
		||||
	"sort"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	ftypes "github.com/aquasecurity/fanal/types"
 | 
			
		||||
 | 
			
		||||
	"github.com/aquasecurity/fanal/analyzer/os"
 | 
			
		||||
	"github.com/aquasecurity/trivy/pkg/types"
 | 
			
		||||
 | 
			
		||||
@@ -79,8 +77,8 @@ func Convert(results types.Results) (result *models.ScanResult, err error) {
 | 
			
		||||
					LastModified:  lastModified,
 | 
			
		||||
				}},
 | 
			
		||||
			}
 | 
			
		||||
			// do onlyIif image type is Vuln
 | 
			
		||||
			if IsTrivySupportedOS(trivyResult.Type) {
 | 
			
		||||
			// do only if image type is Vuln
 | 
			
		||||
			if isTrivySupportedOS(trivyResult.Type) {
 | 
			
		||||
				pkgs[vuln.PkgName] = models.Package{
 | 
			
		||||
					Name:    vuln.PkgName,
 | 
			
		||||
					Version: vuln.InstalledVersion,
 | 
			
		||||
@@ -178,51 +176,25 @@ func Convert(results types.Results) (result *models.ScanResult, err error) {
 | 
			
		||||
	return scanResult, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsTrivySupportedOS :
 | 
			
		||||
func IsTrivySupportedOS(family string) bool {
 | 
			
		||||
	supportedFamilies := map[string]interface{}{
 | 
			
		||||
		os.RedHat:             struct{}{},
 | 
			
		||||
		os.Debian:             struct{}{},
 | 
			
		||||
		os.Ubuntu:             struct{}{},
 | 
			
		||||
		os.CentOS:             struct{}{},
 | 
			
		||||
		os.Rocky:              struct{}{},
 | 
			
		||||
		os.Alma:               struct{}{},
 | 
			
		||||
		os.Fedora:             struct{}{},
 | 
			
		||||
		os.Amazon:             struct{}{},
 | 
			
		||||
		os.Oracle:             struct{}{},
 | 
			
		||||
		os.Windows:            struct{}{},
 | 
			
		||||
		os.OpenSUSE:           struct{}{},
 | 
			
		||||
		os.OpenSUSELeap:       struct{}{},
 | 
			
		||||
		os.OpenSUSETumbleweed: struct{}{},
 | 
			
		||||
		os.SLES:               struct{}{},
 | 
			
		||||
		os.Photon:             struct{}{},
 | 
			
		||||
		os.Alpine:             struct{}{},
 | 
			
		||||
		// os.Fedora:             struct{}{}, not supported yet
 | 
			
		||||
func isTrivySupportedOS(family string) bool {
 | 
			
		||||
	supportedFamilies := map[string]struct{}{
 | 
			
		||||
		os.RedHat:             {},
 | 
			
		||||
		os.Debian:             {},
 | 
			
		||||
		os.Ubuntu:             {},
 | 
			
		||||
		os.CentOS:             {},
 | 
			
		||||
		os.Rocky:              {},
 | 
			
		||||
		os.Alma:               {},
 | 
			
		||||
		os.Fedora:             {},
 | 
			
		||||
		os.Amazon:             {},
 | 
			
		||||
		os.Oracle:             {},
 | 
			
		||||
		os.Windows:            {},
 | 
			
		||||
		os.OpenSUSE:           {},
 | 
			
		||||
		os.OpenSUSELeap:       {},
 | 
			
		||||
		os.OpenSUSETumbleweed: {},
 | 
			
		||||
		os.SLES:               {},
 | 
			
		||||
		os.Photon:             {},
 | 
			
		||||
		os.Alpine:             {},
 | 
			
		||||
	}
 | 
			
		||||
	_, ok := supportedFamilies[family]
 | 
			
		||||
	return ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsTrivySupportedLib :
 | 
			
		||||
func IsTrivySupportedLib(typestr string) bool {
 | 
			
		||||
	supportedLibs := map[string]interface{}{
 | 
			
		||||
		ftypes.Bundler:   struct{}{},
 | 
			
		||||
		ftypes.GemSpec:   struct{}{},
 | 
			
		||||
		ftypes.Cargo:     struct{}{},
 | 
			
		||||
		ftypes.Composer:  struct{}{},
 | 
			
		||||
		ftypes.Npm:       struct{}{},
 | 
			
		||||
		ftypes.NuGet:     struct{}{},
 | 
			
		||||
		ftypes.Pip:       struct{}{},
 | 
			
		||||
		ftypes.Pipenv:    struct{}{},
 | 
			
		||||
		ftypes.Poetry:    struct{}{},
 | 
			
		||||
		ftypes.PythonPkg: struct{}{},
 | 
			
		||||
		ftypes.NodePkg:   struct{}{},
 | 
			
		||||
		ftypes.Yarn:      struct{}{},
 | 
			
		||||
		ftypes.Jar:       struct{}{},
 | 
			
		||||
		ftypes.Pom:       struct{}{},
 | 
			
		||||
		ftypes.GoBinary:  struct{}{},
 | 
			
		||||
		ftypes.GoMod:     struct{}{},
 | 
			
		||||
	}
 | 
			
		||||
	_, ok := supportedLibs[typestr]
 | 
			
		||||
	return ok
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -208,31 +208,21 @@ func Detect(rs []models.ScanResult, dir string) ([]models.ScanResult, error) {
 | 
			
		||||
// pass 2 configs
 | 
			
		||||
func DetectPkgCves(r *models.ScanResult, ovalCnf config.GovalDictConf, gostCnf config.GostConf, logOpts logging.LogOpts) error {
 | 
			
		||||
	// Pkg Scan
 | 
			
		||||
	if r.Release != "" {
 | 
			
		||||
		if len(r.Packages)+len(r.SrcPackages) > 0 {
 | 
			
		||||
			// OVAL, gost(Debian Security Tracker) does not support Package for Raspbian, so skip it.
 | 
			
		||||
			if r.Family == constant.Raspbian {
 | 
			
		||||
				r = r.RemoveRaspbianPackFromResult()
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// OVAL
 | 
			
		||||
			if err := detectPkgsCvesWithOval(ovalCnf, r, logOpts); err != nil {
 | 
			
		||||
				return xerrors.Errorf("Failed to detect CVE with OVAL: %w", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// gost
 | 
			
		||||
			if err := detectPkgsCvesWithGost(gostCnf, r, logOpts); err != nil {
 | 
			
		||||
				return xerrors.Errorf("Failed to detect CVE with gost: %w", err)
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			logging.Log.Infof("Number of packages is 0. Skip OVAL and gost detection")
 | 
			
		||||
	if isPkgCvesDetactable(r) {
 | 
			
		||||
		// OVAL, gost(Debian Security Tracker) does not support Package for Raspbian, so skip it.
 | 
			
		||||
		if r.Family == constant.Raspbian {
 | 
			
		||||
			r = r.RemoveRaspbianPackFromResult()
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// OVAL
 | 
			
		||||
		if err := detectPkgsCvesWithOval(ovalCnf, r, logOpts); err != nil {
 | 
			
		||||
			return xerrors.Errorf("Failed to detect CVE with OVAL: %w", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// gost
 | 
			
		||||
		if err := detectPkgsCvesWithGost(gostCnf, r, logOpts); err != nil {
 | 
			
		||||
			return xerrors.Errorf("Failed to detect CVE with gost: %w", err)
 | 
			
		||||
		}
 | 
			
		||||
	} else if reuseScannedCves(r) {
 | 
			
		||||
		logging.Log.Infof("r.Release is empty. Use CVEs as it as.")
 | 
			
		||||
	} else if r.Family == constant.ServerTypePseudo {
 | 
			
		||||
		logging.Log.Infof("pseudo type. Skip OVAL and gost detection")
 | 
			
		||||
	} else {
 | 
			
		||||
		logging.Log.Infof("r.Release is empty. detect as pseudo type. Skip OVAL and gost detection")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i, v := range r.ScannedCves {
 | 
			
		||||
@@ -265,6 +255,31 @@ func DetectPkgCves(r *models.ScanResult, ovalCnf config.GovalDictConf, gostCnf c
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// isPkgCvesDetactable checks whether CVEs is detactable with gost and oval from the result
 | 
			
		||||
func isPkgCvesDetactable(r *models.ScanResult) bool {
 | 
			
		||||
	if r.Release == "" {
 | 
			
		||||
		logging.Log.Infof("r.Release is empty. Skip OVAL and gost detection")
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if r.ScannedBy == "trivy" {
 | 
			
		||||
		logging.Log.Infof("r.ScannedBy is trivy. Skip OVAL and gost detection")
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch r.Family {
 | 
			
		||||
	case constant.FreeBSD, constant.ServerTypePseudo:
 | 
			
		||||
		logging.Log.Infof("%s type. Skip OVAL and gost detection", r.Family)
 | 
			
		||||
		return false
 | 
			
		||||
	default:
 | 
			
		||||
		if len(r.Packages)+len(r.SrcPackages) == 0 {
 | 
			
		||||
			logging.Log.Infof("Number of packages is 0. Skip OVAL and gost detection")
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DetectGitHubCves fetches CVEs from GitHub Security Alerts
 | 
			
		||||
func DetectGitHubCves(r *models.ScanResult, githubConfs map[string]config.GitHubConf) error {
 | 
			
		||||
	if len(githubConfs) == 0 {
 | 
			
		||||
 
 | 
			
		||||
@@ -26,12 +26,7 @@ func reuseScannedCves(r *models.ScanResult) bool {
 | 
			
		||||
	case constant.FreeBSD, constant.Raspbian:
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	return isTrivyResult(r)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isTrivyResult(r *models.ScanResult) bool {
 | 
			
		||||
	_, ok := r.Optional["trivy-target"]
 | 
			
		||||
	return ok
 | 
			
		||||
	return r.ScannedBy == "trivy"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func needToRefreshCve(r models.ScanResult) bool {
 | 
			
		||||
@@ -130,7 +125,7 @@ func getPlusDiffCves(previous, current models.ScanResult) models.VulnInfos {
 | 
			
		||||
		previousCveIDsSet[previousVulnInfo.CveID] = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	new := models.VulnInfos{}
 | 
			
		||||
	newer := models.VulnInfos{}
 | 
			
		||||
	updated := models.VulnInfos{}
 | 
			
		||||
	for _, v := range current.ScannedCves {
 | 
			
		||||
		if previousCveIDsSet[v.CveID] {
 | 
			
		||||
@@ -150,17 +145,17 @@ func getPlusDiffCves(previous, current models.ScanResult) models.VulnInfos {
 | 
			
		||||
				logging.Log.Debugf("same: %s", v.CveID)
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			logging.Log.Debugf("new: %s", v.CveID)
 | 
			
		||||
			logging.Log.Debugf("newer: %s", v.CveID)
 | 
			
		||||
			v.DiffStatus = models.DiffPlus
 | 
			
		||||
			new[v.CveID] = v
 | 
			
		||||
			newer[v.CveID] = v
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(updated) == 0 && len(new) == 0 {
 | 
			
		||||
	if len(updated) == 0 && len(newer) == 0 {
 | 
			
		||||
		logging.Log.Infof("%s: There are %d vulnerabilities, but no difference between current result and previous one.", current.FormatServerName(), len(current.ScannedCves))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for cveID, vuln := range new {
 | 
			
		||||
	for cveID, vuln := range newer {
 | 
			
		||||
		updated[cveID] = vuln
 | 
			
		||||
	}
 | 
			
		||||
	return updated
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										81
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										81
									
								
								go.mod
									
									
									
									
									
								
							@@ -1,20 +1,20 @@
 | 
			
		||||
module github.com/future-architect/vuls
 | 
			
		||||
 | 
			
		||||
go 1.17
 | 
			
		||||
go 1.18
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/Azure/azure-sdk-for-go v62.0.0+incompatible
 | 
			
		||||
	github.com/BurntSushi/toml v1.0.0
 | 
			
		||||
	github.com/Azure/azure-sdk-for-go v63.0.0+incompatible
 | 
			
		||||
	github.com/BurntSushi/toml v1.1.0
 | 
			
		||||
	github.com/Ullaakut/nmap/v2 v2.1.2-0.20210406060955-59a52fe80a4f
 | 
			
		||||
	github.com/VividCortex/ewma v1.2.0 // indirect
 | 
			
		||||
	github.com/aquasecurity/fanal v0.0.0-20220303080309-254063f95ea0
 | 
			
		||||
	github.com/aquasecurity/go-dep-parser v0.0.0-20220302151315-ff6d77c26988
 | 
			
		||||
	github.com/aquasecurity/trivy v0.24.2
 | 
			
		||||
	github.com/aquasecurity/trivy-db v0.0.0-20220130223604-df65ebde46f4
 | 
			
		||||
	github.com/aquasecurity/fanal v0.0.0-20220426115253-1d75fc0c7219
 | 
			
		||||
	github.com/aquasecurity/go-dep-parser v0.0.0-20220422134844-880747206031
 | 
			
		||||
	github.com/aquasecurity/trivy v0.27.1
 | 
			
		||||
	github.com/aquasecurity/trivy-db v0.0.0-20220327074450-74195d9604b2
 | 
			
		||||
	github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
 | 
			
		||||
	github.com/aws/aws-sdk-go v1.43.8
 | 
			
		||||
	github.com/aws/aws-sdk-go v1.43.31
 | 
			
		||||
	github.com/boltdb/bolt v1.3.1
 | 
			
		||||
	github.com/briandowns/spinner v1.16.0 // indirect
 | 
			
		||||
	github.com/briandowns/spinner v1.18.1 // indirect
 | 
			
		||||
	github.com/cenkalti/backoff v2.2.1+incompatible
 | 
			
		||||
	github.com/d4l3k/messagediff v1.2.2-0.20190829033028-7e0a312ae40b
 | 
			
		||||
	github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21
 | 
			
		||||
@@ -45,22 +45,24 @@ require (
 | 
			
		||||
	github.com/vulsio/go-exploitdb v0.4.2
 | 
			
		||||
	github.com/vulsio/go-kev v0.1.1-0.20220118062020-5f69b364106f
 | 
			
		||||
	github.com/vulsio/go-msfdb v0.2.1-0.20211028071756-4a9759bd9f14
 | 
			
		||||
	github.com/vulsio/gost v0.4.1-0.20211028071837-7ad032a6ffa8
 | 
			
		||||
	github.com/vulsio/goval-dictionary v0.7.1-0.20220215081041-a472884d0afa
 | 
			
		||||
	golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
 | 
			
		||||
	github.com/vulsio/gost v0.4.1
 | 
			
		||||
	github.com/vulsio/goval-dictionary v0.7.3
 | 
			
		||||
	golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5
 | 
			
		||||
	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
 | 
			
		||||
	golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
 | 
			
		||||
	golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f
 | 
			
		||||
	gopkg.in/ini.v1 v1.66.4 // indirect
 | 
			
		||||
	gorm.io/driver/mysql v1.3.2 // indirect
 | 
			
		||||
	gorm.io/driver/postgres v1.3.1 // indirect
 | 
			
		||||
	gorm.io/driver/sqlite v1.3.1 // indirect
 | 
			
		||||
	gorm.io/driver/mysql v1.3.3 // indirect
 | 
			
		||||
	gorm.io/driver/postgres v1.3.5 // indirect
 | 
			
		||||
	gorm.io/driver/sqlite v1.3.2 // indirect
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	cloud.google.com/go v0.99.0 // indirect
 | 
			
		||||
	cloud.google.com/go v0.100.2 // indirect
 | 
			
		||||
	cloud.google.com/go/compute v1.5.0 // indirect
 | 
			
		||||
	cloud.google.com/go/iam v0.3.0 // indirect
 | 
			
		||||
	cloud.google.com/go/storage v1.14.0 // indirect
 | 
			
		||||
	github.com/Azure/go-autorest v14.2.0+incompatible // indirect
 | 
			
		||||
	github.com/Azure/go-autorest/autorest v0.11.24 // indirect
 | 
			
		||||
	github.com/Azure/go-autorest/autorest v0.11.25 // indirect
 | 
			
		||||
	github.com/Azure/go-autorest/autorest/adal v0.9.18 // indirect
 | 
			
		||||
	github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
 | 
			
		||||
	github.com/Azure/go-autorest/autorest/to v0.3.0 // indirect
 | 
			
		||||
@@ -80,10 +82,10 @@ require (
 | 
			
		||||
	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
 | 
			
		||||
	github.com/docker/cli v20.10.12+incompatible // indirect
 | 
			
		||||
	github.com/docker/distribution v2.7.1+incompatible // indirect
 | 
			
		||||
	github.com/docker/docker v20.10.12+incompatible // indirect
 | 
			
		||||
	github.com/docker/docker v20.10.14+incompatible // indirect
 | 
			
		||||
	github.com/docker/docker-credential-helpers v0.6.4 // indirect
 | 
			
		||||
	github.com/fatih/color v1.13.0 // indirect
 | 
			
		||||
	github.com/fsnotify/fsnotify v1.5.1 // indirect
 | 
			
		||||
	github.com/fsnotify/fsnotify v1.5.4 // indirect
 | 
			
		||||
	github.com/go-redis/redis/v8 v8.11.5 // indirect
 | 
			
		||||
	github.com/go-sql-driver/mysql v1.6.0 // indirect
 | 
			
		||||
	github.com/go-stack/stack v1.8.1 // indirect
 | 
			
		||||
@@ -92,26 +94,26 @@ require (
 | 
			
		||||
	github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
 | 
			
		||||
	github.com/golang/protobuf v1.5.2 // indirect
 | 
			
		||||
	github.com/google/go-containerregistry v0.8.0 // indirect
 | 
			
		||||
	github.com/googleapis/gax-go/v2 v2.1.1 // indirect
 | 
			
		||||
	github.com/googleapis/gax-go/v2 v2.3.0 // indirect
 | 
			
		||||
	github.com/gorilla/websocket v1.4.2 // indirect
 | 
			
		||||
	github.com/grokify/html-strip-tags-go v0.0.1 // indirect
 | 
			
		||||
	github.com/hashicorp/errwrap v1.1.0 // indirect
 | 
			
		||||
	github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
 | 
			
		||||
	github.com/hashicorp/go-getter v1.5.11 // indirect
 | 
			
		||||
	github.com/hashicorp/go-multierror v1.1.1 // indirect
 | 
			
		||||
	github.com/hashicorp/go-retryablehttp v0.7.0 // indirect
 | 
			
		||||
	github.com/hashicorp/go-retryablehttp v0.7.1 // indirect
 | 
			
		||||
	github.com/hashicorp/go-safetemp v1.0.0 // indirect
 | 
			
		||||
	github.com/hashicorp/hcl v1.0.0 // indirect
 | 
			
		||||
	github.com/inconshreveable/log15 v0.0.0-20201112154412-8562bdadbbac // indirect
 | 
			
		||||
	github.com/inconshreveable/mousetrap v1.0.0 // indirect
 | 
			
		||||
	github.com/jackc/chunkreader/v2 v2.0.1 // indirect
 | 
			
		||||
	github.com/jackc/pgconn v1.11.0 // indirect
 | 
			
		||||
	github.com/jackc/pgconn v1.12.0 // indirect
 | 
			
		||||
	github.com/jackc/pgio v1.0.0 // indirect
 | 
			
		||||
	github.com/jackc/pgpassfile v1.0.0 // indirect
 | 
			
		||||
	github.com/jackc/pgproto3/v2 v2.2.0 // indirect
 | 
			
		||||
	github.com/jackc/pgproto3/v2 v2.3.0 // indirect
 | 
			
		||||
	github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
 | 
			
		||||
	github.com/jackc/pgtype v1.10.0 // indirect
 | 
			
		||||
	github.com/jackc/pgx/v4 v4.15.0 // indirect
 | 
			
		||||
	github.com/jackc/pgtype v1.11.0 // indirect
 | 
			
		||||
	github.com/jackc/pgx/v4 v4.16.0 // indirect
 | 
			
		||||
	github.com/jinzhu/inflection v1.0.0 // indirect
 | 
			
		||||
	github.com/jinzhu/now v1.1.5 // indirect
 | 
			
		||||
	github.com/jmespath/go-jmespath v0.4.0 // indirect
 | 
			
		||||
@@ -122,10 +124,11 @@ require (
 | 
			
		||||
	github.com/mattn/go-isatty v0.0.14 // indirect
 | 
			
		||||
	github.com/mattn/go-sqlite3 v1.14.12 // indirect
 | 
			
		||||
	github.com/mitchellh/go-testing-interface v1.0.0 // indirect
 | 
			
		||||
	github.com/mitchellh/mapstructure v1.4.3 // indirect
 | 
			
		||||
	github.com/mitchellh/mapstructure v1.5.0 // indirect
 | 
			
		||||
	github.com/opencontainers/go-digest v1.0.0 // indirect
 | 
			
		||||
	github.com/opencontainers/image-spec v1.0.2 // indirect
 | 
			
		||||
	github.com/pelletier/go-toml v1.9.4 // indirect
 | 
			
		||||
	github.com/pelletier/go-toml v1.9.5 // indirect
 | 
			
		||||
	github.com/pelletier/go-toml/v2 v2.0.0-beta.8 // indirect
 | 
			
		||||
	github.com/pkg/errors v0.9.1 // indirect
 | 
			
		||||
	github.com/pmezard/go-difflib v1.0.0 // indirect
 | 
			
		||||
	github.com/rivo/uniseg v0.2.0 // indirect
 | 
			
		||||
@@ -133,9 +136,9 @@ require (
 | 
			
		||||
	github.com/spf13/cast v1.4.1 // indirect
 | 
			
		||||
	github.com/spf13/jwalterweatherman v1.1.0 // indirect
 | 
			
		||||
	github.com/spf13/pflag v1.0.5 // indirect
 | 
			
		||||
	github.com/spf13/viper v1.10.1 // indirect
 | 
			
		||||
	github.com/spf13/viper v1.11.0 // indirect
 | 
			
		||||
	github.com/stretchr/objx v0.3.0 // indirect
 | 
			
		||||
	github.com/stretchr/testify v1.7.0 // indirect
 | 
			
		||||
	github.com/stretchr/testify v1.7.1 // indirect
 | 
			
		||||
	github.com/subosito/gotenv v1.2.0 // indirect
 | 
			
		||||
	github.com/ulikunitz/xz v0.5.10 // indirect
 | 
			
		||||
	go.etcd.io/bbolt v1.3.6 // indirect
 | 
			
		||||
@@ -144,19 +147,21 @@ require (
 | 
			
		||||
	go.uber.org/goleak v1.1.12 // indirect
 | 
			
		||||
	go.uber.org/multierr v1.6.0 // indirect
 | 
			
		||||
	go.uber.org/zap v1.21.0 // indirect
 | 
			
		||||
	golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064 // indirect
 | 
			
		||||
	golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
 | 
			
		||||
	golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 // indirect
 | 
			
		||||
	golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect
 | 
			
		||||
	golang.org/x/exp v0.0.0-20220407100705-7b9b53b0aca4 // indirect
 | 
			
		||||
	golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57 // indirect
 | 
			
		||||
	golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 // indirect
 | 
			
		||||
	golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 // indirect
 | 
			
		||||
	golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
 | 
			
		||||
	golang.org/x/text v0.3.7 // indirect
 | 
			
		||||
	google.golang.org/api v0.63.0 // indirect
 | 
			
		||||
	google.golang.org/api v0.74.0 // indirect
 | 
			
		||||
	google.golang.org/appengine v1.6.7 // indirect
 | 
			
		||||
	google.golang.org/genproto v0.0.0-20220204002441-d6cc3cc0770e // indirect
 | 
			
		||||
	google.golang.org/grpc v1.44.0 // indirect
 | 
			
		||||
	google.golang.org/protobuf v1.27.1 // indirect
 | 
			
		||||
	google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac // indirect
 | 
			
		||||
	google.golang.org/grpc v1.45.0 // indirect
 | 
			
		||||
	google.golang.org/protobuf v1.28.0 // indirect
 | 
			
		||||
	gopkg.in/yaml.v2 v2.4.0 // indirect
 | 
			
		||||
	gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
 | 
			
		||||
	gorm.io/gorm v1.23.3 // indirect
 | 
			
		||||
	gorm.io/gorm v1.23.5 // indirect
 | 
			
		||||
	k8s.io/utils v0.0.0-20201110183641-67b214c5f920 // indirect
 | 
			
		||||
	moul.io/http2curl v1.0.0 // indirect
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -54,7 +54,7 @@ func FillCVEsWithRedHat(r *models.ScanResult, cnf config.GostConf, o logging.Log
 | 
			
		||||
	return client.fillCvesWithRedHatAPI(r)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewClient make Client by family
 | 
			
		||||
// NewGostClient make Client by family
 | 
			
		||||
func NewGostClient(cnf config.GostConf, family string, o logging.LogOpts) (Client, error) {
 | 
			
		||||
	if err := gostlog.SetLogger(o.LogToFile, o.LogDir, o.Debug, o.LogJSON); err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("Failed to set gost logger. err: %w", err)
 | 
			
		||||
 
 | 
			
		||||
@@ -25,9 +25,12 @@ func (ubu Ubuntu) supported(version string) bool {
 | 
			
		||||
		"1404": "trusty",
 | 
			
		||||
		"1604": "xenial",
 | 
			
		||||
		"1804": "bionic",
 | 
			
		||||
		"1910": "eoan",
 | 
			
		||||
		"2004": "focal",
 | 
			
		||||
		"2010": "groovy",
 | 
			
		||||
		"2104": "hirsute",
 | 
			
		||||
		"2110": "impish",
 | 
			
		||||
		"2204": "jammy",
 | 
			
		||||
	}[version]
 | 
			
		||||
	return ok
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 Submodule integration updated: fa8df1dd6c...d97bf53114
									
								
							@@ -3,13 +3,14 @@ package models
 | 
			
		||||
import (
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
 | 
			
		||||
	ftypes "github.com/aquasecurity/fanal/types"
 | 
			
		||||
	"github.com/aquasecurity/trivy-db/pkg/db"
 | 
			
		||||
	trivyDBTypes "github.com/aquasecurity/trivy-db/pkg/types"
 | 
			
		||||
	"github.com/aquasecurity/trivy/pkg/detector/library"
 | 
			
		||||
	"github.com/future-architect/vuls/logging"
 | 
			
		||||
 | 
			
		||||
	"github.com/aquasecurity/trivy/pkg/types"
 | 
			
		||||
	"golang.org/x/xerrors"
 | 
			
		||||
 | 
			
		||||
	"github.com/future-architect/vuls/logging"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// LibraryScanners is an array of LibraryScanner
 | 
			
		||||
@@ -132,32 +133,53 @@ func getCveContents(cveID string, vul trivyDBTypes.Vulnerability) (contents map[
 | 
			
		||||
 | 
			
		||||
// LibraryMap is filename and library type
 | 
			
		||||
var LibraryMap = map[string]string{
 | 
			
		||||
	"package-lock.json":  "node",
 | 
			
		||||
	"yarn.lock":          "node",
 | 
			
		||||
	"Gemfile.lock":       "ruby",
 | 
			
		||||
	"Cargo.lock":         "rust",
 | 
			
		||||
	"composer.lock":      "php",
 | 
			
		||||
	"requirements.txt":   "python",
 | 
			
		||||
	"Pipfile.lock":       "python",
 | 
			
		||||
	"poetry.lock":        "python",
 | 
			
		||||
	"packages.lock.json": ".net",
 | 
			
		||||
	"packages.config":    ".net",
 | 
			
		||||
	"go.sum":             "gomod",
 | 
			
		||||
	"pom.xml":            "java",
 | 
			
		||||
	"*.jar":              "java",
 | 
			
		||||
	"*.war":              "java",
 | 
			
		||||
	"*.ear":              "java",
 | 
			
		||||
	"*.par":              "java",
 | 
			
		||||
	ftypes.NpmPkgLock:      "node",
 | 
			
		||||
	ftypes.YarnLock:        "node",
 | 
			
		||||
	ftypes.GemfileLock:     "ruby",
 | 
			
		||||
	ftypes.CargoLock:       "rust",
 | 
			
		||||
	ftypes.ComposerLock:    "php",
 | 
			
		||||
	ftypes.PipRequirements: "python",
 | 
			
		||||
	ftypes.PipfileLock:     "python",
 | 
			
		||||
	ftypes.PoetryLock:      "python",
 | 
			
		||||
	ftypes.NuGetPkgsLock:   ".net",
 | 
			
		||||
	ftypes.NuGetPkgsConfig: ".net",
 | 
			
		||||
	ftypes.GoMod:           "gomod",
 | 
			
		||||
	ftypes.GoSum:           "gomod",
 | 
			
		||||
	ftypes.MavenPom:        "java",
 | 
			
		||||
	"*.jar":                "java",
 | 
			
		||||
	"*.war":                "java",
 | 
			
		||||
	"*.ear":                "java",
 | 
			
		||||
	"*.par":                "java",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetLibraryKey returns target library key
 | 
			
		||||
func (s LibraryScanner) GetLibraryKey() string {
 | 
			
		||||
	fileName := filepath.Base(s.LockfilePath)
 | 
			
		||||
	switch s.Type {
 | 
			
		||||
	case "jar", "war", "ear", "par":
 | 
			
		||||
	case ftypes.Bundler, ftypes.GemSpec:
 | 
			
		||||
		return "ruby"
 | 
			
		||||
	case ftypes.Cargo:
 | 
			
		||||
		return "rust"
 | 
			
		||||
	case ftypes.Composer:
 | 
			
		||||
		return "php"
 | 
			
		||||
	case ftypes.GoBinary, ftypes.GoModule:
 | 
			
		||||
		return "gomod"
 | 
			
		||||
	case ftypes.Jar, ftypes.Pom:
 | 
			
		||||
		return "java"
 | 
			
		||||
	case ftypes.Npm, ftypes.Yarn, ftypes.NodePkg, ftypes.JavaScript:
 | 
			
		||||
		return "node"
 | 
			
		||||
	case ftypes.NuGet:
 | 
			
		||||
		return ".net"
 | 
			
		||||
	case ftypes.Pipenv, ftypes.Poetry, ftypes.Pip, ftypes.PythonPkg:
 | 
			
		||||
		return "python"
 | 
			
		||||
	default:
 | 
			
		||||
		filename := filepath.Base(s.LockfilePath)
 | 
			
		||||
		switch filepath.Ext(filename) {
 | 
			
		||||
		case ".jar", ".war", ".ear", ".par":
 | 
			
		||||
			return "java"
 | 
			
		||||
		default:
 | 
			
		||||
			return LibraryMap[filename]
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return LibraryMap[fileName]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LibraryFixedIn has library fixed information
 | 
			
		||||
 
 | 
			
		||||
@@ -395,6 +395,35 @@ func (o Ubuntu) FillWithOval(r *models.ScanResult) (nCVEs int, err error) {
 | 
			
		||||
			"linux-virtual",
 | 
			
		||||
		}
 | 
			
		||||
		return o.fillWithOval(r, kernelNamesInOval)
 | 
			
		||||
	case "22":
 | 
			
		||||
		kernelNamesInOval := []string{
 | 
			
		||||
			"linux-aws",
 | 
			
		||||
			"linux-azure",
 | 
			
		||||
			"linux-gcp",
 | 
			
		||||
			"linux-generic",
 | 
			
		||||
			"linux-gke",
 | 
			
		||||
			"linux-header-aws",
 | 
			
		||||
			"linux-header-azure",
 | 
			
		||||
			"linux-header-gcp",
 | 
			
		||||
			"linux-header-generic",
 | 
			
		||||
			"linux-header-gke",
 | 
			
		||||
			"linux-header-oracle",
 | 
			
		||||
			"linux-image-aws",
 | 
			
		||||
			"linux-image-azure",
 | 
			
		||||
			"linux-image-gcp",
 | 
			
		||||
			"linux-image-generic",
 | 
			
		||||
			"linux-image-gke",
 | 
			
		||||
			"linux-image-oracle",
 | 
			
		||||
			"linux-oracle",
 | 
			
		||||
			"linux-tools-aws",
 | 
			
		||||
			"linux-tools-azure",
 | 
			
		||||
			"linux-tools-common",
 | 
			
		||||
			"linux-tools-gcp",
 | 
			
		||||
			"linux-tools-generic",
 | 
			
		||||
			"linux-tools-gke",
 | 
			
		||||
			"linux-tools-oracle",
 | 
			
		||||
		}
 | 
			
		||||
		return o.fillWithOval(r, kernelNamesInOval)
 | 
			
		||||
	}
 | 
			
		||||
	return 0, fmt.Errorf("Ubuntu %s is not support for now", r.Release)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@ func NewPseudo(family string) Pseudo {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FillWithOval is a mock function for operating systems that do not use OVAL
 | 
			
		||||
func (pse Pseudo) FillWithOval(_ *models.ScanResult) (int, error) {
 | 
			
		||||
	return 0, nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -623,7 +623,7 @@ func getPlusDiffCves(previous, current models.ScanResult) models.VulnInfos {
 | 
			
		||||
		previousCveIDsSet[previousVulnInfo.CveID] = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	new := models.VulnInfos{}
 | 
			
		||||
	newer := models.VulnInfos{}
 | 
			
		||||
	updated := models.VulnInfos{}
 | 
			
		||||
	for _, v := range current.ScannedCves {
 | 
			
		||||
		if previousCveIDsSet[v.CveID] {
 | 
			
		||||
@@ -643,17 +643,17 @@ func getPlusDiffCves(previous, current models.ScanResult) models.VulnInfos {
 | 
			
		||||
				logging.Log.Debugf("same: %s", v.CveID)
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			logging.Log.Debugf("new: %s", v.CveID)
 | 
			
		||||
			logging.Log.Debugf("newer: %s", v.CveID)
 | 
			
		||||
			v.DiffStatus = models.DiffPlus
 | 
			
		||||
			new[v.CveID] = v
 | 
			
		||||
			newer[v.CveID] = v
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(updated) == 0 && len(new) == 0 {
 | 
			
		||||
	if len(updated) == 0 && len(newer) == 0 {
 | 
			
		||||
		logging.Log.Infof("%s: There are %d vulnerabilities, but no difference between current result and previous one.", current.FormatServerName(), len(current.ScannedCves))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for cveID, vuln := range new {
 | 
			
		||||
	for cveID, vuln := range newer {
 | 
			
		||||
		updated[cveID] = vuln
 | 
			
		||||
	}
 | 
			
		||||
	return updated
 | 
			
		||||
 
 | 
			
		||||
@@ -19,8 +19,8 @@ func TestMain(m *testing.M) {
 | 
			
		||||
 | 
			
		||||
func TestIsCveInfoUpdated(t *testing.T) {
 | 
			
		||||
	f := "2006-01-02"
 | 
			
		||||
	old, _ := time.Parse(f, "2015-12-15")
 | 
			
		||||
	new, _ := time.Parse(f, "2015-12-16")
 | 
			
		||||
	base, _ := time.Parse(f, "2015-12-15")
 | 
			
		||||
	newer, _ := time.Parse(f, "2015-12-16")
 | 
			
		||||
 | 
			
		||||
	type In struct {
 | 
			
		||||
		cveID string
 | 
			
		||||
@@ -78,7 +78,7 @@ func TestIsCveInfoUpdated(t *testing.T) {
 | 
			
		||||
								models.CveContent{
 | 
			
		||||
									Type:         models.Jvn,
 | 
			
		||||
									CveID:        "CVE-2017-0002",
 | 
			
		||||
									LastModified: old,
 | 
			
		||||
									LastModified: base,
 | 
			
		||||
								},
 | 
			
		||||
							),
 | 
			
		||||
						},
 | 
			
		||||
@@ -92,7 +92,7 @@ func TestIsCveInfoUpdated(t *testing.T) {
 | 
			
		||||
								models.CveContent{
 | 
			
		||||
									Type:         models.Jvn,
 | 
			
		||||
									CveID:        "CVE-2017-0002",
 | 
			
		||||
									LastModified: old,
 | 
			
		||||
									LastModified: base,
 | 
			
		||||
								},
 | 
			
		||||
							),
 | 
			
		||||
						},
 | 
			
		||||
@@ -114,7 +114,7 @@ func TestIsCveInfoUpdated(t *testing.T) {
 | 
			
		||||
								models.CveContent{
 | 
			
		||||
									Type:         models.Nvd,
 | 
			
		||||
									CveID:        "CVE-2017-0002",
 | 
			
		||||
									LastModified: new,
 | 
			
		||||
									LastModified: newer,
 | 
			
		||||
								},
 | 
			
		||||
							),
 | 
			
		||||
						},
 | 
			
		||||
@@ -129,7 +129,7 @@ func TestIsCveInfoUpdated(t *testing.T) {
 | 
			
		||||
								models.CveContent{
 | 
			
		||||
									Type:         models.Nvd,
 | 
			
		||||
									CveID:        "CVE-2017-0002",
 | 
			
		||||
									LastModified: old,
 | 
			
		||||
									LastModified: base,
 | 
			
		||||
								},
 | 
			
		||||
							),
 | 
			
		||||
						},
 | 
			
		||||
@@ -151,7 +151,7 @@ func TestIsCveInfoUpdated(t *testing.T) {
 | 
			
		||||
								models.CveContent{
 | 
			
		||||
									Type:         models.Nvd,
 | 
			
		||||
									CveID:        "CVE-2017-0002",
 | 
			
		||||
									LastModified: old,
 | 
			
		||||
									LastModified: base,
 | 
			
		||||
								},
 | 
			
		||||
							),
 | 
			
		||||
						},
 | 
			
		||||
 
 | 
			
		||||
@@ -686,6 +686,7 @@ func AnalyzeLibraries(ctx context.Context, libFilemap map[string]LibFile, isOffl
 | 
			
		||||
		analyzer.TypeJSON,
 | 
			
		||||
		analyzer.TypeDockerfile,
 | 
			
		||||
		analyzer.TypeHCL,
 | 
			
		||||
		analyzer.TypeSecret,
 | 
			
		||||
	}
 | 
			
		||||
	anal := analyzer.NewAnalyzerGroup(analyzer.GroupBuiltin, disabledAnalyzers)
 | 
			
		||||
 | 
			
		||||
@@ -701,6 +702,7 @@ func AnalyzeLibraries(ctx context.Context, libFilemap map[string]LibFile, isOffl
 | 
			
		||||
			path,
 | 
			
		||||
			&DummyFileInfo{size: int64(len(f.Contents)), filemode: f.Filemode},
 | 
			
		||||
			func() (dio.ReadSeekCloserAt, error) { return dio.NopCloser(bytes.NewReader(f.Contents)), nil },
 | 
			
		||||
			nil,
 | 
			
		||||
			analyzer.AnalysisOptions{Offline: isOffline},
 | 
			
		||||
		); err != nil {
 | 
			
		||||
			return nil, xerrors.Errorf("Failed to get libs. err: %w", err)
 | 
			
		||||
 
 | 
			
		||||
@@ -784,49 +784,49 @@ func (o *redhatBase) getOwnerPkgs(paths []string) (names []string, _ error) {
 | 
			
		||||
 | 
			
		||||
func (o *redhatBase) rpmQa() string {
 | 
			
		||||
	const old = `rpm -qa --queryformat "%{NAME} %{EPOCH} %{VERSION} %{RELEASE} %{ARCH}\n"`
 | 
			
		||||
	const new = `rpm -qa --queryformat "%{NAME} %{EPOCHNUM} %{VERSION} %{RELEASE} %{ARCH}\n"`
 | 
			
		||||
	const newer = `rpm -qa --queryformat "%{NAME} %{EPOCHNUM} %{VERSION} %{RELEASE} %{ARCH}\n"`
 | 
			
		||||
	switch o.Distro.Family {
 | 
			
		||||
	case constant.OpenSUSE:
 | 
			
		||||
		if o.Distro.Release == "tumbleweed" {
 | 
			
		||||
			return new
 | 
			
		||||
			return newer
 | 
			
		||||
		}
 | 
			
		||||
		return old
 | 
			
		||||
	case constant.OpenSUSELeap:
 | 
			
		||||
		return new
 | 
			
		||||
		return newer
 | 
			
		||||
	case constant.SUSEEnterpriseServer, constant.SUSEEnterpriseDesktop:
 | 
			
		||||
		if v, _ := o.Distro.MajorVersion(); v < 12 {
 | 
			
		||||
			return old
 | 
			
		||||
		}
 | 
			
		||||
		return new
 | 
			
		||||
		return newer
 | 
			
		||||
	default:
 | 
			
		||||
		if v, _ := o.Distro.MajorVersion(); v < 6 {
 | 
			
		||||
			return old
 | 
			
		||||
		}
 | 
			
		||||
		return new
 | 
			
		||||
		return newer
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *redhatBase) rpmQf() string {
 | 
			
		||||
	const old = `rpm -qf --queryformat "%{NAME} %{EPOCH} %{VERSION} %{RELEASE} %{ARCH}\n" `
 | 
			
		||||
	const new = `rpm -qf --queryformat "%{NAME} %{EPOCHNUM} %{VERSION} %{RELEASE} %{ARCH}\n" `
 | 
			
		||||
	const newer = `rpm -qf --queryformat "%{NAME} %{EPOCHNUM} %{VERSION} %{RELEASE} %{ARCH}\n" `
 | 
			
		||||
	switch o.Distro.Family {
 | 
			
		||||
	case constant.OpenSUSE:
 | 
			
		||||
		if o.Distro.Release == "tumbleweed" {
 | 
			
		||||
			return new
 | 
			
		||||
			return newer
 | 
			
		||||
		}
 | 
			
		||||
		return old
 | 
			
		||||
	case constant.OpenSUSELeap:
 | 
			
		||||
		return new
 | 
			
		||||
		return newer
 | 
			
		||||
	case constant.SUSEEnterpriseServer, constant.SUSEEnterpriseDesktop:
 | 
			
		||||
		if v, _ := o.Distro.MajorVersion(); v < 12 {
 | 
			
		||||
			return old
 | 
			
		||||
		}
 | 
			
		||||
		return new
 | 
			
		||||
		return newer
 | 
			
		||||
	default:
 | 
			
		||||
		if v, _ := o.Distro.MajorVersion(); v < 6 {
 | 
			
		||||
			return old
 | 
			
		||||
		}
 | 
			
		||||
		return new
 | 
			
		||||
		return newer
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -237,6 +237,8 @@ func ParseInstalledPkgs(distro config.Distro, kernel models.Kernel, pkgList stri
 | 
			
		||||
		osType = &amazon{redhatBase: redhatBase{base: base}}
 | 
			
		||||
	case constant.Fedora:
 | 
			
		||||
		osType = &fedora{redhatBase: redhatBase{base: base}}
 | 
			
		||||
	case constant.OpenSUSE, constant.OpenSUSELeap, constant.SUSEEnterpriseServer, constant.SUSEEnterpriseDesktop:
 | 
			
		||||
		osType = &suse{redhatBase: redhatBase{base: base}}
 | 
			
		||||
	default:
 | 
			
		||||
		return models.Packages{}, models.SrcPackages{}, xerrors.Errorf("Server mode for %s is not implemented yet", base.Distro.Family)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user