├── .devcontainer
└── devcontainer.json
├── .github
├── ISSUE_TEMPLATE
│ ├── config.yml
│ ├── feature_request.md
│ └── issue-report.md
├── dependabot.yml
├── stale.yml
└── workflows
│ ├── build-test.yml
│ ├── codeql-analysis.yml
│ ├── dockerhub-push.yml
│ ├── lint-test.yml
│ └── release-binary.yml
├── .gitignore
├── .goreleaser.yml
├── Dockerfile
├── LICENSE.md
├── README.md
├── README_KU.md
├── README_TR.md
├── cmd
└── openrisk
│ └── main.go
├── examples
├── example.go
└── example_nuclei_scan.txt
├── go.mod
├── go.sum
└── pkg
└── openrisk
├── issue_processor.go
├── jsonl_parser.go
├── markdown_parser.go
├── openrisk.go
└── types.go
/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the
2 | // README at: https://github.com/devcontainers/templates/tree/main/src/go
3 | {
4 | "name": "Go",
5 | "image": "mcr.microsoft.com/devcontainers/go:0-1.20-buster",
6 |
7 | // Features to add to the dev container. More info: https://containers.dev/features.
8 | // "features": {},
9 |
10 | // Configure tool-specific properties.
11 | "customizations": {
12 | // Configure properties specific to VS Code.
13 | "vscode": {
14 | // Set *default* container specific settings.json values on container create.
15 | "settings": {
16 | "go.toolsManagement.checkForUpdates": "local",
17 | "go.useLanguageServer": true,
18 | "go.gopath": "/go"
19 | }
20 | }
21 | },
22 | "features": {
23 | "ghcr.io/devcontainers/features/python:1": {},
24 | }
25 |
26 | // Use 'forwardPorts' to make a list of ports inside the container available locally.
27 | // "forwardPorts": [],
28 |
29 | // Use 'postCreateCommand' to run commands after the container is created.
30 | // "postCreateCommand": "go version",
31 |
32 | // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
33 | // "remoteUser": "root"
34 | }
35 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 |
3 | contact_links:
4 | - name: Ask an question / advise on using openrisk
5 | url: https://github.com/projectdiscovery/openrisk/discussions/categories/q-a
6 | about: Ask a question or request support for using openrisk
7 |
8 | - name: Share idea / feature to discuss for openrisk
9 | url: https://github.com/projectdiscovery/openrisk/discussions/categories/ideas
10 | about: Share idea / feature to discuss for openrisk
11 |
12 | - name: Connect with PD Team (Discord)
13 | url: https://discord.gg/projectdiscovery
14 | about: Connect with PD Team for direct communication
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Request feature to implement in this project
4 | labels: 'Type: Enhancement'
5 | ---
6 |
7 |
13 |
14 | ### Please describe your feature request:
15 |
16 |
17 | ### Describe the use case of this feature:
18 |
19 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/issue-report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Issue report
3 | about: Create a report to help us to improve the project
4 | labels: 'Type: Bug'
5 |
6 | ---
7 |
8 |
13 |
14 |
15 |
16 | ### openrisk version:
17 |
18 |
19 |
20 |
21 | ### Current Behavior:
22 |
23 |
24 | ### Expected Behavior:
25 |
26 |
27 | ### Steps To Reproduce:
28 |
33 |
34 |
35 | ### Anything else:
36 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 |
9 | # Maintain dependencies for GitHub Actions
10 | - package-ecosystem: "github-actions"
11 | directory: "/"
12 | schedule:
13 | interval: "weekly"
14 | target-branch: "main"
15 | commit-message:
16 | prefix: "chore"
17 | include: "scope"
18 | labels:
19 | - "Type: Maintenance"
20 |
21 | # Maintain dependencies for go modules
22 | - package-ecosystem: "gomod"
23 | directory: "/"
24 | schedule:
25 | interval: "daily"
26 | target-branch: "main"
27 | commit-message:
28 | prefix: "chore"
29 | include: "scope"
30 | labels:
31 | - "Type: Maintenance"
32 |
33 | # Maintain dependencies for docker
34 | - package-ecosystem: "docker"
35 | directory: "/"
36 | schedule:
37 | interval: "weekly"
38 | target-branch: "main"
39 | commit-message:
40 | prefix: "chore"
41 | include: "scope"
42 | labels:
43 | - "Type: Maintenance"
44 |
--------------------------------------------------------------------------------
/.github/stale.yml:
--------------------------------------------------------------------------------
1 | # Number of days of inactivity before an issue becomes stale
2 | daysUntilStale: 14
3 |
4 | # Number of days of inactivity before a stale issue is closed
5 | daysUntilClose: 30
6 |
7 | # Issues with these labels will never be considered stale
8 | # exemptLabels:
9 | # - pinned
10 | # - security
11 |
12 | # Only issues or pull requests with all of these labels are check if stale.
13 | onlyLabels:
14 | - "Status: Abandoned"
15 | - "Type: Question"
16 |
17 | # Label to use when marking as stale
18 | staleLabel: stale
19 |
20 | # Comment to post when marking an issue as stale. Set to `false` to disable
21 | markComment: >
22 | This issue has been automatically marked as stale because it has not had
23 | activity in the past 2 weeks. It will be closed if no further activity occurs. Thank you
24 | for your contributions.
25 | # Comment to post when closing a stale issue. Set to `false` to disable
26 | closeComment: This issue is being closed after 30 days of inactivity. Thank you.
--------------------------------------------------------------------------------
/.github/workflows/build-test.yml:
--------------------------------------------------------------------------------
1 | name: 🔨 Build Test
2 | on:
3 | pull_request:
4 | workflow_dispatch:
5 |
6 | jobs:
7 | build:
8 | name: Test Builds
9 | runs-on: ${{ matrix.os }}
10 | strategy:
11 | matrix:
12 | os: [ubuntu-latest, windows-latest, macOS-latest]
13 | steps:
14 | - name: Set up Go
15 | uses: actions/setup-go@v4
16 | with:
17 | go-version: 1.20.x
18 |
19 | - name: Check out code
20 | uses: actions/checkout@v3
21 |
22 | - name: Build
23 | run: go build .
24 | working-directory: cmd/openrisk
25 |
26 | - name: Test
27 | run: go test ./...
28 | working-directory: cmd/openrisk
29 |
30 | - name: Building example
31 | # env:
32 | # OPENAI_API_KEY: ${{secrets.OPENAI_API_KEY}}
33 | run: go build .
34 | working-directory: examples/
35 |
36 |
37 |
--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | name: 🚨 CodeQL Analysis
2 |
3 | on:
4 | workflow_dispatch:
5 | pull_request:
6 | branches:
7 | - dev
8 |
9 | jobs:
10 | analyze:
11 | name: Analyze
12 | runs-on: ubuntu-latest
13 | permissions:
14 | actions: read
15 | contents: read
16 | security-events: write
17 |
18 | strategy:
19 | fail-fast: false
20 | matrix:
21 | language: [ 'go' ]
22 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
23 |
24 | steps:
25 | - name: Checkout repository
26 | uses: actions/checkout@v3
27 |
28 | # Initializes the CodeQL tools for scanning.
29 | - name: Initialize CodeQL
30 | uses: github/codeql-action/init@v2
31 | with:
32 | languages: ${{ matrix.language }}
33 |
34 | - name: Autobuild
35 | uses: github/codeql-action/autobuild@v2
36 |
37 | - name: Perform CodeQL Analysis
38 | uses: github/codeql-action/analyze@v2
--------------------------------------------------------------------------------
/.github/workflows/dockerhub-push.yml:
--------------------------------------------------------------------------------
1 | name: 🌥 Docker Push
2 |
3 | on:
4 | workflow_run:
5 | workflows: ["🎉 Release Binary"]
6 | types:
7 | - completed
8 | workflow_dispatch:
9 |
10 | jobs:
11 | docker:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - name: Git Checkout
15 | uses: actions/checkout@v3
16 |
17 | - name: Get Github tag
18 | id: meta
19 | run: |
20 | echo "::set-output name=tag::$(curl --silent "https://api.github.com/repos/projectdiscovery/openrisk/releases/latest" | jq -r .tag_name)"
21 |
22 | - name: Set up QEMU
23 | uses: docker/setup-qemu-action@v2
24 |
25 | - name: Set up Docker Buildx
26 | uses: docker/setup-buildx-action@v2
27 |
28 | - name: Login to DockerHub
29 | uses: docker/login-action@v2
30 | with:
31 | username: ${{ secrets.DOCKER_USERNAME }}
32 | password: ${{ secrets.DOCKER_TOKEN }}
33 |
34 | - name: Build and push
35 | uses: docker/build-push-action@v4
36 | with:
37 | context: .
38 | platforms: linux/amd64,linux/arm64,linux/arm
39 | push: true
40 | tags: projectdiscovery/openrisk:latest,projectdiscovery/openrisk:${{ steps.meta.outputs.tag }}
--------------------------------------------------------------------------------
/.github/workflows/lint-test.yml:
--------------------------------------------------------------------------------
1 | name: 🙏🏻 Lint Test
2 | on:
3 | pull_request:
4 | workflow_dispatch:
5 |
6 | jobs:
7 | lint:
8 | name: Lint Test
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Checkout code
12 | uses: actions/checkout@v3
13 | - name: "Set up Go"
14 | uses: actions/setup-go@v4
15 | with:
16 | go-version: 1.20.x
17 | - name: Run golangci-lint
18 | uses: golangci/golangci-lint-action@v3.4.0
19 | with:
20 | version: latest
21 | args: --timeout 5m
22 | working-directory: .
--------------------------------------------------------------------------------
/.github/workflows/release-binary.yml:
--------------------------------------------------------------------------------
1 | name: 🎉 Release Binary
2 | on:
3 | push:
4 | tags:
5 | - 'v*'
6 | workflow_dispatch:
7 |
8 | jobs:
9 | release:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: "Check out code"
13 | uses: actions/checkout@v3
14 | with:
15 | fetch-depth: 0
16 |
17 | - name: "Set up Go"
18 | uses: actions/setup-go@v4
19 | with:
20 | go-version: 1.20.x
21 |
22 | - name: "Create release on GitHub"
23 | uses: goreleaser/goreleaser-action@v4
24 | with:
25 | args: "release --rm-dist"
26 | version: latest
27 | workdir: .
28 | env:
29 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # If you prefer the allow list template instead of the deny list, see community template:
2 | # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
3 | #
4 | # Binaries for programs and plugins
5 | *.exe
6 | *.exe~
7 | *.dll
8 | *.so
9 | *.dylib
10 | openrisk
11 | !openrisk/
12 |
13 | # Test binary, built with `go test -c`
14 | *.test
15 |
16 | # Output of the go coverage tool, specifically when used with LiteIDE
17 | *.out
18 |
19 | # Dependency directories (remove the comment below to include it)
20 | # vendor/
21 |
22 | # Go workspace file
23 | go.work
24 | dist/*
25 |
26 | # IDE settings
27 | /.idea
--------------------------------------------------------------------------------
/.goreleaser.yml:
--------------------------------------------------------------------------------
1 | before:
2 | hooks:
3 | - go mod tidy
4 |
5 | builds:
6 | - binary: '{{ .ProjectName }}'
7 | main: .
8 |
9 | goos:
10 | - windows
11 | - linux
12 | - darwin
13 | goarch:
14 | - amd64
15 | - 386
16 | - arm
17 | - arm64
18 |
19 | ignore:
20 | - goos: darwin
21 | goarch: '386'
22 | - goos: windows
23 | goarch: 'arm'
24 | - goos: windows
25 | goarch: 'arm64'
26 |
27 | archives:
28 | - format: zip
29 | replacements:
30 | darwin: macOS
31 |
32 | checksum:
33 | algorithm: sha256
34 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM golang:1.18.2-alpine3.14 AS build-env
2 | RUN apk add --no-cache build-base
3 | RUN go install -v github.com/projectdiscovery/openrisk@latest
4 |
5 | FROM alpine:3.18.0
6 | RUN apk add --no-cache bind-tools ca-certificates
7 | COPY --from=build-env /go/bin/openrisk /usr/local/bin/openrisk
8 | ENTRYPOINT ["openrisk"]
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 ProjectDiscovery, Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | openrisk
3 |
4 |
5 |
6 |
7 | openrisk is an experimental tool which reads [nuclei](http://github.com/projectdiscovery/nuclei) output (text, markdown, and JSON) and generates a risk score for the host using OpenAI's GPT-3 model. It is intended, for now, to work against a single target at a time.
8 |
9 | > **NOTE**: This is an experimental program released by the ProjectDiscovery Research Team. As such, it may not meet the same code quality standards as our other projects, and may not be as well-tested. We welcome suggestions, bug fixes, and ideas on integrating these experiments into our other tools!
10 |
11 | ### Install openrisk
12 | openrisk requires **go1.20** to install successfully. Run the following command to install the latest version -
13 |
14 | ```sh
15 | go install -v github.com/projectdiscovery/openrisk@latest
16 | ```
17 |
18 | ### Usage
19 |
20 | ```sh
21 | openrisk -h
22 | ```
23 |
24 | ```console
25 | _ __
26 | ____ ____ ___ ____ _____(_)____/ /__
27 | / __ \/ __ \/ _ \/ __ \/ ___/ / ___/ //_/
28 | / /_/ / /_/ / __/ / / / / / (__ ) ,<
29 | \____/ .___/\___/_/ /_/_/ /_/____/_/|_| Powered by OpenAI (GPT-3)
30 | /_/ v0.0.1 (experimental)
31 | projectdiscovery.io
32 |
33 | openrisk is an experimental tool generates a risk score from nuclei output for the host using OpenAI's GPT-3 model.
34 |
35 | Usage:
36 | openrisk [flags]
37 |
38 | Flags:
39 | INPUT:
40 | -f, -files string[] Nuclei scan result file or directory path. Supported file extensions: .txt, .md, .jsonl
41 | ```
42 |
43 | > **NOTE**: `OPENAI_API_KEY` is required to run this program and can be obtained by signing up at `https://openai.com/api/`
44 |
45 | ### Generating Risk Score
46 |
47 | ```sh
48 | export OPENAI_API_KEY=
49 |
50 | openrisk -f nuclei_scan_result.txt
51 | ```
52 |
53 | ### Example Run:
54 |
55 | ```console
56 | openrisk -f nuclei_results.txt
57 |
58 | _ __
59 | ____ ____ ___ ____ _____(_)____/ /__
60 | / __ \/ __ \/ _ \/ __ \/ ___/ / ___/ //_/
61 | / /_/ / /_/ / __/ / / / / / (__ ) ,<
62 | \____/ .___/\___/_/ /_/_/ /_/____/_/|_| Powered by OpenAI (GPT-3)
63 | /_/ v0.0.1 (experimental)
64 |
65 | projectdiscovery.io
66 |
67 | [RISK SCORE] The 10-scale risk score for the Nuclei scan results is 10. There are multiple high-severity vulnerabilities related to Pantheon, AWS, and Netlify takeovers.
68 | ```
69 |
70 | ### Using `openrisk` as a library
71 |
72 | To utilize `openrisk` as a library, simply create an instance of the `Options` structure and input your OpenAI API key. With these options, you can then create `OpenRisk` and `IssueProcessor` by including a sample nuclei scan result file. To generate a score for the sample file, call the `openRisk.GetScore` function. For a clear example, refer to the code provided in the [examples](examples/) folder.
--------------------------------------------------------------------------------
/README_KU.md:
--------------------------------------------------------------------------------
1 | # openrisk
2 |
3 | openrisk amûrek ceribandî ye ku derketina nuclei (text û markdown) dixwîne û bi karanîna modela GPT-3 ya OpenAI-ê ji bo host xala rîskê çêdike. Armanc ew e, ji bo niha, ku di demekê de li dijî yek hostê bixebite.
4 |
5 | > **NOTE**: Ev bernameyek ceribandinê ye ku ji hêla Tîma Lêkolînê ya ProjectDiscovery ve hatî berdan. Bi vî rengî, dibe ku ew standardên kalîteya kodê wekî projeyên me yên din pêk neyne û dibe ku ew qas baş neyê ceribandin. Em pêşwaziya pêşniyaran, rastkirina xeletiyan, û ramanên li ser yekkirina van ceribandinan di nav amûrên me yên din de dikin!
6 |
7 | # openrisk saz bikin
8 | openrisk pêdivî ye ku **go1.20** bi serfirazî were saz kirin. Fermana jêrîn bicîh bikin ku guhertoya herî dawî saz bikin -
9 |
10 | ```sh
11 | go install -v github.com/projectdiscovery/openrisk
12 | ```
13 |
14 | ### Bikaranîn
15 |
16 | ```sh
17 | openrisk -h
18 | ```
19 |
20 | ```console
21 | _ __
22 | ____ ____ ___ ____ _____(_)____/ /__
23 | / __ \/ __ \/ _ \/ __ \/ ___/ / ___/ //_/
24 | / /_/ / /_/ / __/ / / / / / (__ ) ,<
25 | \____/ .___/\___/_/ /_/_/ /_/____/_/|_| Powered by OpenAI (GPT-3)
26 | /_/ v0.0.1 (experimental)
27 | projectdiscovery.io
28 |
29 | Usage:
30 | openrisk [flags]
31 |
32 | Flags:
33 | INPUT:
34 | -f, -files string[] Nuclei scan result file or directory path. Supported file extensions: .txt, .md, .jsonl
35 | ```
36 |
37 | ### Hilberîna xala riskê
38 |
39 | ```sh
40 | export OPENAI_API_KEY=
41 | openrisk -f nuclei_scan_result.txt
42 | ```
43 |
44 | Nimûne derketin:
45 |
46 | ```console
47 | openrisk -f nuclei_results.txt
48 |
49 | _ __
50 | ____ ____ ___ ____ _____(_)____/ /__
51 | / __ \/ __ \/ _ \/ __ \/ ___/ / ___/ //_/
52 | / /_/ / /_/ / __/ / / / / / (__ ) ,<
53 | \____/ .___/\___/_/ /_/_/ /_/____/_/|_| Powered by OpenAI (GPT-3)
54 | /_/ v0.0.1 (experimental)
55 |
56 | projectdiscovery.io
57 |
58 | [RISK SCORE] The 10-scale risk score for the Nuclei scan results is 10. There are multiple high-severity vulnerabilities related to Pantheon, AWS, and Netlify takeovers.
59 | ```
60 |
61 | ### `openrisk`-ê wek library bikar anîn
62 | Ji bo bikaranîna `openrisk` wek libraryê, nimûne yekê ji `Options` ava bikin û keya API'yê ya OpenAI'yê tevlî bikin. Bi tevlîkirina pelê encama skanê ya nimûneyê ya nuclei hûn dikarin `OpenRisk` û `IssueProcessor` biafirînin. Ji bo çêkirina xala rîskê ji bo pelê nimûneyê, bang fonksiyona `openRisk.GetScore` bikin. Ji bo nimûne yekê ya diyar, referansa koda ku di peldanka [examples](examples/) de hatiye dayîn bikin.
63 |
--------------------------------------------------------------------------------
/README_TR.md:
--------------------------------------------------------------------------------
1 | # openrisk
2 |
3 | openrisk, nuclei çıktısını (text ve markdown) okuyan ve OpenAI'nin GPT-3 modelini kullanarak host için bir risk puanı oluşturan deneysel bir araçtır. Şimdilik, tek seferde tek bir host -a karşı çalışması amaçlanıyor.
4 |
5 | > **NOT**: Bu, ProjectDiscovery Araştırma Ekibi tarafından yayınlanan deneysel bir programdır. Bu nedenle, diğer projelerimizle aynı kod kalite standartlarını karşılamayabilir ve iyi test edilmemiş olabilir. Önerilere, hata düzeltmelerine ve bu deneyleri diğer araçlarımıza entegre etmeye yönelik fikirlere açığız!
6 |
7 | # openrisk'i yükleyin
8 | openrisk'in başarıyla yüklenmesi için **g20** gereklidir. En son sürümü yüklemek için aşağıdaki komutu çalıştırın -
9 |
10 | ```sh
11 | go install -v github.com/projectdiscovery/openrisk
12 | ```
13 |
14 | ### Kullanım
15 |
16 | ```sh
17 | openrisk -h
18 | ```
19 |
20 | ```console
21 | _ __
22 | ____ ____ ___ ____ _____(_)____/ /__
23 | / __ \/ __ \/ _ \/ __ \/ ___/ / ___/ //_/
24 | / /_/ / /_/ / __/ / / / / / (__ ) ,<
25 | \____/ .___/\___/_/ /_/_/ /_/____/_/|_| Powered by OpenAI (GPT-3)
26 | /_/ v0.0.1 (experimental)
27 | projectdiscovery.io
28 |
29 | Usage:
30 | openrisk [flags]
31 |
32 | Flags:
33 | INPUT:
34 | -f, -files string[] Nuclei scan result file or directory path. Supported file extensions: .txt, .md, .jsonl
35 | ```
36 |
37 | ### Risk puanı oluşturma
38 |
39 | ```sh
40 | export OPENAI_API_KEY=
41 | openrisk -f nuclei_scan_result.txt
42 | ```
43 |
44 | Örnek çıktı:
45 |
46 | ```console
47 | openrisk -f nuclei_results.txt
48 |
49 | _ __
50 | ____ ____ ___ ____ _____(_)____/ /__
51 | / __ \/ __ \/ _ \/ __ \/ ___/ / ___/ //_/
52 | / /_/ / /_/ / __/ / / / / / (__ ) ,<
53 | \____/ .___/\___/_/ /_/_/ /_/____/_/|_| Powered by OpenAI (GPT-3)
54 | /_/ v0.0.1 (experimental)
55 |
56 | projectdiscovery.io
57 |
58 | [RISK SCORE] The 10-scale risk score for the Nuclei scan results is 10. There are multiple high-severity vulnerabilities related to Pantheon, AWS, and Netlify takeovers.
59 | ```
60 |
61 | ### `openrisk`'i bir kütüphane olarak kullanma
62 |
63 | `openrisk`'i bir kütüphane olarak kullanmak için, `Options` örneği oluşturun ve OpenAI API anahtarınızı girin. Bu seçeneklerle, örnek bir nuclei tarama sonuç dosyasını dahil ederek `OpenRisk` ve `IssueProcessor`'u oluşturabilirsiniz. Örnek dosya için bir puan oluşturmak için, `openRisk.GetScore` fonksiyonunu çağırın. Açık bir örnek için, [örnekler](examples/) klasöründeki sağlanan koda bakın.
64 |
--------------------------------------------------------------------------------
/cmd/openrisk/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "errors"
5 | "fmt"
6 | "os"
7 |
8 | "github.com/projectdiscovery/goflags"
9 | "github.com/projectdiscovery/gologger"
10 | "github.com/projectdiscovery/openrisk/pkg/openrisk"
11 | )
12 |
13 | var version = "0.0.1"
14 |
15 | var banner = fmt.Sprintf(`
16 | _ __
17 | ____ ____ ___ ____ _____(_)____/ /__
18 | / __ \/ __ \/ _ \/ __ \/ ___/ / ___/ //_/
19 | / /_/ / /_/ / __/ / / / / / (__ ) ,<
20 | \____/ .___/\___/_/ /_/_/ /_/____/_/|_| Powered by OpenAI (GPT-3)
21 | /_/ v%s (experimental)
22 | `, version)
23 |
24 | func printBanner() {
25 | gologger.Print().Msgf("%s\n", banner)
26 | gologger.Print().Msgf("\t\tprojectdiscovery.io\n\n")
27 | }
28 |
29 | type CliOptions struct {
30 | Files goflags.StringSlice
31 | }
32 |
33 | var cliOptions = CliOptions{}
34 |
35 | func main() {
36 | printBanner()
37 | flagSet := goflags.NewFlagSet()
38 | flagSet.SetDescription(`openrisk is an experimental tool generates a risk score from nuclei output for the host using OpenAI's GPT-3 model.`)
39 | flagSet.CreateGroup("input", "Input",
40 | flagSet.StringSliceVarP(&cliOptions.Files, "files", "f", nil, "Nuclei scan result file or directory path. Supported file extensions: .txt, .md, .jsonl", goflags.CommaSeparatedStringSliceOptions),
41 | )
42 |
43 | if err := flagSet.Parse(); err != nil {
44 | gologger.Error().Msg("could not parse flags")
45 | return
46 | }
47 |
48 | if len(cliOptions.Files) == 0 {
49 | gologger.Fatal().Msgf("no input provided")
50 | }
51 |
52 | apiKey, err := getApiKey()
53 | if err != nil {
54 | gologger.Fatal().Msgf("%s\n", err)
55 | }
56 | options := &openrisk.Options{ApiKey: apiKey}
57 | openRisk, _ := openrisk.New(options)
58 |
59 | for _, file := range cliOptions.Files {
60 | issues, err := openRisk.ParseIssuesWithFile(file)
61 | if err != nil {
62 | gologger.Error().Msgf("Could not parse issues: %v", err)
63 | }
64 |
65 | nucleiScan, _ := openRisk.GetScoreWithIssues(issues)
66 | gologger.Info().Label("RISK SCORE[" + file + "]").Msg(nucleiScan.Score)
67 | }
68 | }
69 |
70 | func getApiKey() (string, error) {
71 | apiKey := os.Getenv("OPENAI_API_KEY")
72 | if apiKey == "" {
73 | return "", errors.New("Environment variable for OPENAI_API_KEY is not set.")
74 | }
75 | return apiKey, nil
76 | }
77 |
--------------------------------------------------------------------------------
/examples/example.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "log"
6 | "os"
7 |
8 | "github.com/projectdiscovery/openrisk/pkg/openrisk"
9 | )
10 |
11 | func main() {
12 | apiKey := os.Getenv("OPENAI_API_KEY")
13 | options := &openrisk.Options{ApiKey: apiKey}
14 | openRisk, err := openrisk.New(options)
15 | if err != nil {
16 | log.Fatal(err)
17 | }
18 |
19 | file := "example_nuclei_scan.txt"
20 | issues, err := openRisk.ParseIssuesWithFile(file)
21 | if err != nil {
22 | log.Fatal(err)
23 | }
24 |
25 | nucleiScan, err := openRisk.GetScoreWithIssues(issues)
26 | if err != nil {
27 | log.Fatal(err)
28 | }
29 | fmt.Println(nucleiScan.Score)
30 | }
31 |
--------------------------------------------------------------------------------
/examples/example_nuclei_scan.txt:
--------------------------------------------------------------------------------
1 | __ _
2 | ____ __ _______/ /__ (_)
3 | / __ \/ / / / ___/ / _ \/ /
4 | / / / / /_/ / /__/ / __/ /
5 | /_/ /_/\__,_/\___/_/\___/_/ v2.8.2
6 |
7 | projectdiscovery.io
8 |
9 |
10 | [WRN] Use with caution. You are responsible for your actions.
11 | [WRN] Developers assume no liability and are not responsible for any misuse or damage.
12 | [INF] Using Nuclei Engine 2.8.2 (latest)
13 | [INF] Using Nuclei Templates 9.3.1 (latest)
14 | [INF] Templates added in last update: 2
15 | [INF] Templates loaded for scan: 14
16 | [INF] Targets loaded for scan: 6
17 | [INF] Using Interactsh Server: oast.me
18 | [open-redirect] [http] [medium] http://127.0.0.1:8082/redirect?redirect_url=https%3A%2F%2Fevil.com
19 | [reflected-xss] [http] [medium] http://127.0.0.1:8082/email?text=important_user%27%22%3E%3C32511
20 | [reflected-xss] [http] [medium] http://127.0.0.1:8082/info?another=value&name=test%27%22%3E%3C32511&random=data
21 | [reflection-ssti] [http] [medium] http://127.0.0.1:8082/email?text=important_user%7B%7B7478%2A3958%7D%7D
22 | [reflected-xss] [http] [medium] http://127.0.0.1:8082/info?name=redirected_from_url%27%22%3E%3C32511
23 | [reflected-xss] [http] [medium] http://127.0.0.1:8082/request?url=https%3A%2F%2Fexample.com%27%22%3E%3C32511
24 | [blind-ssrf] [http] [medium] http://127.0.0.1:8082/request?url=https%3A%2F%2Fce9f23fkobjp303t0ti0j5xwyddrip93y.oast.me
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/projectdiscovery/openrisk
2 |
3 | go 1.20
4 |
5 | require (
6 | github.com/projectdiscovery/goflags v0.1.8
7 | github.com/projectdiscovery/gologger v1.1.10
8 | github.com/sashabaranov/go-gpt3 v1.3.3
9 | )
10 |
11 | require (
12 | github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect
13 | github.com/aymerick/douceur v0.2.0 // indirect
14 | github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 // indirect
15 | github.com/dsnet/compress v0.0.1 // indirect
16 | github.com/golang/snappy v0.0.1 // indirect
17 | github.com/google/go-cmp v0.5.9 // indirect
18 | github.com/gorilla/css v1.0.0 // indirect
19 | github.com/json-iterator/go v1.1.12 // indirect
20 | github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
21 | github.com/mholt/archiver v3.1.1+incompatible // indirect
22 | github.com/microcosm-cc/bluemonday v1.0.21 // indirect
23 | github.com/miekg/dns v1.1.50 // indirect
24 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
25 | github.com/modern-go/reflect2 v1.0.2 // indirect
26 | github.com/nwaples/rardecode v1.1.0 // indirect
27 | github.com/pierrec/lz4 v2.6.0+incompatible // indirect
28 | github.com/pkg/errors v0.9.1 // indirect
29 | github.com/projectdiscovery/utils v0.0.4-0.20221214110533-9f95ee986a54 // indirect
30 | github.com/rogpeppe/go-internal v1.9.0 // indirect
31 | github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca // indirect
32 | github.com/ulikunitz/xz v0.5.11 // indirect
33 | github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
34 | golang.org/x/exp v0.0.0-20221019170559-20944726eadf // indirect
35 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
36 | golang.org/x/net v0.7.0 // indirect
37 | golang.org/x/sys v0.5.0 // indirect
38 | golang.org/x/tools v0.1.12 // indirect
39 | gopkg.in/djherbis/times.v1 v1.3.0 // indirect
40 | gopkg.in/yaml.v3 v3.0.1 // indirect
41 | )
42 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ=
2 | github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
3 | github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
4 | github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
5 | github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 h1:ox2F0PSMlrAAiAdknSRMDrAr8mfxPCfSZolH+/qQnyQ=
6 | github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08/go.mod h1:pCxVEbcm3AMg7ejXyorUXi6HQCzOIBf7zEDVPtw0/U4=
7 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
8 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
9 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
10 | github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q=
11 | github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo=
12 | github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
13 | github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY=
14 | github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
15 | github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
16 | github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
17 | github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
18 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
19 | github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
20 | github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
21 | github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
22 | github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
23 | github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
24 | github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
25 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
26 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
27 | github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
28 | github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
29 | github.com/mholt/archiver v3.1.1+incompatible h1:1dCVxuqs0dJseYEhi5pl7MYPH9zDa1wBi7mF09cbNkU=
30 | github.com/mholt/archiver v3.1.1+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1TwETms9B8CTWfeh7ROU=
31 | github.com/microcosm-cc/bluemonday v1.0.21 h1:dNH3e4PSyE4vNX+KlRGHT5KrSvjeUkoNPwEORjffHJg=
32 | github.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM=
33 | github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
34 | github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
35 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
36 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
37 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
38 | github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
39 | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
40 | github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ=
41 | github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
42 | github.com/pierrec/lz4 v2.6.0+incompatible h1:Ix9yFKn1nSPBLFl/yZknTp8TU5G4Ps0JDmguYK6iH1A=
43 | github.com/pierrec/lz4 v2.6.0+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
44 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
45 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
46 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
47 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
48 | github.com/projectdiscovery/goflags v0.1.8 h1:Urhm2Isq2BdRt8h4h062lHKYXO65RHRjGTDSkUwex/g=
49 | github.com/projectdiscovery/goflags v0.1.8/go.mod h1:Yxi9tclgwGczzDU65ntrwaIql5cXeTvW5j2WxFuF+Jk=
50 | github.com/projectdiscovery/gologger v1.1.10 h1:XNRdtzLTdxiFGuK9gutoL752mykzXDoii4P2yDovqck=
51 | github.com/projectdiscovery/gologger v1.1.10/go.mod h1:VqANHK7qcEq3i6/vV5HNWwdyv2aFPSrlaVDU4Ogrc6U=
52 | github.com/projectdiscovery/utils v0.0.4-0.20221214110533-9f95ee986a54 h1:/fZvw6gT1fzdmMLMBBw75OrJ0Z6g7dulQrxM9FRp1qU=
53 | github.com/projectdiscovery/utils v0.0.4-0.20221214110533-9f95ee986a54/go.mod h1:PCwA5YuCYWPgHaGiZmr53/SA9iGQmAnw7DSHuhr8VPQ=
54 | github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
55 | github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
56 | github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca h1:NugYot0LIVPxTvN8n+Kvkn6TrbMyxQiuvKdEwFdR9vI=
57 | github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
58 | github.com/sashabaranov/go-gpt3 v1.3.3 h1:S8Zd4YybnBaNMK+w+XGGWgsjQY1R+6QE2n9SLzVna9k=
59 | github.com/sashabaranov/go-gpt3 v1.3.3/go.mod h1:BIZdbwdzxZbCrcKGMGH6u2eyGe1xFuX9Anmh3tCP8lQ=
60 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
61 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
62 | github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
63 | github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
64 | github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
65 | github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
66 | github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
67 | github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
68 | github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
69 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
70 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
71 | golang.org/x/exp v0.0.0-20221019170559-20944726eadf h1:nFVjjKDgNY37+ZSYCJmtYf7tOlfQswHqplG2eosjOMg=
72 | golang.org/x/exp v0.0.0-20221019170559-20944726eadf/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
73 | golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
74 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
75 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
76 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
77 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
78 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
79 | golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
80 | golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
81 | golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
82 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
83 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
84 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
85 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
86 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
87 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
88 | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
89 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
90 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
91 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
92 | golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
93 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
94 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
95 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
96 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
97 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
98 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
99 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
100 | golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
101 | golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
102 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
103 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
104 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
105 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
106 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
107 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
108 | gopkg.in/djherbis/times.v1 v1.3.0 h1:uxMS4iMtH6Pwsxog094W0FYldiNnfY/xba00vq6C2+o=
109 | gopkg.in/djherbis/times.v1 v1.3.0/go.mod h1:AQlg6unIsrsCEdQYhTzERy542dz6SFdQFZFv6mUY0P8=
110 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
111 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
112 |
--------------------------------------------------------------------------------
/pkg/openrisk/issue_processor.go:
--------------------------------------------------------------------------------
1 | package openrisk
2 |
3 | import (
4 | "fmt"
5 | "os"
6 | "path/filepath"
7 | "strings"
8 |
9 | "github.com/projectdiscovery/gologger"
10 | )
11 |
12 | func (o *OpenRisk) ParseIssuesWithFile(path string) (string, error) {
13 | var issues strings.Builder
14 |
15 | err := filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
16 | if err != nil {
17 | gologger.Error().Msgf("Invalid filename or directory: %v", err)
18 | return err
19 | }
20 | if !info.IsDir() {
21 | issue, err := processFile(path)
22 | if err != nil {
23 | return err
24 | }
25 | issues.WriteString(issue)
26 | }
27 | return nil
28 | })
29 | return issues.String(), err
30 | }
31 |
32 | func processFile(path string) (string, error) {
33 | nucleiScanResult, err := os.ReadFile(path)
34 | if err != nil {
35 | return "", fmt.Errorf("Could not read the nuclei scan result: %v", err)
36 | }
37 |
38 | ext := filepath.Ext(path)
39 | switch ext {
40 | case ".jsonl":
41 | return ParseJsonL(nucleiScanResult)
42 | case ".md":
43 | return ParseMarkdown(nucleiScanResult)
44 | case ".txt":
45 | return string(nucleiScanResult), nil
46 | default:
47 | return "", fmt.Errorf("Unknown file type: %v", path)
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/pkg/openrisk/jsonl_parser.go:
--------------------------------------------------------------------------------
1 | package openrisk
2 |
3 | import (
4 | "bufio"
5 | "encoding/json"
6 | "errors"
7 | "fmt"
8 | "strings"
9 | )
10 |
11 | func ParseJsonL(nucleiScanResult []byte) (string, error) {
12 | // Initialize the empty results string. This will be in the format "template_name,severity\n" to match the resulting
13 | // string from the Markdown parsing in parseMD()
14 | results := ""
15 |
16 | var errs []error
17 |
18 | // Loop through the lines of the file and parse each row as a JSON object as Nuclei exports the json
19 | // file as a JSON-line file
20 | scanner := bufio.NewScanner(strings.NewReader(string(nucleiScanResult)))
21 | for scanner.Scan() {
22 | line := scanner.Text()
23 | // Set the default and minimally required fields for the NucleiResult struct that are utilized in the result
24 | // parsing below
25 | result := NucleiResult{
26 | Info: NucleiInfo{
27 | Name: "",
28 | Severity: "",
29 | },
30 | }
31 | //var result NucleiResult
32 | err := json.Unmarshal([]byte(line), &result)
33 | if err != nil {
34 | errs = append(errs, err)
35 | continue
36 | }
37 | results += fmt.Sprintf("%s,%s\n", result.Info.Name, result.Info.Severity)
38 | }
39 |
40 | return results, errors.Join(errs...)
41 | }
42 |
--------------------------------------------------------------------------------
/pkg/openrisk/markdown_parser.go:
--------------------------------------------------------------------------------
1 | package openrisk
2 |
3 | import (
4 | "bufio"
5 | "regexp"
6 | "strings"
7 | )
8 |
9 | func ParseMarkdown(nucleiScanResult []byte) (string, error) {
10 | rName := regexp.MustCompile(`^\| Name \|\s*(.*)\s*\|$`)
11 | rSev := regexp.MustCompile(`^\| Severity \|\s*(.*)\s*\|$`)
12 | results := make(map[string]string)
13 | results["details"] = ""
14 | results["severity"] = "unknown"
15 |
16 | scanner := bufio.NewScanner(strings.NewReader(string(nucleiScanResult)))
17 | for scanner.Scan() {
18 | line := scanner.Text()
19 | mName := rName.FindStringSubmatch(line)
20 | if len(mName) > 0 {
21 | results["details"] = strings.TrimSpace(mName[1])
22 | continue
23 | }
24 |
25 | mSev := rSev.FindStringSubmatch(line)
26 | if len(mSev) > 0 {
27 | results["severity"] = strings.TrimSpace(mSev[1])
28 | continue
29 | }
30 |
31 | if mSev != nil && mName != nil {
32 | break
33 | }
34 | }
35 |
36 | return results["details"] + "," + results["severity"] + "\n", nil
37 | }
38 |
--------------------------------------------------------------------------------
/pkg/openrisk/openrisk.go:
--------------------------------------------------------------------------------
1 | package openrisk
2 |
3 | import (
4 | "bufio"
5 | "context"
6 | "errors"
7 | "regexp"
8 | "strings"
9 |
10 | gogpt "github.com/sashabaranov/go-gpt3"
11 | )
12 |
13 | const Question = "Calculate the 10-scale risk score for the following Nuclei scan results. The format of the CSV is 'finding,severity'. Write an executive summary of vulnerabilities with 30 words max."
14 |
15 | func New(options *Options) (*OpenRisk, error) {
16 | if options.ApiKey == "" {
17 | return nil, errors.New("api key not defined")
18 | }
19 | gptClient := gogpt.NewClient(options.ApiKey)
20 | openRisk := &OpenRisk{
21 | Options: options,
22 | client: gptClient,
23 | }
24 | return openRisk, nil
25 |
26 | }
27 |
28 | func (o *OpenRisk) GetScoreWithIssues(scanIssues string) (NucleiScan, error) {
29 | issues := reduceTokens(scanIssues)
30 | if len(issues) == 0 {
31 | return NucleiScan{Issues: scanIssues, Score: "Risk Score: 0 \nExecutive Summary: No vulnerabilities found."}, nil
32 | }
33 |
34 | prompt := buildPrompt(issues)
35 | req := buildRequest(prompt)
36 | resp, err := o.makeRequest(req)
37 | if err != nil {
38 | return NucleiScan{}, err
39 | }
40 | if len(resp.Choices) == 0 {
41 | return NucleiScan{}, errors.New("no choices returned")
42 | }
43 | return NucleiScan{Issues: scanIssues, Score: strings.TrimSpace(resp.Choices[0].Text)}, nil
44 | }
45 |
46 | func (o *OpenRisk) makeRequest(req gogpt.CompletionRequest) (gogpt.CompletionResponse, error) {
47 | return o.client.CreateCompletion(context.Background(), req)
48 | }
49 |
50 | func buildRequest(prompt string) gogpt.CompletionRequest {
51 | req := gogpt.CompletionRequest{
52 | Model: "text-davinci-003",
53 | Temperature: 0.01, // FIXME: https://github.com/sashabaranov/go-gpt3/issues/9
54 | TopP: 1,
55 | FrequencyPenalty: 0.01,
56 | PresencePenalty: 0.01,
57 | BestOf: 1,
58 | MaxTokens: 256,
59 | Prompt: prompt,
60 | }
61 | return req
62 | }
63 |
64 | func buildPrompt(nucleiScanResult string) string {
65 | var sb strings.Builder
66 | sb.WriteString(Question)
67 | sb.WriteString("\n")
68 | sb.WriteString(nucleiScanResult)
69 | return sb.String()
70 | }
71 |
72 | func reduceTokens(issues string) string {
73 | var sb strings.Builder
74 | dateRegex := regexp.MustCompile(`^\[\d{4}\-\d{2}\-\d{2} \d{2}:\d{2}:\d{2}\] `)
75 | urlRegex := regexp.MustCompile(`(https?:\/\/)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#()?&//=]*)`)
76 | csvRegex := regexp.MustCompile(`\] \[?`)
77 | skipTxtRegex := regexp.MustCompile(`^(\[INF]|\[WRN]|\[ERR]|\[DBG]|\[FTL]|\s|\/|\\|\d)`)
78 | txtLine := regexp.MustCompile("^.*,.*,")
79 | scanner := bufio.NewScanner(strings.NewReader(issues))
80 | for scanner.Scan() {
81 | line := scanner.Text()
82 |
83 | // Skip lines that start with space, \, or [ but not [YYYY-MM-DD HH:MM:SS] (txt)
84 | if skipTxtRegex.MatchString(line) {
85 | continue
86 | }
87 |
88 | // Remove the date and URL
89 | line = dateRegex.ReplaceAllString(line, "")
90 | line = urlRegex.ReplaceAllString(line, "")
91 |
92 | // Make it CSV
93 | line = csvRegex.ReplaceAllString(line, ",")
94 | line = strings.Trim(line, "[],")
95 |
96 | // Remove the protocol (txt)
97 | if txtLine.MatchString(line) {
98 | parts := strings.Split(line, ",")
99 | line = parts[0] + "," + parts[2]
100 |
101 | }
102 |
103 | // Skip info/unknown lines as they don't impact the score (md)
104 | if strings.HasSuffix(line, "info") || strings.HasSuffix(line, "unknown") {
105 | continue
106 | }
107 |
108 | // Skip lines that don't have 2 commas as it's not a valid vulnerability
109 | if strings.Count(line, ",") < 1 {
110 | continue
111 | }
112 | sb.WriteString(line + "\n")
113 | }
114 | return sb.String()
115 | }
116 |
--------------------------------------------------------------------------------
/pkg/openrisk/types.go:
--------------------------------------------------------------------------------
1 | package openrisk
2 |
3 | import gogpt "github.com/sashabaranov/go-gpt3"
4 |
5 | type OpenRisk struct {
6 | Options *Options
7 | client *gogpt.Client
8 | }
9 |
10 | type Options struct {
11 | ApiKey string
12 | }
13 |
14 | type NucleiScan struct {
15 | Issues string
16 | Score string
17 | }
18 |
19 | // The JSON types do not define the entire structure of the JSON object that is exported by Nuclei, but rather only
20 | // the fields that are used in the issue list generation. This reduces the amount of data that is parsed from the JSON
21 | // file as well as reducing the risk of a change in the Nuclei JSON export format breaking the issue list generation.
22 |
23 | type NucleiInfo struct {
24 | Name string `json:"name,omitempty"`
25 | Severity string `json:"severity,omitempty"`
26 | }
27 |
28 | type NucleiResult struct {
29 | Info NucleiInfo
30 | }
31 |
--------------------------------------------------------------------------------