diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000..9db7326
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,14 @@
+blank_issues_enabled: false
+
+contact_links:
+ - name: Ask an question / advise on using cvemap
+ url: https://github.com/projectdiscovery/cvemap/discussions/categories/q-a
+ about: Ask a question or request support for using cvemap
+
+ - name: Share idea / feature to discuss for cvemap
+ url: https://github.com/projectdiscovery/cvemap/discussions/categories/ideas
+ about: Share idea / feature to discuss for cvemap
+
+ - name: Connect with PD Team (Discord)
+ url: https://discord.gg/projectdiscovery
+ about: Connect with PD Team for direct communication
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000..a44c78a
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,18 @@
+---
+name: Feature request
+about: Request feature to implement in this project
+labels: 'Type: Enhancement'
+---
+
+
+
+### Please describe your feature request:
+
+
+### Describe the use case of this feature:
+
diff --git a/.github/ISSUE_TEMPLATE/issue-report.md b/.github/ISSUE_TEMPLATE/issue-report.md
new file mode 100644
index 0000000..1cad67e
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/issue-report.md
@@ -0,0 +1,36 @@
+---
+name: Issue report
+about: Create a report to help us to improve the project
+labels: 'Type: Bug'
+
+---
+
+
+
+
+
+### cvemap version:
+
+
+
+
+### Current Behavior:
+
+
+### Expected Behavior:
+
+
+### Steps To Reproduce:
+
+
+
+### Anything else:
+
\ No newline at end of file
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..f9ecf8d
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,45 @@
+# To get started with Dependabot version updates, you'll need to specify which
+# package ecosystems to update and where the package manifests are located.
+# Please see the documentation for all configuration options:
+# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
+
+version: 2
+updates:
+
+ # Maintain dependencies for go modules
+ - package-ecosystem: "gomod"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ target-branch: "main"
+ commit-message:
+ prefix: "chore"
+ include: "scope"
+ labels:
+ - "Type: Maintenance"
+ allow:
+ - dependency-name: "github.com/projectdiscovery/*"
+
+# # Maintain dependencies for docker
+# - package-ecosystem: "docker"
+# directory: "/"
+# schedule:
+# interval: "weekly"
+# target-branch: "dev"
+# commit-message:
+# prefix: "chore"
+# include: "scope"
+# labels:
+# - "Type: Maintenance"
+#
+# # Maintain dependencies for GitHub Actions
+# - package-ecosystem: "github-actions"
+# directory: "/"
+# schedule:
+# interval: "weekly"
+# target-branch: "dev"
+# commit-message:
+# prefix: "chore"
+# include: "scope"
+# labels:
+# - "Type: Maintenance"
\ No newline at end of file
diff --git a/.github/release.yml b/.github/release.yml
new file mode 100644
index 0000000..596ba07
--- /dev/null
+++ b/.github/release.yml
@@ -0,0 +1,17 @@
+changelog:
+ exclude:
+ authors:
+ - dependabot
+ categories:
+ - title: 🎉 New Features
+ labels:
+ - "Type: Enhancement"
+ - title: 🐞 Bugs Fixes
+ labels:
+ - "Type: Bug"
+ - title: 🔨 Maintenance
+ labels:
+ - "Type: Maintenance"
+ - title: Other Changes
+ labels:
+ - "*"
\ No newline at end of file
diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml
new file mode 100644
index 0000000..8bd137d
--- /dev/null
+++ b/.github/workflows/build-test.yml
@@ -0,0 +1,63 @@
+name: 🔨 Build Test
+
+on:
+ pull_request:
+ paths:
+ - '**.go'
+ - '**.mod'
+ workflow_dispatch:
+
+jobs:
+ build:
+ name: Test Builds
+ runs-on: ${{ matrix.os }}
+ strategy:
+ matrix:
+ os: [ubuntu-latest, windows-latest, macOS-latest]
+ go-version: [1.21.x]
+ steps:
+ - name: Set up Go
+ uses: actions/setup-go@v4
+ with:
+ go-version: ${{ matrix.go-version }}
+
+ - name: Check out code
+ uses: actions/checkout@v3
+
+ - name: Build
+ run: go build .
+ working-directory: cmd/cvemap/
+
+ - name: Test
+ run: go test ./...
+ working-directory: .
+
+ - name: Integration Tests Linux, macOS
+ if: runner.os == 'Linux' || runner.os == 'macOS'
+ env:
+ GH_ACTION: true
+ run: bash run.sh
+ working-directory: cmd/integration-test/
+
+ - name: Integration Tests Windows
+ if: runner.os == 'Windows'
+ env:
+ GH_ACTION: true
+ MSYS_NO_PATHCONV: true
+ run: bash run.sh
+ working-directory: cmd/integration-test/
+
+ - name: Race Condition Tests
+ if: github.actor != 'dependabot[bot]'
+ run: go run -race . -id CVE-1999-0027
+ working-directory: cmd/cvemap/
+ env:
+ PDCP_API_KEY: "${{ secrets.PDCP_API_KEY }}"
+ PDCP_API_SERVER: https://api.projectdiscovery.io
+ DEBUG: true
+
+ # - name: Test Example Code
+ # run: go run .
+ # working-directory: examples/
+
+
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
new file mode 100644
index 0000000..9f533f8
--- /dev/null
+++ b/.github/workflows/codeql-analysis.yml
@@ -0,0 +1,38 @@
+name: 🚨 CodeQL Analysis
+
+on:
+ workflow_dispatch:
+ pull_request:
+ branches:
+ - dev
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: [ 'go' ]
+ # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v2
+ with:
+ languages: ${{ matrix.language }}
+
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@v2
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v2
\ No newline at end of file
diff --git a/.github/workflows/dep-auto-merge.yml b/.github/workflows/dep-auto-merge.yml
new file mode 100644
index 0000000..fc26472
--- /dev/null
+++ b/.github/workflows/dep-auto-merge.yml
@@ -0,0 +1,26 @@
+name: 🤖 dep auto merge
+
+on:
+ pull_request:
+ branches:
+ - main
+ workflow_dispatch:
+
+permissions:
+ pull-requests: write
+ issues: write
+ repository-projects: write
+
+jobs:
+ automerge:
+ runs-on: ubuntu-latest
+ if: github.actor == 'dependabot[bot]'
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ token: ${{ secrets.DEPENDABOT_PAT }}
+
+ - uses: ahmadnassri/action-dependabot-auto-merge@v2
+ with:
+ github-token: ${{ secrets.DEPENDABOT_PAT }}
+ target: all
\ No newline at end of file
diff --git a/.github/workflows/dockerhub-push.yml b/.github/workflows/dockerhub-push.yml
new file mode 100644
index 0000000..1e9f341
--- /dev/null
+++ b/.github/workflows/dockerhub-push.yml
@@ -0,0 +1,40 @@
+name: 🌥 Docker Push
+
+on:
+ workflow_run:
+ workflows: ["🎉 Release Binary"]
+ types:
+ - completed
+ workflow_dispatch:
+
+jobs:
+ docker:
+ runs-on: ubuntu-latest-16-cores
+ steps:
+ - name: Git Checkout
+ uses: actions/checkout@v3
+
+ - name: Get Github tag
+ id: meta
+ run: |
+ curl --silent "https://api.github.com/repos/projectdiscovery/cvemap/releases/latest" | jq -r .tag_name | xargs -I {} echo TAG={} >> $GITHUB_OUTPUT
+
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v2
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v2
+
+ - name: Login to DockerHub
+ uses: docker/login-action@v2
+ with:
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_TOKEN }}
+
+ - name: Build and push
+ uses: docker/build-push-action@v4
+ with:
+ context: .
+ platforms: linux/amd64,linux/arm64,linux/arm
+ push: true
+ tags: projectdiscovery/cvemap:latest,projectdiscovery/cvemap:${{ steps.meta.outputs.TAG }}
\ No newline at end of file
diff --git a/.github/workflows/lint-test.yml b/.github/workflows/lint-test.yml
new file mode 100644
index 0000000..57d31cf
--- /dev/null
+++ b/.github/workflows/lint-test.yml
@@ -0,0 +1,28 @@
+name: 🙏🏻 Lint Test
+
+on:
+ pull_request:
+ paths:
+ - '**.go'
+ - '**.mod'
+ workflow_dispatch:
+
+jobs:
+ lint:
+ name: Lint Test
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+
+ - name: "Set up Go"
+ uses: actions/setup-go@v4
+ with:
+ go-version: 1.21.x
+
+ - name: Run golangci-lint
+ uses: golangci/golangci-lint-action@v3.6.0
+ with:
+ version: latest
+ args: --timeout 5m
+ working-directory: .
\ No newline at end of file
diff --git a/.github/workflows/release-binary.yml b/.github/workflows/release-binary.yml
new file mode 100644
index 0000000..b17ae06
--- /dev/null
+++ b/.github/workflows/release-binary.yml
@@ -0,0 +1,32 @@
+name: 🎉 Release Binary
+on:
+ push:
+ tags:
+ - '*'
+ workflow_dispatch:
+
+jobs:
+ release:
+ runs-on: ubuntu-latest-16-cores
+ steps:
+ - name: "Check out code"
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+
+ - name: "Set up Go"
+ uses: actions/setup-go@v4
+ with:
+ go-version: 1.21.x
+
+ - name: "Create release on GitHub"
+ uses: goreleaser/goreleaser-action@v4
+ with:
+ args: "release --clean"
+ version: latest
+ workdir: .
+ env:
+ GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+ SLACK_WEBHOOK: "${{ secrets.RELEASE_SLACK_WEBHOOK }}"
+ DISCORD_WEBHOOK_ID: "${{ secrets.DISCORD_WEBHOOK_ID }}"
+ DISCORD_WEBHOOK_TOKEN: "${{ secrets.DISCORD_WEBHOOK_TOKEN }}"
\ No newline at end of file
diff --git a/.github/workflows/release-test.yml b/.github/workflows/release-test.yml
new file mode 100644
index 0000000..3cc2909
--- /dev/null
+++ b/.github/workflows/release-test.yml
@@ -0,0 +1,30 @@
+name: 🔨 Release Test
+
+on:
+ pull_request:
+ paths:
+ - '**.go'
+ - '**.mod'
+ - '**.yml'
+ workflow_dispatch:
+
+jobs:
+ release-test:
+ runs-on: ubuntu-latest-16-cores
+ steps:
+ - name: "Check out code"
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+
+ - name: Set up Go
+ uses: actions/setup-go@v4
+ with:
+ go-version: 1.21.x
+
+ - name: release test
+ uses: goreleaser/goreleaser-action@v4
+ with:
+ args: "release --clean --snapshot"
+ version: latest
+ workdir: .
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3b735ec
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,21 @@
+# If you prefer the allow list template instead of the deny list, see community template:
+# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
+#
+# Binaries for programs and plugins
+*.exe
+*.exe~
+*.dll
+*.so
+*.dylib
+
+# Test binary, built with `go test -c`
+*.test
+
+# Output of the go coverage tool, specifically when used with LiteIDE
+*.out
+
+# Dependency directories (remove the comment below to include it)
+# vendor/
+
+# Go workspace file
+go.work
diff --git a/.goreleaser.yml b/.goreleaser.yml
new file mode 100644
index 0000000..a5a7834
--- /dev/null
+++ b/.goreleaser.yml
@@ -0,0 +1,45 @@
+before:
+ hooks:
+ - go mod tidy
+
+builds:
+- env:
+ - CGO_ENABLED=0
+ goos:
+ - windows
+ - linux
+ - darwin
+ goarch:
+ - amd64
+ - 386
+ - arm
+ - arm64
+
+ ignore:
+ - goos: darwin
+ goarch: '386'
+ - goos: windows
+ goarch: 'arm'
+ - goos: windows
+ goarch: 'arm64'
+
+ binary: '{{ .ProjectName }}'
+ main: cmd/cvemap/main.go
+
+archives:
+- format: zip
+ name_template: '{{ .ProjectName }}_{{ .Version }}_{{ if eq .Os "darwin" }}macOS{{ else }}{{ .Os }}{{ end }}_{{ .Arch }}'
+
+checksum:
+ algorithm: sha256
+
+announce:
+ slack:
+ enabled: true
+ channel: '#release'
+ username: GoReleaser
+ message_template: 'New Release: {{ .ProjectName }} {{.Tag}} is published! Check it out at {{ .ReleaseURL }}'
+
+ discord:
+ enabled: true
+ message_template: '**New Release: {{ .ProjectName }} {{.Tag}}** is published! Check it out at {{ .ReleaseURL }}'
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..822f480
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 ProjectDiscovery
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..2d33510
--- /dev/null
+++ b/README.md
@@ -0,0 +1,153 @@
+
+
+**cvemap** is made with ❤️ by the [projectdiscovery](https://projectdiscovery.io) team and distributed under [MIT License](LICENSE).
+
+
+
\ No newline at end of file
diff --git a/cmd/cvemap/main.go b/cmd/cvemap/main.go
new file mode 100644
index 0000000..44f71ed
--- /dev/null
+++ b/cmd/cvemap/main.go
@@ -0,0 +1,8 @@
+package main
+
+import "github.com/projectdiscovery/cvemap/runner"
+
+func main() {
+ options := runner.ParseOptions()
+ runner.Run(*options)
+}
diff --git a/cmd/integration-test/main.go b/cmd/integration-test/main.go
new file mode 100644
index 0000000..61831a5
--- /dev/null
+++ b/cmd/integration-test/main.go
@@ -0,0 +1,62 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+
+ "github.com/logrusorgru/aurora"
+ "github.com/pkg/errors"
+ "github.com/projectdiscovery/cvemap/runner/testutils"
+)
+
+var (
+ xPDCPHeaderTestKey = "test-67291d9a-0aa6-49b1-b249-2b9d4b45bcea"
+ debug = os.Getenv("DEBUG") == "true"
+ success = aurora.Green("[✓]").String()
+ failed = aurora.Red("[✘]").String()
+ currentCvemapBinary = flag.String("current", "", "Current Branch Cvemap Binary")
+)
+
+func main() {
+ flag.Parse()
+ SetupMockServer()
+ os.Setenv("CVEMAP_API_URL", "http://localhost:8080/api/v1")
+ os.Setenv("PDCP_API_KEY", xPDCPHeaderTestKey)
+ if err := runIntegrationTests(); err != nil {
+ fmt.Println("Error running integration tests:", err)
+ }
+}
+
+var testCases = map[string]testutils.TestCase{
+ "Get By cve_id": &CveIDTestCase{},
+}
+
+type CveIDTestCase struct{}
+
+func (c *CveIDTestCase) Execute() error {
+ currentOutput, err := testutils.RunCvemapBinaryAndGetResults(*currentCvemapBinary, debug, []string{"-id", "CVE-1999-0027", "-j", "-silent"})
+ if err != nil {
+ return errors.Wrap(err, "could not run cvemap test")
+ }
+ if len(currentOutput) == 0 {
+ return errors.New("no output from cvemap")
+ }
+ if strings.Contains(strings.Join(currentOutput, ""), `"cve_id": "CVE-1999-0027"`) {
+ return nil
+ }
+ return errors.New("cve_id not found in output")
+}
+
+func runIntegrationTests() error {
+
+ for testName, testcase := range testCases {
+ if err := testcase.Execute(); err != nil {
+ fmt.Fprintf(os.Stderr, "%s Test \"%s\" failed: %s\n", failed, testName, err)
+ } else {
+ fmt.Printf("%s Test \"%s\" passed!\n", success, testName)
+ }
+ }
+ return nil
+}
diff --git a/cmd/integration-test/run.sh b/cmd/integration-test/run.sh
new file mode 100644
index 0000000..488deca
--- /dev/null
+++ b/cmd/integration-test/run.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+# reading os type from arguments
+CURRENT_OS=$1
+
+if [ "${CURRENT_OS}" == "windows-latest" ];then
+ extension=.exe
+fi
+
+echo "::group::Building integration-test binary"
+go build -o integration-test$extension
+echo "::endgroup::"
+
+echo "::group::Building cvemap binary from current branch"
+go build -o cvemap$extension ../cvemap
+echo "::endgroup::"
+
+
+echo 'Starting cvemap integration test'
+./integration-test$extension -current cvemap$extension
diff --git a/cmd/integration-test/server.go b/cmd/integration-test/server.go
new file mode 100644
index 0000000..f09c025
--- /dev/null
+++ b/cmd/integration-test/server.go
@@ -0,0 +1,80 @@
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "os"
+
+ "github.com/projectdiscovery/cvemap/runner"
+)
+
+var cveData *runner.CVEBulkData
+
+func SetupMockServer() {
+ var err error
+ // Load data from the JSON file
+ cveData, err = loadData("test-data.json")
+ if err != nil {
+ fmt.Println("Error loading data:", err)
+ return
+ }
+ // Setup HTTP server
+ http.HandleFunc("/api/v1/cves", RequireAPIKey(http.HandlerFunc(handleRequest)))
+
+ go func() {
+ // Start the server on port 8080
+ fmt.Println("Cvemap test server listening on 8080...")
+ if err := http.ListenAndServe(":8080", nil); err != nil {
+ fmt.Println("Error starting server:", err)
+ }
+ }()
+}
+
+// RequireAPIKey is a middleware that checks for the X-PDCP-Key header.
+func RequireAPIKey(next http.HandlerFunc) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ apiKey := r.Header.Get("X-PDCP-Key")
+ if apiKey != xPDCPHeaderTestKey {
+ http.Error(w, "Unauthorized: X-PDCP-Key header is required", http.StatusUnauthorized)
+ return
+ }
+ next(w, r)
+ }
+}
+
+// handleRequest handles HTTP requests.
+func handleRequest(w http.ResponseWriter, r *http.Request) {
+ // Handle the case where "cve_id" is a query parameter
+ cveID := r.URL.Query().Get("cve_id")
+ if cveID == "" {
+ http.NotFound(w, r)
+ }
+ for _, data := range cveData.Cves {
+ if data.CveID == cveID {
+ // Return the data corresponding to the given CVE ID
+ if err := json.NewEncoder(w).Encode(cveData); err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ }
+ return
+ }
+ }
+ http.NotFound(w, r)
+}
+
+// LoadData loads data from a JSON file into a slice of CVEData.
+func loadData(filename string) (*runner.CVEBulkData, error) {
+ file, err := os.Open(filename)
+ if err != nil {
+ return nil, err
+ }
+ defer file.Close()
+
+ var data runner.CVEBulkData
+ decoder := json.NewDecoder(file)
+ if err := decoder.Decode(&data); err != nil {
+ return nil, err
+ }
+
+ return &data, nil
+}
diff --git a/cmd/integration-test/test-data.json b/cmd/integration-test/test-data.json
new file mode 100644
index 0000000..056693b
--- /dev/null
+++ b/cmd/integration-test/test-data.json
@@ -0,0 +1,56 @@
+{
+ "result_count": 1,
+ "total_results": 1,
+ "cves": [
+ {
+ "cpe": {
+ "cpe": "cpe:2.3:o:sgi:irix:*:*:*:*:*:*:*:*",
+ "vendor": "sgi",
+ "product": "irix"
+ },
+ "epss": {
+ "epss_score": 0.00064,
+ "epss_percentile": 0.26181
+ },
+ "cve_id": "CVE-1999-0027",
+ "is_oss": false,
+ "is_poc": false,
+ "assignee": "cve@mitre.org",
+ "severity": "high",
+ "hackerone": {
+ "rank": 6320,
+ "count": 0
+ },
+ "is_remote": false,
+ "reference": [
+ "https://exchange.xforce.ibmcloud.com/vulnerabilities/CVE-1999-0027",
+ "https://github.com/Kuromesi/Py4CSKG"
+ ],
+ "cvss_score": 7.2,
+ "updated_at": "2022-08-17T07:15:08.580",
+ "weaknesses": [
+ {
+ "cwe_id": "CWE-119",
+ "cwe_name": "Improper Restriction of Operations within the Bounds of a Memory Buffer"
+ }
+ ],
+ "age_in_days": 9682,
+ "is_template": false,
+ "vuln_status": "modified",
+ "cvss_metrics": {
+ "cvss2": {
+ "score": 7.2,
+ "vector": "CVSS:2.0/AV:L/AC:L/Au:N/C:C/I:C/A:C",
+ "severity": "high"
+ }
+ },
+ "is_exploited": false,
+ "published_at": "1997-07-16T04:00:00.000",
+ "vulnerable_cpe": [
+ "cpe:2.3:o:sgi:irix:*:*:*:*:*:*:*:*"
+ ],
+ "cve_description": "root privileges via buffer overflow in eject command on SGI IRIX systems.",
+ "vendor_advisory": ""
+ }
+ ]
+}
\ No newline at end of file
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..2e044c9
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,104 @@
+module github.com/projectdiscovery/cvemap
+
+go 1.21
+
+require (
+ github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203
+ github.com/jedib0t/go-pretty/v6 v6.4.7
+ github.com/logrusorgru/aurora v2.0.3+incompatible
+ github.com/pkg/errors v0.9.1
+ github.com/projectdiscovery/goflags v0.1.36
+ github.com/projectdiscovery/gologger v1.1.12
+ github.com/projectdiscovery/utils v0.0.74
+)
+
+require (
+ aead.dev/minisign v0.2.0 // indirect
+ github.com/Masterminds/semver/v3 v3.2.1 // indirect
+ github.com/Mzack9999/gcache v0.0.0-20230410081825-519e28eab057 // indirect
+ github.com/Mzack9999/go-http-digest-auth-client v0.6.1-0.20220414142836-eb8883508809 // indirect
+ github.com/VividCortex/ewma v1.2.0 // indirect
+ github.com/akrylysov/pogreb v0.10.1 // indirect
+ github.com/alecthomas/chroma v0.10.0 // indirect
+ github.com/andybalholm/brotli v1.0.6 // indirect
+ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
+ github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
+ github.com/aymerick/douceur v0.2.0 // indirect
+ github.com/charmbracelet/glamour v0.6.0 // indirect
+ github.com/cheggaaa/pb/v3 v3.1.4 // indirect
+ github.com/cloudflare/circl v1.3.7 // indirect
+ github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 // indirect
+ github.com/denisbrodbeck/machineid v1.0.1 // indirect
+ github.com/dimchansky/utfbom v1.1.1 // indirect
+ github.com/dlclark/regexp2 v1.8.1 // indirect
+ github.com/docker/go-units v0.5.0 // indirect
+ github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
+ github.com/fatih/color v1.15.0 // indirect
+ github.com/gaukas/godicttls v0.0.4 // indirect
+ github.com/golang/protobuf v1.5.3 // indirect
+ github.com/golang/snappy v0.0.4 // indirect
+ github.com/google/go-github/v30 v30.1.0 // indirect
+ github.com/google/go-querystring v1.1.0 // indirect
+ github.com/gorilla/css v1.0.1 // indirect
+ github.com/json-iterator/go v1.1.12 // indirect
+ github.com/klauspost/compress v1.16.7 // indirect
+ github.com/klauspost/pgzip v1.2.5 // indirect
+ github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
+ github.com/mattn/go-colorable v0.1.13 // indirect
+ github.com/mattn/go-isatty v0.0.19 // indirect
+ github.com/mattn/go-runewidth v0.0.15 // indirect
+ github.com/mholt/archiver/v3 v3.5.1 // indirect
+ github.com/microcosm-cc/bluemonday v1.0.26 // indirect
+ github.com/miekg/dns v1.1.57 // indirect
+ github.com/minio/selfupdate v0.6.1-0.20230907112617-f11e74f84ca7 // indirect
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+ github.com/modern-go/reflect2 v1.0.2 // indirect
+ github.com/muesli/reflow v0.3.0 // indirect
+ github.com/muesli/termenv v0.15.1 // indirect
+ github.com/nwaples/rardecode v1.1.3 // indirect
+ github.com/olekukonko/tablewriter v0.0.5 // indirect
+ github.com/pierrec/lz4/v4 v4.1.2 // indirect
+ github.com/projectdiscovery/blackrock v0.0.1 // indirect
+ github.com/projectdiscovery/fastdialer v0.0.55 // indirect
+ github.com/projectdiscovery/hmap v0.0.35 // indirect
+ github.com/projectdiscovery/networkpolicy v0.0.7 // indirect
+ github.com/projectdiscovery/retryabledns v1.0.52 // indirect
+ github.com/projectdiscovery/retryablehttp-go v1.0.44 // indirect
+ github.com/quic-go/quic-go v0.37.7 // indirect
+ github.com/refraction-networking/utls v1.5.4 // indirect
+ github.com/rivo/uniseg v0.4.4 // indirect
+ github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect
+ github.com/syndtr/goleveldb v1.0.0 // indirect
+ github.com/tidwall/btree v1.4.3 // indirect
+ github.com/tidwall/buntdb v1.3.0 // indirect
+ github.com/tidwall/gjson v1.14.3 // indirect
+ github.com/tidwall/grect v0.1.4 // indirect
+ github.com/tidwall/match v1.1.1 // indirect
+ github.com/tidwall/pretty v1.2.0 // indirect
+ github.com/tidwall/rtred v0.1.2 // indirect
+ github.com/tidwall/tinyqueue v0.1.1 // indirect
+ github.com/ulikunitz/xz v0.5.11 // indirect
+ github.com/ulule/deepcopier v0.0.0-20200430083143-45decc6639b6 // indirect
+ github.com/weppos/publicsuffix-go v0.30.1-0.20230422193905-8fecedd899db // indirect
+ github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
+ github.com/yl2chen/cidranger v1.0.2 // indirect
+ github.com/yuin/goldmark v1.5.4 // indirect
+ github.com/yuin/goldmark-emoji v1.0.1 // indirect
+ github.com/zmap/rc2 v0.0.0-20190804163417-abaa70531248 // indirect
+ github.com/zmap/zcrypto v0.0.0-20230422215203-9a665e1e9968 // indirect
+ go.etcd.io/bbolt v1.3.7 // indirect
+ go.uber.org/multierr v1.11.0 // indirect
+ golang.org/x/crypto v0.18.0 // indirect
+ golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc // indirect
+ golang.org/x/mod v0.14.0 // indirect
+ golang.org/x/net v0.20.0 // indirect
+ golang.org/x/oauth2 v0.11.0 // indirect
+ golang.org/x/sys v0.16.0 // indirect
+ golang.org/x/term v0.16.0 // indirect
+ golang.org/x/text v0.14.0 // indirect
+ golang.org/x/tools v0.16.1 // indirect
+ google.golang.org/appengine v1.6.7 // indirect
+ google.golang.org/protobuf v1.31.0 // indirect
+ gopkg.in/djherbis/times.v1 v1.3.0 // indirect
+ gopkg.in/yaml.v3 v3.0.1 // indirect
+)
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..7c4ccd1
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,388 @@
+aead.dev/minisign v0.2.0 h1:kAWrq/hBRu4AARY6AlciO83xhNnW9UaC8YipS2uhLPk=
+aead.dev/minisign v0.2.0/go.mod h1:zdq6LdSd9TbuSxchxwhpA9zEb9YXcVGoE8JakuiGaIQ=
+cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
+github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
+github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
+github.com/Mzack9999/gcache v0.0.0-20230410081825-519e28eab057 h1:KFac3SiGbId8ub47e7kd2PLZeACxc1LkiiNoDOFRClE=
+github.com/Mzack9999/gcache v0.0.0-20230410081825-519e28eab057/go.mod h1:iLB2pivrPICvLOuROKmlqURtFIEsoJZaMidQfCG1+D4=
+github.com/Mzack9999/go-http-digest-auth-client v0.6.1-0.20220414142836-eb8883508809 h1:ZbFL+BDfBqegi+/Ssh7im5+aQfBRx6it+kHnC7jaDU8=
+github.com/Mzack9999/go-http-digest-auth-client v0.6.1-0.20220414142836-eb8883508809/go.mod h1:upgc3Zs45jBDnBT4tVRgRcgm26ABpaP7MoTSdgysca4=
+github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow=
+github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4=
+github.com/akrylysov/pogreb v0.10.1 h1:FqlR8VR7uCbJdfUob916tPM+idpKgeESDXOA1K0DK4w=
+github.com/akrylysov/pogreb v0.10.1/go.mod h1:pNs6QmpQ1UlTJKDezuRWmaqkgUE2TuU0YTWyqJZ7+lI=
+github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek=
+github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s=
+github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
+github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
+github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
+github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
+github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
+github.com/aymanbagabas/go-osc52 v1.0.3/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4=
+github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
+github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
+github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
+github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
+github.com/bits-and-blooms/bitset v1.8.0 h1:FD+XqgOZDUxxZ8hzoBFuV9+cGWY9CslN6d5MS5JVb4c=
+github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
+github.com/bits-and-blooms/bloom/v3 v3.5.0 h1:AKDvi1V3xJCmSR6QhcBfHbCN4Vf8FfxeWkMNQfmAGhY=
+github.com/bits-and-blooms/bloom/v3 v3.5.0/go.mod h1:Y8vrn7nk1tPIlmLtW2ZPV+W7StdVMor6bC1xgpjMZFs=
+github.com/charmbracelet/glamour v0.6.0 h1:wi8fse3Y7nfcabbbDuwolqTqMQPMnVPeZhDM273bISc=
+github.com/charmbracelet/glamour v0.6.0/go.mod h1:taqWV4swIMMbWALc0m7AfE9JkPSU8om2538k9ITBxOc=
+github.com/cheggaaa/pb/v3 v3.1.4 h1:DN8j4TVVdKu3WxVwcRKu0sG00IIU6FewoABZzXbRQeo=
+github.com/cheggaaa/pb/v3 v3.1.4/go.mod h1:6wVjILNBaXMs8c21qRiaUM8BR82erfgau1DQ4iUXmSA=
+github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
+github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
+github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 h1:ox2F0PSMlrAAiAdknSRMDrAr8mfxPCfSZolH+/qQnyQ=
+github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08/go.mod h1:pCxVEbcm3AMg7ejXyorUXi6HQCzOIBf7zEDVPtw0/U4=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/denisbrodbeck/machineid v1.0.1 h1:geKr9qtkB876mXguW2X6TU4ZynleN6ezuMSRhl4D7AQ=
+github.com/denisbrodbeck/machineid v1.0.1/go.mod h1:dJUwb7PTidGDeYyUBmXZ2GphQBbjJCrnectwCyxcUSI=
+github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U=
+github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
+github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
+github.com/dlclark/regexp2 v1.8.1 h1:6Lcdwya6GjPUNsBct8Lg/yRPwMhABj269AAzdGSiR+0=
+github.com/dlclark/regexp2 v1.8.1/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
+github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
+github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
+github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY=
+github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
+github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
+github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203 h1:XBBHcIb256gUJtLmY22n99HaZTz+r2Z51xUPi01m3wg=
+github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203/go.mod h1:E1jcSv8FaEny+OP/5k9UxZVw9YFWGj7eI4KR/iOBqCg=
+github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
+github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
+github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
+github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk=
+github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI=
+github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
+github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
+github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
+github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
+github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-github/v30 v30.1.0 h1:VLDx+UolQICEOKu2m4uAoMti1SxuEBAl7RSEG16L+Oo=
+github.com/google/go-github/v30 v30.1.0/go.mod h1:n8jBpHl45a/rlBUtRJMOG4GhNADUQFEufcolZ95JfU8=
+github.com/google/go-github/v50 v50.1.0/go.mod h1:Ev4Tre8QoKiolvbpOSG3FIi4Mlon3S2Nt9W5JYqKiwA=
+github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
+github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
+github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
+github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
+github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
+github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
+github.com/hashicorp/golang-lru/v2 v2.0.6 h1:3xi/Cafd1NaoEnS/yDssIiuVeDVywU0QdFGl3aQaQHM=
+github.com/hashicorp/golang-lru/v2 v2.0.6/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/jedib0t/go-pretty/v6 v6.4.7 h1:lwiTJr1DEkAgzljsUsORmWsVn5MQjt1BPJdPCtJ6KXE=
+github.com/jedib0t/go-pretty/v6 v6.4.7/go.mod h1:Ndk3ase2CkQbXLLNf5QDHoYb6J9WtVfmHZu9n8rk2xs=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
+github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
+github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
+github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
+github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
+github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
+github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
+github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
+github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
+github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
+github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
+github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
+github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
+github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
+github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
+github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo=
+github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
+github.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM=
+github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58=
+github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs=
+github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM=
+github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk=
+github.com/minio/selfupdate v0.6.1-0.20230907112617-f11e74f84ca7 h1:yRZGarbxsRytL6EGgbqK2mCY+Lk5MWKQYKJT2gEglhc=
+github.com/minio/selfupdate v0.6.1-0.20230907112617-f11e74f84ca7/go.mod h1:bO02GTIPCMQFTEvE5h4DjYB58bCoZ35XLeBf0buTDdM=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8=
+github.com/mreiferson/go-httpclient v0.0.0-20201222173833-5e475fde3a4d/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8=
+github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
+github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
+github.com/muesli/termenv v0.13.0/go.mod h1:sP1+uffeLaEYpyOTb8pLCUctGcGLnoFjSn4YJK5e2bc=
+github.com/muesli/termenv v0.15.1 h1:UzuTb/+hhlBugQz28rpzey4ZuKcZ03MeKsoG7IJZIxs=
+github.com/muesli/termenv v0.15.1/go.mod h1:HeAQPTzpfs016yGtA4g00CsdYnVLJvxsS4ANqrZs2sQ=
+github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
+github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc=
+github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
+github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
+github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc=
+github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
+github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
+github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
+github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
+github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k=
+github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
+github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
+github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
+github.com/pierrec/lz4/v4 v4.1.2 h1:qvY3YFXRQE/XB8MlLzJH7mSzBs74eA2gg52YTk6jUPM=
+github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/projectdiscovery/blackrock v0.0.1 h1:lHQqhaaEFjgf5WkuItbpeCZv2DUIE45k0VbGJyft6LQ=
+github.com/projectdiscovery/blackrock v0.0.1/go.mod h1:ANUtjDfaVrqB453bzToU+YB4cUbvBRpLvEwoWIwlTss=
+github.com/projectdiscovery/fastdialer v0.0.55 h1:dcD3La9MsImgQMrBnG0/w5Mu8PRJu2TU1STycKSSodc=
+github.com/projectdiscovery/fastdialer v0.0.55/go.mod h1:DNP62sWCLp0YHXwhlo73iyZODpSZE7dVstt2GNAC7+A=
+github.com/projectdiscovery/goflags v0.1.36 h1:gElwVU9BJsUbxjyHqDTmlGsB8Br2DDxbfMQMXLYvYhg=
+github.com/projectdiscovery/goflags v0.1.36/go.mod h1:A+MLWJgGKZ2WUED0ZlW5EQ4mmJ/s71VnvY6KF5ThLaM=
+github.com/projectdiscovery/gologger v1.1.12 h1:uX/QkQdip4PubJjjG0+uk5DtyAi1ANPJUvpmimXqv4A=
+github.com/projectdiscovery/gologger v1.1.12/go.mod h1:DI8nywPLERS5mo8QEA9E7gd5HZ3Je14SjJBH3F5/kLw=
+github.com/projectdiscovery/hmap v0.0.35 h1:JkadBpuB/GttuS+O72E26y6RrC8Ox90iFunrI2/zvrc=
+github.com/projectdiscovery/hmap v0.0.35/go.mod h1:EXm6Z/e10GS0uK7qNLH2OcT0bIKq+T4ZDWxSzK0ho5U=
+github.com/projectdiscovery/networkpolicy v0.0.7 h1:AwHqBRXBqDQgnWzBMuoJtHBNEYBw+NFp/4qIK688x7o=
+github.com/projectdiscovery/networkpolicy v0.0.7/go.mod h1:CK0CnFoLF1Nou6mY7P4WODSAxhPN8g8g7XpapgEP8tI=
+github.com/projectdiscovery/retryabledns v1.0.52 h1:jJRIT5y7KYZvaZAAvlkxvkKkQzst6LvEeLDqRc3LeOM=
+github.com/projectdiscovery/retryabledns v1.0.52/go.mod h1:Ea478e6XNVAmfH4KwqtLNjkwdgkpVH1O3+FL2dKLNb8=
+github.com/projectdiscovery/retryablehttp-go v1.0.44 h1:hicCe2h6daHt4muPovmffZE3YKBqGioreO6EpIGZ87g=
+github.com/projectdiscovery/retryablehttp-go v1.0.44/go.mod h1:7ECXK2cH2/G4sstf8hacyrMdPPJ/3wCAO5tFPZ4iO4s=
+github.com/projectdiscovery/utils v0.0.74 h1:mrjRm1eF3ZLIikIpWF3Nzbar/twHHqhz9WSi9fqGQeA=
+github.com/projectdiscovery/utils v0.0.74/go.mod h1:4MBUFfZ9Mm96PiWUj2zJ99sx2AVOpZkGukC6O16+p+o=
+github.com/quic-go/quic-go v0.37.7 h1:AgKsQLZ1+YCwZd2GYhBUsJDYZwEkA5gENtAjb+MxONU=
+github.com/quic-go/quic-go v0.37.7/go.mod h1:YsbH1r4mSHPJcLF4k4zruUkLBqctEMBDR6VPvcYjIsU=
+github.com/refraction-networking/utls v1.5.4 h1:9k6EO2b8TaOGsQ7Pl7p9w6PUhx18/ZCeT0WNTZ7Uw4o=
+github.com/refraction-networking/utls v1.5.4/go.mod h1:SPuDbBmgLGp8s+HLNc83FuavwZCFoMmExj+ltUHiHUw=
+github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
+github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
+github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
+github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
+github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA=
+github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
+github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
+github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
+github.com/tidwall/assert v0.1.0 h1:aWcKyRBUAdLoVebxo95N7+YZVTFF/ASTr7BN4sLP6XI=
+github.com/tidwall/assert v0.1.0/go.mod h1:QLYtGyeqse53vuELQheYl9dngGCJQ+mTtlxcktb+Kj8=
+github.com/tidwall/btree v1.4.3 h1:Lf5U/66bk0ftNppOBjVoy/AIPBrLMkheBp4NnSNiYOo=
+github.com/tidwall/btree v1.4.3/go.mod h1:LGm8L/DZjPLmeWGjv5kFrY8dL4uVhMmzmmLYmsObdKE=
+github.com/tidwall/buntdb v1.3.0 h1:gdhWO+/YwoB2qZMeAU9JcWWsHSYU3OvcieYgFRS0zwA=
+github.com/tidwall/buntdb v1.3.0/go.mod h1:lZZrZUWzlyDJKlLQ6DKAy53LnG7m5kHyrEHvvcDmBpU=
+github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/tidwall/gjson v1.14.3 h1:9jvXn7olKEHU1S9vwoMGliaT8jq1vJ7IH/n9zD9Dnlw=
+github.com/tidwall/gjson v1.14.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/tidwall/grect v0.1.4 h1:dA3oIgNgWdSspFzn1kS4S/RDpZFLrIxAZOdJKjYapOg=
+github.com/tidwall/grect v0.1.4/go.mod h1:9FBsaYRaR0Tcy4UwefBX/UDcDcDy9V5jUcxHzv2jd5Q=
+github.com/tidwall/lotsa v1.0.2 h1:dNVBH5MErdaQ/xd9s769R31/n2dXavsQ0Yf4TMEHHw8=
+github.com/tidwall/lotsa v1.0.2/go.mod h1:X6NiU+4yHA3fE3Puvpnn1XMDrFZrE9JO2/w+UMuqgR8=
+github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
+github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
+github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
+github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
+github.com/tidwall/rtred v0.1.2 h1:exmoQtOLvDoO8ud++6LwVsAMTu0KPzLTUrMln8u1yu8=
+github.com/tidwall/rtred v0.1.2/go.mod h1:hd69WNXQ5RP9vHd7dqekAz+RIdtfBogmglkZSRxCHFQ=
+github.com/tidwall/tinyqueue v0.1.1 h1:SpNEvEggbpyN5DIReaJ2/1ndroY8iyEGxPYxoSaymYE=
+github.com/tidwall/tinyqueue v0.1.1/go.mod h1:O/QNHwrnjqr6IHItYrzoHAKYhBkLI67Q096fQP5zMYw=
+github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
+github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
+github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
+github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
+github.com/ulule/deepcopier v0.0.0-20200430083143-45decc6639b6 h1:TtyC78WMafNW8QFfv3TeP3yWNDG+uxNkk9vOrnDu6JA=
+github.com/ulule/deepcopier v0.0.0-20200430083143-45decc6639b6/go.mod h1:h8272+G2omSmi30fBXiZDMkmHuOgonplfKIKjQWzlfs=
+github.com/weppos/publicsuffix-go v0.13.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8Ln16JPQ02lHAdn5k=
+github.com/weppos/publicsuffix-go v0.30.1-0.20230422193905-8fecedd899db h1:/WcxBne+5CbtbgWd/sV2wbravmr4sT7y52ifQaCgoLs=
+github.com/weppos/publicsuffix-go v0.30.1-0.20230422193905-8fecedd899db/go.mod h1:aiQaH1XpzIfgrJq3S1iw7w+3EDbRP7mF5fmwUhWyRUs=
+github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
+github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
+github.com/yl2chen/cidranger v1.0.2 h1:lbOWZVCG1tCRX4u24kuM1Tb4nHqWkDxwLdoS+SevawU=
+github.com/yl2chen/cidranger v1.0.2/go.mod h1:9U1yz7WPYDwf0vpNWFaeRh0bjwz5RVgRy/9UEQfHl0g=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+github.com/yuin/goldmark v1.5.2/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+github.com/yuin/goldmark v1.5.4 h1:2uY/xC0roWy8IBEGLgB1ywIoEJFGmRrX21YQcvGZzjU=
+github.com/yuin/goldmark v1.5.4/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+github.com/yuin/goldmark-emoji v1.0.1 h1:ctuWEyzGBwiucEqxzwe0SOYDXPAucOrE9NQC18Wa1os=
+github.com/yuin/goldmark-emoji v1.0.1/go.mod h1:2w1E6FEWLcDQkoTE+7HU6QF1F6SLlNGjRIBbIZQFqkQ=
+github.com/zmap/rc2 v0.0.0-20131011165748-24b9757f5521/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE=
+github.com/zmap/rc2 v0.0.0-20190804163417-abaa70531248 h1:Nzukz5fNOBIHOsnP+6I79kPx3QhLv8nBy2mfFhBRq30=
+github.com/zmap/rc2 v0.0.0-20190804163417-abaa70531248/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE=
+github.com/zmap/zcertificate v0.0.0-20180516150559-0e3d58b1bac4/go.mod h1:5iU54tB79AMBcySS0R2XIyZBAVmeHranShAFELYx7is=
+github.com/zmap/zcertificate v0.0.1/go.mod h1:q0dlN54Jm4NVSSuzisusQY0hqDWvu92C+TWveAxiVWk=
+github.com/zmap/zcrypto v0.0.0-20201128221613-3719af1573cf/go.mod h1:aPM7r+JOkfL+9qSB4KbYjtoEzJqUK50EXkkJabeNJDQ=
+github.com/zmap/zcrypto v0.0.0-20201211161100-e54a5822fb7e/go.mod h1:aPM7r+JOkfL+9qSB4KbYjtoEzJqUK50EXkkJabeNJDQ=
+github.com/zmap/zcrypto v0.0.0-20230422215203-9a665e1e9968 h1:YOQ1vXEwE4Rnj+uQ/3oCuJk5wgVsvUyW+glsndwYuyA=
+github.com/zmap/zcrypto v0.0.0-20230422215203-9a665e1e9968/go.mod h1:xIuOvYCZX21S5Z9bK1BMrertTGX/F8hgAPw7ERJRNS0=
+github.com/zmap/zlint/v3 v3.0.0/go.mod h1:paGwFySdHIBEMJ61YjoqT4h7Ge+fdYG4sUQhnTb1lJ8=
+go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
+go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
+go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
+go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
+golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
+golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
+golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
+golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
+golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
+golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
+golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
+golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc h1:ao2WRsKSzW6KuUY9IWPwWahcHCgR0s52IfwutMfEbdM=
+golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
+golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
+golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
+golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
+golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I=
+golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU=
+golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
+golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
+golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
+golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
+golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
+golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA=
+golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
+google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
+google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/djherbis/times.v1 v1.3.0 h1:uxMS4iMtH6Pwsxog094W0FYldiNnfY/xba00vq6C2+o=
+gopkg.in/djherbis/times.v1 v1.3.0/go.mod h1:AQlg6unIsrsCEdQYhTzERy542dz6SFdQFZFv6mUY0P8=
+gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/runner/banner.go b/runner/banner.go
new file mode 100644
index 0000000..ce02bd4
--- /dev/null
+++ b/runner/banner.go
@@ -0,0 +1,40 @@
+package runner
+
+import (
+ "github.com/projectdiscovery/gologger"
+ "github.com/projectdiscovery/utils/auth/pdcp"
+ updateutils "github.com/projectdiscovery/utils/update"
+)
+
+const banner = `
+
+ ______ _____ ____ ___ ____ ____
+ / ___/ | / / _ \/ __ \__ \/ __ \/ __ \
+ / /__ | |/ / __/ / / / / / /_/ / /_/ /
+ \___/ |___/\___/_/ /_/ /_/\__,_/ .___/
+ /_/
+
+`
+
+// Version is the current version
+const Version = `v0.0.1`
+
+// showBanner is used to show the banner to the user
+func showBanner() {
+ gologger.Print().Msgf("%s\n", banner)
+ gologger.Print().Msgf("\t\tprojectdiscovery.io\n\n")
+}
+
+// GetUpdateCallback returns a callback function that updates proxify
+func GetUpdateCallback() func() {
+ return func() {
+ showBanner()
+ updateutils.GetUpdateToolCallback("cvemap", Version)()
+ }
+}
+
+// AuthWithPDCP is used to authenticate with PDCP
+func AuthWithPDCP() {
+ showBanner()
+ pdcp.CheckNValidateCredentials("cvemap")
+}
diff --git a/runner/options.go b/runner/options.go
new file mode 100644
index 0000000..b777b62
--- /dev/null
+++ b/runner/options.go
@@ -0,0 +1,43 @@
+package runner
+
+import "github.com/projectdiscovery/goflags"
+
+type Options struct {
+ PdcpAuth bool
+ CveIds goflags.StringSlice
+ CweIds goflags.StringSlice
+ Vendor goflags.StringSlice
+ Product goflags.StringSlice
+ Eproduct goflags.StringSlice
+ Severity goflags.StringSlice
+ CvssScore goflags.StringSlice
+ //cvssMetrics goflags.StringSlice
+ EpssPercentile goflags.StringSlice
+ //year goflags.StringSlice
+ Assignees goflags.StringSlice
+ Reference goflags.StringSlice
+ //vulnType goflags.StringSlice
+ IncludeColumns []string
+ ExcludeColumns []string
+ TableHeaders []string
+ ListId bool
+ EpssScore string
+ Cpe string
+ VulnStatus string
+ Age string
+ Kev string
+ //trending bool
+ Hackerone string
+ HasNucleiTemplate string
+ HasPoc string
+ Search string
+ RemotlyExploitable string
+ EnablePageKeys bool
+ Json bool
+ Limit int
+ Offset int
+ Version bool
+ DisableUpdateCheck bool
+ Silent bool
+ Verbose bool
+}
diff --git a/runner/runner.go b/runner/runner.go
new file mode 100644
index 0000000..1b4aff0
--- /dev/null
+++ b/runner/runner.go
@@ -0,0 +1,865 @@
+package runner
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+ "net/http/httputil"
+ "net/url"
+ "os"
+ "strconv"
+ "strings"
+ "sync"
+
+ "github.com/eiannone/keyboard"
+ "github.com/jedib0t/go-pretty/v6/table"
+ "github.com/projectdiscovery/goflags"
+ "github.com/projectdiscovery/gologger"
+ "github.com/projectdiscovery/gologger/levels"
+ "github.com/projectdiscovery/utils/auth/pdcp"
+ errorutil "github.com/projectdiscovery/utils/errors"
+ fileutil "github.com/projectdiscovery/utils/file"
+ sliceutil "github.com/projectdiscovery/utils/slice"
+ updateutils "github.com/projectdiscovery/utils/update"
+)
+
+const xPDCPKeyHeader = "X-PDCP-Key"
+
+var (
+ baseUrl = "https://cve.projectdiscovery.io/api/v1"
+ httpCleint = &http.Client{}
+ pdcpApiKey = ""
+ DEFAULT_FEILD_CHAR_LIMIT = 20
+)
+
+func init() {
+ if os.Getenv("CVEMAP_API_URL") != "" {
+ baseUrl = os.Getenv("CVEMAP_API_URL")
+ }
+ pch := pdcp.PDCPCredHandler{}
+ if os.Getenv("PDCP_API_KEY") != "" {
+ pdcpApiKey = os.Getenv("PDCP_API_KEY")
+ } else if creds, err := pch.GetCreds(); err == nil {
+ pdcpApiKey = creds.APIKey
+ }
+ if os.Getenv("DEFAULT_FEILD_CHAR_LIMIT") != "" {
+ DEFAULT_FEILD_CHAR_LIMIT, _ = strconv.Atoi(os.Getenv("DEFAULT_FEILD_CHAR_LIMIT"))
+ }
+}
+
+var (
+ defaultHeaders = []string{"ID", "CVSS", "Severity", "EPSS", "Product", "Age", "Template"}
+
+ headerMap = map[string]string{
+ "id": "id",
+ "cwe": "cwe",
+ "epss": "epss",
+ "cvss": "cvss",
+ "severity": "severity",
+ "vendor": "vendor",
+ "product": "product",
+ "vstatus": "vstatus",
+ "assignee": "assignee",
+ "age": "age",
+ "kev": "kev",
+ "template": "template",
+ "poc": "poc",
+ "rank": "rank",
+ "reports": "reports",
+ }
+
+ allowedHeader = goflags.AllowdTypes{
+ "": goflags.EnumVariable(-1),
+ "cwe": goflags.EnumVariable(0),
+ "epss": goflags.EnumVariable(1),
+ "product": goflags.EnumVariable(2),
+ "vendor": goflags.EnumVariable(3),
+ "vstatus": goflags.EnumVariable(4),
+ "assignee": goflags.EnumVariable(5),
+ "age": goflags.EnumVariable(6),
+ "kev": goflags.EnumVariable(7),
+ "template": goflags.EnumVariable(8),
+ "poc": goflags.EnumVariable(9),
+ }
+ allowedHeaderString = allowedHeader.String()
+
+ allowedVstatus = goflags.AllowdTypes{
+ "": goflags.EnumVariable(-1),
+ "new": goflags.EnumVariable(0),
+ "confirmed": goflags.EnumVariable(1),
+ "unconfirmed": goflags.EnumVariable(2),
+ "modified": goflags.EnumVariable(3),
+ "rejected": goflags.EnumVariable(4),
+ "unknown": goflags.EnumVariable(5),
+ }
+
+ maxLimit = 300
+)
+
+func ParseOptions() *Options {
+ var options Options
+
+ flagset := goflags.NewFlagSet()
+ flagset.SetDescription(`Navigate the CVE jungle with ease.`)
+
+ flagset.CreateGroup("config", "Config",
+ flagset.BoolVar(&options.PdcpAuth, "auth", false, "configure projectdiscovery cloud (pdcp) api key"),
+ )
+
+ flagset.CreateGroup("OPTIONS", "options",
+ // currently only one cve id is supported
+ flagset.StringSliceVar(&options.CveIds, "id", nil, "cve to list for given id", goflags.FileCommaSeparatedStringSliceOptions),
+ // flagset.StringSliceVarP(&options.cweIds, "cwe-id", "cwe", nil, "cve to list for given cwe id", goflags.CommaSeparatedStringSliceOptions),
+ flagset.StringSliceVarP(&options.Vendor, "vendor", "v", nil, "cve to list for given vendor", goflags.CommaSeparatedStringSliceOptions),
+ flagset.StringSliceVarP(&options.Product, "product", "p", nil, "cve to list for given product", goflags.CommaSeparatedStringSliceOptions),
+ flagset.StringSliceVar(&options.Eproduct, "eproduct", nil, "cves to exclude based on products", goflags.CommaSeparatedStringSliceOptions),
+ flagset.StringSliceVarP(&options.Severity, "severity", "s", nil, "cve to list for given severity", goflags.CommaSeparatedStringSliceOptions),
+ flagset.StringSliceVarP(&options.CvssScore, "cvss-score", "cs", nil, "cve to list for given cvss score", goflags.CommaSeparatedStringSliceOptions),
+ flagset.StringVarP(&options.Cpe, "cpe", "c", "", "cve to list for given cpe"),
+ flagset.StringVarP(&options.EpssScore, "epss-score", "es", "", "cve to list for given epss score"),
+ flagset.StringSliceVarP(&options.EpssPercentile, "epss-percentile", "ep", nil, "cve to list for given epss percentile", goflags.CommaSeparatedStringSliceOptions),
+ flagset.StringVar(&options.Age, "age", "", "cve to list published by given age in days"),
+ flagset.StringSliceVarP(&options.Assignees, "assignee", "a", nil, "cve to list for given publisher assignee", goflags.CommaSeparatedStringSliceOptions),
+ //flagset.StringSliceVarP(&options.vulnType, "type", "vt", nil, "cve to list for given vulnerability type", goflags.CommaSeparatedStringSliceOptions),
+ flagset.EnumVarP(&options.VulnStatus, "vstatus", "vs", goflags.EnumVariable(-1), strings.Replace(fmt.Sprintf("cve to list for given vulnerability status in cli output. supported: %s", allowedVstatus.String()), " ,", "", -1), allowedVstatus),
+ )
+
+ flagset.CreateGroup("update", "Update",
+ flagset.CallbackVarP(GetUpdateCallback(), "update", "up", "update cvemap to latest version"),
+ flagset.BoolVarP(&options.DisableUpdateCheck, "disable-update-check", "duc", false, "disable automatic cvemap update check"),
+ )
+
+ flagset.CreateGroup("FILTER", "filter",
+ flagset.StringVarP(&options.Search, "search", "q", "", "search in cve data"),
+ flagset.DynamicVarP(&options.Kev, "kev", "k", "true", "display cves marked as exploitable vulnerabilities by cisa"),
+ flagset.DynamicVarP(&options.HasNucleiTemplate, "template", "t", "true", "display cves that has public nuclei templates"),
+ flagset.DynamicVar(&options.HasPoc, "poc", "true", "display cves that has public published poc"),
+ flagset.DynamicVarP(&options.Hackerone, "hackerone", "h1", "true", "display cves reported on hackerone"),
+ flagset.DynamicVarP(&options.RemotlyExploitable, "remote", "re", "true", "display remotely exploitable cves (AV:N & PR:N | PR:L)"),
+ )
+
+ flagset.CreateGroup("OUTPUT", "output",
+ flagset.EnumSliceVarP(&options.IncludeColumns, "field", "f", []goflags.EnumVariable{goflags.EnumVariable(-1)}, strings.Replace(fmt.Sprintf("fields to display in cli output. supported: %s", allowedHeaderString), " ,", "", -1), allowedHeader),
+ flagset.EnumSliceVarP(&options.ExcludeColumns, "exclude", "fe", []goflags.EnumVariable{goflags.EnumVariable(-1)}, strings.Replace(fmt.Sprintf("fields to exclude from cli output. supported: %s", allowedHeaderString), " ,", "", -1), allowedHeader),
+ flagset.BoolVarP(&options.ListId, "list-id", "lsi", false, "list only the cve ids in the output"),
+ flagset.IntVarP(&options.Limit, "limit", "l", 50, "limit the number of results to display"),
+ flagset.IntVar(&options.Offset, "offset", 0, "offset the results to display"),
+ flagset.BoolVarP(&options.Json, "json", "j", false, "return output in json format"),
+ // experimental
+ flagset.BoolVarP(&options.EnablePageKeys, "enable-page-keys", "epk", false, "enable page keys to navigate results"),
+ )
+
+ flagset.CreateGroup("DEBUG", "debug",
+ flagset.BoolVar(&options.Version, "version", false, "Version"),
+ flagset.BoolVar(&options.Silent, "silent", false, "Silent"),
+ flagset.BoolVar(&options.Verbose, "verbose", false, "Verbose"),
+ )
+
+ if err := flagset.Parse(); err != nil {
+ gologger.Fatal().Msgf("Error parsing flags: %s\n", err)
+ }
+
+ if options.Limit > maxLimit {
+ options.Limit = maxLimit
+ }
+
+ if fileutil.HasStdin() {
+ // Read from stdin
+ bin, err := io.ReadAll(os.Stdin)
+ if err != nil {
+ gologger.Fatal().Msgf("couldn't read stdin: %s\n", err)
+ }
+ options.CveIds = append(options.CveIds, strings.Split(strings.TrimSpace(string(bin)), "\n")...)
+ }
+
+ return &options
+}
+
+func Run(options Options) {
+
+ if options.Version {
+ gologger.Info().Msgf("Current Version: %s\n", Version)
+ os.Exit(0)
+ }
+
+ if options.PdcpAuth {
+ AuthWithPDCP()
+ }
+
+ if options.Silent {
+ gologger.DefaultLogger.SetMaxLevel(levels.LevelSilent)
+ } else if options.Verbose {
+ gologger.DefaultLogger.SetMaxLevel(levels.LevelVerbose)
+ }
+
+ // Show the user the banner
+ showBanner()
+
+ if !options.DisableUpdateCheck {
+ latestVersion, err := updateutils.GetToolVersionCallback("cvemap", Version)()
+ if err != nil {
+ if options.Verbose {
+ gologger.Error().Msgf("cvemap version check failed: %v", err.Error())
+ }
+ } else {
+ gologger.Info().Msgf("Current cvemap version %v %v", Version, updateutils.GetVersionDescription(Version, latestVersion))
+ }
+ }
+
+ // on default, enable kev
+ if isDefaultRun(options) {
+ options.Kev = "true"
+ }
+
+ parseHeaders(&options)
+
+ if options.EnablePageKeys && len(options.CveIds) == 0 {
+ processWithPageKeyEvents(options)
+ } else {
+ _ = process(options)
+ }
+}
+
+func process(options Options) *CVEBulkData {
+ var cvesResp *CVEBulkData
+ var err error
+ cvesResp, err = getCves(options)
+ if err != nil {
+ gologger.Fatal().Msgf("Error getting CVEs: %s\n", err)
+ return nil
+ }
+
+ if options.Json {
+ outputJson(cvesResp.Cves)
+ return cvesResp
+ }
+
+ nPages := cvesResp.TotalResults / options.Limit
+ if cvesResp.TotalResults%options.Limit > 0 {
+ nPages++
+ }
+ currentPage := (options.Offset / options.Limit) + 1
+ if len(options.CveIds) == 0 && (options.Verbose || options.EnablePageKeys) {
+ gologger.Print().Msgf("\n Limit: %v Page: %v TotalPages: %v TotalResults: %v\n", options.Limit, currentPage, nPages, cvesResp.TotalResults)
+ }
+
+ if options.ListId {
+ for _, cve := range cvesResp.Cves {
+ fmt.Println(cve.CveID)
+ }
+ return cvesResp
+ }
+
+ // limit headers to 10, otherwise it will be too wide
+ if len(options.TableHeaders) > 10 {
+ options.TableHeaders = options.TableHeaders[:10]
+ }
+
+ headers, rows := generateTableData(cvesResp.Cves, options.TableHeaders)
+
+ renderTable(headers, rows)
+
+ if options.EnablePageKeys {
+ pageString := ""
+ if currentPage > 1 {
+ pageString += " ◀ "
+ }
+ if currentPage < nPages {
+ pageString += " ▶"
+ }
+ fmt.Print(pageString)
+ }
+ return cvesResp
+}
+
+func processWithPageKeyEvents(options Options) {
+ cveResp := process(options)
+
+ // wait for user input
+ err := keyboard.Open()
+ if err != nil {
+ panic(err)
+ }
+ defer keyboard.Close()
+ waitGroup := sync.WaitGroup{}
+ waitGroup.Add(1)
+
+ go func() {
+ for {
+ _, key, err := keyboard.GetKey()
+ if err != nil {
+ panic(err)
+ }
+
+ if key == keyboard.KeyEsc || key == keyboard.KeyCtrlC {
+ waitGroup.Done()
+ break
+ }
+
+ switch key {
+ case keyboard.KeyArrowRight:
+ if options.Offset+options.Limit < cveResp.TotalResults {
+ options.Offset += options.Limit
+ clearScreen()
+ cveResp = process(options)
+ }
+ case keyboard.KeyArrowLeft:
+ if options.Offset-options.Limit >= 0 {
+ options.Offset -= options.Limit
+ clearScreen()
+ cveResp = process(options)
+ }
+ }
+ }
+ }()
+
+ waitGroup.Wait()
+}
+
+func parseHeaders(options *Options) {
+ // construct headers
+ headers := make([]string, 0)
+
+ if options.Hackerone == "true" {
+ defaultHeaders = []string{"ID", "CVSS", "Severity", "Rank", "Reports", "Product", "Age", "Template"}
+ }
+
+ options.IncludeColumns = getValidHeaders(options.IncludeColumns)
+ options.ExcludeColumns = getValidHeaders(options.ExcludeColumns)
+
+ options.IncludeColumns = append(defaultHeaders, options.IncludeColumns...)
+ // case insensitive contains check
+ contains := func(array []string, element string) bool {
+ for _, e := range array {
+ if strings.EqualFold(e, element) {
+ return true
+ }
+ }
+ return false
+ }
+ // add headers to display
+ for _, header := range options.IncludeColumns {
+ if !contains(options.ExcludeColumns, header) && !contains(headers, header) {
+ headers = append(headers, header)
+ }
+ }
+ options.TableHeaders = headers
+}
+
+func renderTable(headers []string, rows [][]interface{}) {
+ // Create a table for displaying CVE data with the specified headers
+ t := table.NewWriter()
+ t.SetOutputMirror(os.Stdout)
+
+ // Append the specified headers to the table
+ headerRow := make([]interface{}, len(headers))
+ for i, header := range headers {
+ headerRow[i] = header
+ }
+ t.AppendHeader(headerRow)
+ // Loop through the retrieved CVE data and add rows to the table
+ for _, row := range rows {
+ t.AppendRow(row)
+ }
+ // t.SetColumnConfigs([]table.ColumnConfig{
+ // {Number: 5, WidthMax: 20},
+ // })
+ // Set table options and render it
+ t.SetStyle(table.StyleRounded)
+ t.Render()
+}
+
+func generateTableData(cves []CVEData, headers []string) ([]string, [][]interface{}) {
+ dataRows := make([][]interface{}, len(cves))
+ for r, cve := range cves {
+ dataRows[r] = getRow(headers, cve)
+ }
+ return headers, dataRows
+}
+
+func getRow(headers []string, cve CVEData) []interface{} {
+ row := make([]interface{}, len(headers))
+ for i, header := range headers {
+ switch strings.ToLower(header) {
+ case "id":
+ row[i] = getCellValueByLimit(cve.CveID)
+ case "epss":
+ row[i] = getCellValueByLimit(cve.Epss.Score)
+ case "cvss":
+ row[i] = ""
+ if cve.CvssMetrics != nil {
+ row[i] = getCellValueByLimit(getLatestVersionCVSSScore(*cve.CvssMetrics))
+ }
+ case "severity":
+ row[i] = getCellValueByLimit(strings.ToTitle(cve.Severity))
+ case "cwe":
+ row[i] = ""
+ if len(cve.Weaknesses) > 0 {
+ row[i] = getCellValueByLimit(cve.Weaknesses[0].CWEID)
+ }
+ case "vendor":
+ row[i] = ""
+ if cve.Cpe != nil {
+ row[i] = getCellValueByLimit(*cve.Cpe.Vendor)
+ }
+ case "product":
+ row[i] = ""
+ if cve.Cpe != nil {
+ row[i] = getCellValueByLimit(*cve.Cpe.Product)
+ }
+ case "vstatus":
+ row[i] = getCellValueByLimit(strings.ToUpper(cve.VulnStatus))
+ case "assignee":
+ row[i] = ""
+ if len(cve.Assignee) > 0 {
+ row[i] = getCellValueByLimit(cve.Assignee)
+ }
+ case "age":
+ row[i] = ""
+ if cve.AgeInDays > 0 {
+ row[i] = getCellValueByLimit(cve.AgeInDays)
+ }
+ case "kev":
+ row[i] = getCellValueByLimit(strings.ToUpper(strconv.FormatBool(cve.IsKev)))
+ case "template":
+ if cve.IsTemplate {
+ row[i] = "✅"
+ } else {
+ row[i] = "❌"
+ }
+ case "poc":
+ row[i] = getCellValueByLimit(strings.ToUpper(strconv.FormatBool(cve.IsPoc)))
+ case "rank":
+ row[i] = ""
+ if cve.Hackerone.Rank > 0 {
+ row[i] = getCellValueByLimit(cve.Hackerone.Rank)
+ }
+ case "reports":
+ row[i] = getCellValueByLimit(cve.Hackerone.Count)
+
+ default:
+ row[i] = ""
+ }
+ }
+ return row
+}
+
+func getCellValueByLimit(cell interface{}) string {
+ if cell == nil {
+ return ""
+ }
+ cellValue := fmt.Sprintf("%v", cell)
+ if len(cellValue) > DEFAULT_FEILD_CHAR_LIMIT {
+ cellValue = cellValue[:DEFAULT_FEILD_CHAR_LIMIT] + "..."
+ }
+ return cellValue
+}
+
+func getCves(options Options) (*CVEBulkData, error) {
+ if len(options.CveIds) > 0 {
+ return getCvesByIds(options.CveIds)
+ }
+ if options.Search != "" {
+ query := constructQueryByOptions(options)
+ return getCvesBySearchString(query, options.Limit, options.Offset)
+ }
+ return getCvesByFilters(constructQueryParams(options))
+}
+
+func getCvesByFilters(encodedParams string) (*CVEBulkData, error) {
+ url := fmt.Sprintf("%s/cves?%s", baseUrl, encodedParams)
+ // Send an HTTP GET request
+ response, err := makeGetRequest(url)
+ if err != nil {
+ return nil, err
+ }
+ defer response.Body.Close()
+ // Check the response status code
+ if response.StatusCode != http.StatusOK {
+ return nil, errorutil.New("unexpected status code: %d", response.StatusCode)
+ }
+ // Create a variable to store the response data
+ var cvesInBulk CVEBulkData
+ // Decode the JSON response into an array of CVEData structs
+ err = json.NewDecoder(response.Body).Decode(&cvesInBulk)
+ if err != nil {
+ return nil, err
+ }
+ return &cvesInBulk, nil
+}
+
+func getCvesByIds(cveIds []string) (*CVEBulkData, error) {
+ url := fmt.Sprintf("%s/cves", baseUrl)
+ // send only 100 cve ids max
+ if len(cveIds) > 100 {
+ cveIds = cveIds[:100]
+ }
+ var cveIdList CVEIdList
+ cveIdList.Cves = append(cveIdList.Cves, cveIds...)
+ reqData, err := json.Marshal(cveIdList)
+ if err != nil {
+ return nil, err
+ }
+ // Send an HTTP POST request
+ req, err := http.NewRequest("POST", url, bytes.NewBuffer(reqData))
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Set("Content-Type", "application/json")
+ req.Header.Set(xPDCPKeyHeader, pdcpApiKey)
+
+ response, err := doRequest(req)
+ if err != nil {
+ return nil, err
+ }
+ defer response.Body.Close()
+ // Check the response status code
+ if response.StatusCode != http.StatusOK {
+ return nil, errorutil.New("unexpected status code: %d", response.StatusCode)
+ }
+ var cvesInBulk CVEBulkData
+ // Decode the JSON response into an array of CVEData structs
+ err = json.NewDecoder(response.Body).Decode(&cvesInBulk)
+ if err != nil {
+ return nil, err
+ }
+ return &cvesInBulk, nil
+}
+
+func getCvesBySearchString(query string, limit, offset int) (*CVEBulkData, error) {
+ u, err := url.Parse(fmt.Sprintf("%s/cves/search", baseUrl))
+ if err != nil {
+ return nil, err
+ }
+ // Construct query parameters
+ q := u.Query()
+ q.Set("q", query)
+ q.Set("limit", fmt.Sprintf("%v", limit))
+ q.Set("offset", fmt.Sprintf("%v", offset))
+ u.RawQuery = q.Encode()
+ response, err := makeGetRequest(u.String())
+ if err != nil {
+ return nil, err
+ }
+ defer response.Body.Close()
+ // Check the response status code
+ if response.StatusCode != http.StatusOK {
+ return nil, errorutil.New("unexpected status code: %d", response.StatusCode)
+ }
+ // Create a variable to store the response data
+ var cvesInBulk CVEBulkData
+ // Decode the JSON response into an array of CVEData structs
+ err = json.NewDecoder(response.Body).Decode(&cvesInBulk)
+ if err != nil {
+ return nil, err
+ }
+ return &cvesInBulk, nil
+}
+
+// all the root level fields are supported
+// func getCvesForSpecificFields(fields []string, encodedParams string, limit, offset int) (*CVEBulkData, error) {
+// url := fmt.Sprintf("%s/cves?fields=%s&%s&limit=%v&offset=%v", baseUrl, strings.Join(fields, ","), encodedParams, limit, offset)
+// // Send an HTTP GET request
+// response, err := makeGetRequest(url)
+// if err != nil {
+// return nil, err
+// }
+// defer response.Body.Close()
+// // Check the response status code
+// if response.StatusCode != http.StatusOK {
+// return nil, errorutil.New("unexpected status code: %d", response.StatusCode)
+// }
+// // Create a variable to store the response data
+// var cvesInBulk CVEBulkData
+// // Decode the JSON response into an array of CVEData structs
+// err = json.NewDecoder(response.Body).Decode(&cvesInBulk)
+// if err != nil {
+// return nil, err
+// }
+// return &cvesInBulk, nil
+// }
+
+var UNAUTHORIZEDERR = errorutil.New(`unexpected status code: 401 (get your free api key from https://cloud.projectdiscovery.io)`)
+
+func makeGetRequest(url string) (*http.Response, error) {
+ req, err := http.NewRequest("GET", url, nil)
+ if err != nil {
+ gologger.Fatal().Msgf("Error creating request: %s\n", err)
+ }
+ req.Header.Set(xPDCPKeyHeader, pdcpApiKey)
+ return doRequest(req)
+}
+
+func doRequest(req *http.Request) (*http.Response, error) {
+ if os.Getenv("DEBUG") == "true" {
+ // dump request
+ dump, err := httputil.DumpRequest(req, true)
+ if err != nil {
+ gologger.Fatal().Msgf("Error dumping request: %s\n", err)
+ }
+ fmt.Println(string(dump))
+ }
+ resp, err := httpCleint.Do(req)
+ if err == nil && resp.StatusCode == http.StatusUnauthorized {
+ var errResp ErrorMessage
+ _ = json.NewDecoder(resp.Body).Decode(&errResp)
+ if os.Getenv("DEBUG") == "true" {
+ gologger.Error().Msgf("unauthorized: %s\n", errResp.Message)
+ }
+ return nil, UNAUTHORIZEDERR
+ }
+ return resp, err
+}
+
+func outputJson(cve []CVEData) {
+ json, err := json.MarshalIndent(cve, "", " ")
+ if err != nil {
+ gologger.Error().Msgf("Error marshalling json: %s\n", err)
+ return
+ }
+ fmt.Println(string(json))
+}
+
+func constructQueryParams(opts Options) string {
+ queryParams := &url.Values{}
+ if len(opts.Severity) > 0 {
+ addQueryParams(queryParams, "severity", opts.Severity)
+ }
+ if len(opts.Assignees) > 0 {
+ addQueryParams(queryParams, "assignee", opts.Assignees)
+ }
+ if len(opts.CvssScore) > 0 {
+ var cvsKey string
+ for _, cvssScore := range opts.CvssScore {
+ cvsKey = "cvss_score"
+ if cvssScore[0] == '>' {
+ cvsKey = "cvss_score_gte"
+ cvssScore = strings.TrimSpace(cvssScore[1:])
+ } else if cvssScore[0] == '<' {
+ cvsKey = "cvss_score_lte"
+ cvssScore = strings.TrimSpace(cvssScore[1:])
+ }
+ queryParams.Add(cvsKey, cvssScore)
+ }
+ }
+
+ if len(opts.Age) > 0 {
+ ageKey := "age_in_days"
+ if opts.Age[0] == '>' {
+ ageKey = "age_in_days_gte"
+ opts.Age = strings.TrimSpace(opts.Age[1:])
+ } else if opts.Age[0] == '<' {
+ ageKey = "age_in_days_lte"
+ opts.Age = strings.TrimSpace(opts.Age[1:])
+ }
+ queryParams.Add(ageKey, opts.Age)
+ }
+ if len(opts.VulnStatus) > 0 {
+ queryParams.Add("vuln_status", strings.ToLower(opts.VulnStatus))
+ }
+ if len(opts.Reference) > 0 {
+ addQueryParams(queryParams, "reference", opts.Reference)
+ }
+ if len(opts.EpssScore) > 0 {
+ epssKey := "epss.epss_score"
+ if opts.EpssScore[0] == '>' {
+ epssKey = "epss.epss_score_gte"
+ opts.EpssScore = strings.TrimSpace(opts.EpssScore[1:])
+ } else if opts.EpssScore[0] == '<' {
+ epssKey = "epss.epss_score_lte"
+ opts.EpssScore = strings.TrimSpace(opts.EpssScore[1:])
+ }
+ queryParams.Add(epssKey, opts.EpssScore)
+ }
+ if len(opts.EpssPercentile) > 0 {
+ var epKey string
+ for _, ep := range opts.EpssPercentile {
+ epKey = "epss.epss_percentile"
+ if ep[0] == '>' {
+ epKey = "epss.epss_percentile_gte"
+ ep = strings.TrimSpace(ep[1:])
+ } else if ep[0] == '<' {
+ epKey = "epss.epss_percentile_lte"
+ ep = strings.TrimSpace(ep[1:])
+ }
+ queryParams.Add(epKey, ep)
+ }
+ }
+ if len(opts.CweIds) > 0 {
+ addQueryParams(queryParams, "cwe_id", opts.CweIds)
+ }
+ if len(opts.Cpe) > 0 {
+ queryParams.Add("cpe.cpe", opts.Cpe)
+ }
+ if len(opts.Product) > 0 {
+ addQueryParams(queryParams, "cpe.product", opts.Product)
+ }
+ if len(opts.Eproduct) > 0 {
+ addQueryParams(queryParams, "cpe.product_ne", opts.Eproduct)
+ }
+ if len(opts.Vendor) > 0 {
+ addQueryParams(queryParams, "cpe.vendor", opts.Vendor)
+ }
+ if opts.Kev == "true" {
+ queryParams.Add("is_exploited", "true")
+ } else if opts.Kev == "false" {
+ queryParams.Add("is_exploited", "false")
+ }
+ if opts.HasNucleiTemplate == "true" {
+ queryParams.Add("is_template", "true")
+ } else if opts.HasNucleiTemplate == "false" {
+ queryParams.Add("is_template", "false")
+ }
+ if opts.HasPoc == "true" {
+ queryParams.Add("is_poc", "true")
+ } else if opts.HasPoc == "false" {
+ queryParams.Add("is_poc", "false")
+ }
+ if opts.Hackerone == "true" {
+ queryParams.Add("hackerone.rank_gte", "1")
+ queryParams.Add("sort_asc", "hackerone.rank")
+ } else {
+ queryParams.Add("sort_desc", "cve_id")
+ }
+ if opts.RemotlyExploitable == "true" {
+ queryParams.Add("is_remote", "true")
+ }
+ if opts.Limit > 0 {
+ queryParams.Add("limit", strconv.Itoa(opts.Limit))
+ }
+ if opts.Offset >= 0 {
+ queryParams.Add("offset", strconv.Itoa(opts.Offset))
+ }
+ return queryParams.Encode()
+}
+
+func constructQueryByOptions(opts Options) string {
+ query := opts.Search
+ if len(opts.Vendor) > 0 {
+ query = fmt.Sprintf("%s cpe.vendor:%s", query, strings.Join(opts.Vendor, ","))
+ }
+ if len(opts.Product) > 0 {
+ query = fmt.Sprintf("%s cpe.product:%s", query, strings.Join(opts.Product, ","))
+ }
+ if len(opts.Eproduct) > 0 {
+ query = fmt.Sprintf("%s cpe.product_ne:%s", query, strings.Join(opts.Eproduct, ","))
+ }
+ if len(opts.Severity) > 0 {
+ query = fmt.Sprintf("%s severity:%s", query, strings.Join(opts.Severity, ","))
+ }
+ if len(opts.CvssScore) > 0 {
+ var cvsKey string
+ for _, cvssScore := range opts.CvssScore {
+ cvsKey = "cvss_score"
+ if cvssScore[0] == '>' {
+ cvsKey = "cvss_score_gte"
+ cvssScore = strings.TrimSpace(cvssScore[1:])
+ } else if cvssScore[0] == '<' {
+ cvsKey = "cvss_score_lte"
+ cvssScore = strings.TrimSpace(cvssScore[1:])
+ }
+ query = fmt.Sprintf("%s %s:%s", query, cvsKey, cvssScore)
+ }
+ }
+ if len(opts.EpssScore) > 0 {
+ epssKey := "epss.epss_score"
+ if opts.EpssScore[0] == '>' {
+ epssKey = "epss.epss_score_gte"
+ opts.EpssScore = strings.TrimSpace(opts.EpssScore[1:])
+ } else if opts.EpssScore[0] == '<' {
+ epssKey = "epss.epss_score_lte"
+ opts.EpssScore = strings.TrimSpace(opts.EpssScore[1:])
+ }
+ query = fmt.Sprintf("%s %s:%s", query, epssKey, opts.EpssScore)
+ }
+ if len(opts.EpssPercentile) > 0 {
+ var epKey string
+ for _, ep := range opts.EpssPercentile {
+ epKey = "epss.epss_percentile"
+ if ep[0] == '>' {
+ epKey = "epss.epss_percentile_gte"
+ ep = strings.TrimSpace(ep[1:])
+ } else if ep[0] == '<' {
+ epKey = "epss.epss_percentile_lte"
+ ep = strings.TrimSpace(ep[1:])
+ }
+ query = fmt.Sprintf("%s %s:%s", query, epKey, ep)
+ }
+ }
+ if len(opts.Cpe) > 0 {
+ query = fmt.Sprintf(`%s cpe.cpe:"%s"`, query, opts.Cpe)
+ }
+ if len(opts.CweIds) > 0 {
+ query = fmt.Sprintf("%s cwe_id:%s", query, strings.Join(opts.CweIds, ","))
+ }
+ if len(opts.Age) > 0 {
+ ageKey := "age_in_days"
+ if opts.Age[0] == '>' {
+ ageKey = "age_in_days_gte"
+ opts.Age = strings.TrimSpace(opts.Age[1:])
+ } else if opts.Age[0] == '<' {
+ ageKey = "age_in_days_lte"
+ opts.Age = strings.TrimSpace(opts.Age[1:])
+ }
+ query = fmt.Sprintf("%s %s:%s", query, ageKey, opts.Age)
+ }
+ if len(opts.Assignees) > 0 {
+ query = fmt.Sprintf("%s assignee:%s", query, strings.Join(opts.Assignees, ","))
+ }
+ if len(opts.VulnStatus) > 0 {
+ query = fmt.Sprintf("%s vuln_status:%s", query, strings.ToLower(opts.VulnStatus))
+ }
+ if opts.Kev == "true" {
+ query = fmt.Sprintf("%s is_exploited:true", query)
+ } else if opts.Kev == "false" {
+ query = fmt.Sprintf("%s is_exploited:false", query)
+ }
+ if opts.HasNucleiTemplate == "true" {
+ query = fmt.Sprintf("%s is_template:true", query)
+ } else if opts.HasNucleiTemplate == "false" {
+ query = fmt.Sprintf("%s is_template:false", query)
+ }
+ if opts.HasPoc == "true" {
+ query = fmt.Sprintf("%s is_poc:true", query)
+ } else if opts.HasPoc == "false" {
+ query = fmt.Sprintf("%s is_poc:false", query)
+ }
+ if opts.Hackerone == "true" {
+ query = fmt.Sprintf("%s hackerone.rank_gte:1 sort_asc:hackerone.rank", query)
+ } else {
+ query = fmt.Sprintf("%s sort_desc:cve_id", query)
+ }
+ if opts.RemotlyExploitable == "true" {
+ query = fmt.Sprintf("%s is_remote:true", query)
+ }
+
+ parts := strings.Split(query, " ")
+ parts = sliceutil.PruneEmptyStrings(parts)
+ parts = sliceutil.Dedupe(parts)
+ query = strings.Join(parts, " ")
+ if os.Getenv("DEBUG") == "true" {
+ fmt.Println("constructed query: ", query)
+ }
+ return query
+}
+
+func addQueryParams(queryParams *url.Values, key string, values []string) *url.Values {
+ if len(values) > 0 {
+ for _, value := range values {
+ queryParams.Add(key, value)
+ }
+ }
+ return queryParams
+}
+
+func getValidHeaders(keys []string) []string {
+ headers := []string{}
+ for _, hk := range keys {
+ if v, ok := headerMap[hk]; ok {
+ headers = append(headers, v)
+ }
+ }
+ return headers
+}
diff --git a/runner/testutils/util.go b/runner/testutils/util.go
new file mode 100644
index 0000000..0765d22
--- /dev/null
+++ b/runner/testutils/util.go
@@ -0,0 +1,38 @@
+package testutils
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+ "strings"
+)
+
+// RunCvemapßBinaryAndGetResults returns a list of the results
+func RunCvemapBinaryAndGetResults(cvemapBinary string, debug bool, args []string) ([]string, error) {
+ cmd := exec.Command("bash", "-c")
+ cmdLine := fmt.Sprintf(`./%s `, cvemapBinary)
+ cmdLine += strings.Join(args, " ")
+ if debug {
+ os.Setenv("DEBUG", "1")
+ cmd.Stderr = os.Stderr
+ }
+ cmd.Args = append(cmd.Args, cmdLine)
+ data, err := cmd.Output()
+ if err != nil {
+ return nil, err
+ }
+ parts := []string{}
+ items := strings.Split(string(data), "\n")
+ for _, i := range items {
+ if i != "" {
+ parts = append(parts, i)
+ }
+ }
+ return parts, nil
+}
+
+// TestCase is a single integration test case
+type TestCase interface {
+ // Execute executes a test case and returns any errors if occurred
+ Execute() error
+}
diff --git a/runner/types.go b/runner/types.go
new file mode 100644
index 0000000..89b05cf
--- /dev/null
+++ b/runner/types.go
@@ -0,0 +1,143 @@
+package runner
+
+import "time"
+
+type CVEBulkData struct {
+ ResultCount int `json:"result_count"`
+ TotalResults int `json:"total_results"`
+ Cves []CVEData `json:"cves"`
+}
+
+type CVEData struct {
+ CveID string `json:"cve_id,omitempty"`
+ CveDescription string `json:"cve_description,omitempty"`
+ Severity string `json:"severity,omitempty"`
+ CvssScore float64 `json:"cvss_score,omitempty"`
+ CvssMetrics *CvssMetrics `json:"cvss_metrics,omitempty"`
+ Weaknesses []struct {
+ CWEID string `json:"cwe_id"`
+ CWEName string `json:"cwe_name,omitempty"`
+ } `json:"weaknesses,omitempty"`
+ Epss struct {
+ Score float64 `json:"epss_score"`
+ Percentile float64 `json:"epss_percentile"`
+ } `json:"epss,omitempty"`
+ Cpe *OutputCpe `json:"cpe,omitempty"`
+ Reference []string `json:"reference,omitempty"`
+ Poc []struct {
+ URL string `json:"url"`
+ Source string `json:"source"`
+ AddedAt string `json:"added_at"`
+ } `json:"poc,omitempty"`
+ VendorAdvisory *string `json:"vendor_advisory,omitempty"`
+ Patch []string `json:"patch_url,omitempty"`
+ IsTemplate bool `json:"is_template"`
+ NucleiTemplates *NucleiTemplates `json:"nuclei_templates,omitempty"`
+ IsKev bool `json:"is_exploited"`
+ Kev *KevObject `json:"kev,omitempty"`
+ Assignee string `json:"assignee,omitempty"`
+ PublishedAt string `json:"published_at,omitempty"`
+ UpdatedAt string `json:"updated_at,omitempty"`
+ Hackerone struct {
+ Rank int `json:"rank"`
+ Count int `json:"count"`
+ } `json:"hackerone,omitempty"`
+ AgeInDays int `json:"age_in_days,omitempty"`
+ VulnStatus string `json:"vuln_status,omitempty"`
+ IsPoc bool `json:"is_poc"`
+ IsRemote bool `json:"is_remote"`
+ IsOss bool `json:"is_oss"`
+ VulnerableCPE []string `json:"vulnerable_cpe,omitempty"`
+ Shodan *OutputShodanData `json:"shodan,omitempty"`
+ OSS *OSS `json:"oss,omitempty"`
+}
+
+type CvssMetrics struct {
+ Cvss2 *Cvss2 `json:"cvss2,omitempty"`
+ Cvss30 *Cvss30 `json:"cvss30,omitempty"`
+ Cvss31 *Cvss31 `json:"cvss31,omitempty"`
+}
+
+type Cvss2 struct {
+ Score float64 `json:"score"`
+ Vector string `json:"vector"`
+ Severity string `json:"severity"`
+}
+
+type Cvss30 struct {
+ Score float64 `json:"score"`
+ Vector string `json:"vector"`
+ Severity string `json:"severity"`
+}
+
+type Cvss31 struct {
+ Score float64 `json:"score"`
+ Vector string `json:"vector"`
+ Severity string `json:"severity"`
+}
+
+type NucleiTemplates struct {
+ TemplateIssue string `json:"template_issue,omitempty"`
+ TemplateIssueType string `json:"template_issue_type,omitempty"`
+ TemplatePath string `json:"template_path,omitempty"`
+ TemplatePR string `json:"template_pr,omitempty"`
+ TemplateURL string `json:"template_url,omitempty"`
+ CreatedAt *time.Time `json:"created_at,omitempty"`
+ UpdatedAt *time.Time `json:"updated_at,omitempty"`
+}
+
+type OSS struct {
+ AllLanguages map[string]int `json:"all_languages,omitempty"`
+ Description string `json:"description,omitempty"`
+ Forks int `json:"forks,omitempty"`
+ Language string `json:"language,omitempty"`
+ Stars int `json:"stars,omitempty"`
+ Subscribers int `json:"subscribers,omitempty"`
+ Topics []string `json:"topics,omitempty"`
+ PushedAt CustomTime `json:"pushed_at,omitempty"`
+ CreatedAt CustomTime `json:"created_at,omitempty"`
+ UpdatedAt CustomTime `json:"updated_at,omitempty"`
+ URL string `json:"url,omitempty"`
+}
+
+type CustomTime struct {
+ time.Time
+}
+
+func (ct *CustomTime) UnmarshalJSON(b []byte) error {
+ s := string(b)
+ if s == "null" {
+ return nil
+ }
+ t, err := time.Parse(`"2006-01-02 15:04:05 -0700 MST"`, s)
+ if err != nil {
+ return err
+ }
+ ct.Time = t
+ return nil
+}
+
+type OutputCpe struct {
+ Cpe *string `json:"cpe,omitempty"`
+ Vendor *string `json:"vendor,omitempty"`
+ Product *string `json:"product,omitempty"`
+ Platform *string `json:"framework,omitempty"`
+}
+
+type KevObject struct {
+ AddedDate string `json:"added_date"`
+ DueDate string `json:"due_date"`
+}
+
+type OutputShodanData struct {
+ Count int `json:"count"`
+ Query []string `json:"query"`
+}
+
+type ErrorMessage struct {
+ Message string `json:"message"`
+}
+
+type CVEIdList struct {
+ Cves []string `json:"cves"`
+}
diff --git a/runner/util.go b/runner/util.go
new file mode 100644
index 0000000..642a67c
--- /dev/null
+++ b/runner/util.go
@@ -0,0 +1,41 @@
+package runner
+
+import (
+ "os"
+ "os/exec"
+ "runtime"
+
+ fileutil "github.com/projectdiscovery/utils/file"
+)
+
+func getLatestVersionCVSSScore(cvss CvssMetrics) float64 {
+ var highestScore float64
+ if cvss.Cvss2 != nil {
+ highestScore = cvss.Cvss2.Score
+ }
+ if cvss.Cvss30 != nil {
+ highestScore = cvss.Cvss30.Score
+ }
+ if cvss.Cvss31 != nil {
+ highestScore = cvss.Cvss31.Score
+ }
+ return highestScore
+}
+
+func isDefaultRun(opts Options) bool {
+ options := len(opts.CveIds) == 0 && len(opts.CweIds) == 0 && len(opts.Vendor) == 0 && len(opts.Product) == 0 && len(opts.Severity) == 0 && len(opts.CvssScore) == 0 && len(opts.EpssPercentile) == 0 && len(opts.Assignees) == 0 && len(opts.Reference) == 0 && opts.EpssScore == "" && opts.Cpe == "" && opts.VulnStatus == "" && opts.Age == ""
+ filters := opts.Kev == "" && opts.Hackerone == "" && opts.HasNucleiTemplate == "" && opts.HasPoc == "" && opts.RemotlyExploitable == ""
+ return options && filters && !fileutil.HasStdin()
+}
+
+// clearScreen clears the terminal screen
+func clearScreen() {
+ var cmd *exec.Cmd
+ if runtime.GOOS == "windows" {
+ cmd = exec.Command("cls")
+ } else {
+ cmd = exec.Command("clear")
+ }
+ cmd.Stdout = os.Stdout
+ _ = cmd.Run()
+}
diff --git a/static/cvemap.png b/static/cvemap.png
new file mode 100644
index 0000000..edf8e92
Binary files /dev/null and b/static/cvemap.png differ