mirror of
https://github.com/lunchcat/sif.git
synced 2026-06-21 22:31:46 -07:00
Compare commits
111 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e1f35e4883 | |||
| d31560ba08 | |||
| 6b5a471888 | |||
| 342c2be12b | |||
| bdac709437 | |||
| 7d863fe8ff | |||
| 08874762ba | |||
| 662994caf1 | |||
| d5d3178783 | |||
| 32acf6b445 | |||
| cbcc4f43dc | |||
| afe55f36ee | |||
| 2ea412b04d | |||
| 60b2dd2804 | |||
| 73af6bc868 | |||
| 88fb01d70a | |||
| d98a1c4e84 | |||
| 8c4d6d81a7 | |||
| b6ad6f7a3e | |||
| 26ea7c0ee6 | |||
| 976a2d4390 | |||
| c62409bf0a | |||
| 2f288c4eb6 | |||
| 280e6ad8b0 | |||
| 1f808bbea3 | |||
| 2ee2283412 | |||
| 748f320e59 | |||
| ad9a98b132 | |||
| 6d6a57a0e0 | |||
| 53687e4bd4 | |||
| 4331929bd0 | |||
| c9497abfcb | |||
| 9290bbe6a0 | |||
| 0958a2c19c | |||
| 4e97da6863 | |||
| e5c88b754c | |||
| 2389901614 | |||
| 1f73a0dd8f | |||
| 4de9786e99 | |||
| e5510a4a16 | |||
| 8928ac7e99 | |||
| 137ba0c89a | |||
| 9ea0805090 | |||
| df6bfc91f0 | |||
| 255b67dff6 | |||
| 9c3a5fe1f0 | |||
| df274328ee | |||
| 487b440e52 | |||
| bf613c3aaf | |||
| 2922481be3 | |||
| e27476652f | |||
| 5ffea24182 | |||
| 67288577a6 | |||
| 7beb68e145 | |||
| d2f3a42c43 | |||
| c33896a45a | |||
| 652f4f0c7c | |||
| bf65820ff1 | |||
| 0d4c10e6ff | |||
| 0eba16bc4d | |||
| c067eafed0 | |||
| f20198dd26 | |||
| a86f117658 | |||
| a614b2ee8a | |||
| a8686c1e4a | |||
| c3f824e1e3 | |||
| 57acc6d37c | |||
| 2596ce1ea2 | |||
| abce1405ca | |||
| f212aed50a | |||
| 7e27e73554 | |||
| da645ee42f | |||
| 16c191fbaa | |||
| 697c7def57 | |||
| ff002f43f7 | |||
| 30482ecbce | |||
| ce07ac8b16 | |||
| 8b056231f7 | |||
| c517e2eb1f | |||
| 0dd533446a | |||
| 1c0ad454dc | |||
| 17aa3c00f0 | |||
| b6b0a5a782 | |||
| 24b3b43b57 | |||
| 1550202e7a | |||
| a8eb319efe | |||
| 43d5f7383b | |||
| 1447485af9 | |||
| 6e1d5cf488 | |||
| 1583e00478 | |||
| 40db023632 | |||
| 5868deef21 | |||
| b43e54bf60 | |||
| c75ebccb27 | |||
| 858555bc47 | |||
| 51ee65c5df | |||
| 035e9406d9 | |||
| ba5468725e | |||
| 49b081dc30 | |||
| 127eeff265 | |||
| 1b493e9572 | |||
| 74b044ce59 | |||
| 2a2bcf5b92 | |||
| 166e1b82c2 | |||
| be9c02e8ba | |||
| 018af224d6 | |||
| 97aeb4c8b0 | |||
| 2d38d3fea5 | |||
| 3df0064e4b | |||
| c20c37463a | |||
| 9190fa4741 |
@@ -1,44 +0,0 @@
|
||||
ci:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: ".github/**"
|
||||
|
||||
deps:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "go.mod"
|
||||
- "go.sum"
|
||||
- "flake.nix"
|
||||
- "flake.lock"
|
||||
|
||||
scan:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "internal/scan/**"
|
||||
|
||||
nuclei:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "internal/nuclei/**"
|
||||
|
||||
modules:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "internal/modules/**"
|
||||
- "internal/scan/builtin/**"
|
||||
- "internal/scan/js/**"
|
||||
- "modules/**"
|
||||
|
||||
docs:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "**/*.md"
|
||||
- "docs/**"
|
||||
|
||||
tests:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "**/*_test.go"
|
||||
|
||||
config:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "internal/config/**"
|
||||
- ".golangci.yml"
|
||||
- ".editorconfig"
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout the latest code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: automatic rebase
|
||||
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
name: check for large files
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: check for large files
|
||||
run: |
|
||||
large_files=$(find . -path ./.git -prune -o -type f -size +5M -print)
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
name: code quality
|
||||
|
||||
name: qodana
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
schedule:
|
||||
- cron: "0 6 * * 1" # monday 06:00 UTC
|
||||
|
||||
permissions: {}
|
||||
|
||||
@@ -16,24 +13,18 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
codeql:
|
||||
qodana:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
contents: read
|
||||
contents: write
|
||||
pull-requests: write
|
||||
checks: write
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: set up go
|
||||
uses: actions/setup-go@v5
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
go-version: "1.25"
|
||||
- name: initialize codeql
|
||||
uses: github/codeql-action/init@v4
|
||||
with:
|
||||
languages: go
|
||||
- name: build
|
||||
run: go build ./...
|
||||
- name: perform codeql analysis
|
||||
uses: github/codeql-action/analyze@v4
|
||||
with:
|
||||
category: "/language:go"
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
- name: 'Qodana Scan'
|
||||
uses: JetBrains/qodana-action@v2024.3
|
||||
env:
|
||||
QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
|
||||
|
||||
@@ -16,9 +16,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
- name: dependency review
|
||||
uses: actions/dependency-review-action@v5
|
||||
uses: actions/dependency-review-action@v4
|
||||
continue-on-error: ${{ github.event_name == 'push' }}
|
||||
- name: check dependency review outcome
|
||||
if: github.event_name == 'push' && failure()
|
||||
|
||||
+10
-11
@@ -17,25 +17,25 @@ jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: set up go
|
||||
uses: actions/setup-go@v6
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.25"
|
||||
go-version: "1.24"
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v8
|
||||
uses: golangci/golangci-lint-action@v6
|
||||
with:
|
||||
version: v2.11.4
|
||||
version: latest
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: ["1.25"]
|
||||
go-version: ["1.23", "1.24"]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: set up go
|
||||
uses: actions/setup-go@v6
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
- name: build
|
||||
@@ -43,9 +43,8 @@ jobs:
|
||||
- name: run tests with coverage
|
||||
run: go test -race -coverprofile=coverage.out -covermode=atomic ./...
|
||||
- name: upload coverage to codecov
|
||||
uses: codecov/codecov-action@v6
|
||||
if: matrix.go-version == '1.24'
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
files: ./coverage.out
|
||||
fail_ci_if_error: false
|
||||
- name: run integration tests
|
||||
run: go test -tags=integration -race ./internal/scan/...
|
||||
|
||||
@@ -15,11 +15,11 @@ jobs:
|
||||
govulncheck:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: set up go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.25"
|
||||
go-version: "1.24"
|
||||
- name: install govulncheck
|
||||
run: go install golang.org/x/vuln/cmd/govulncheck@v1.1.4
|
||||
- name: run govulncheck
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
check-headers:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: check license headers
|
||||
run: |
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
echo ': █▀ █ █▀▀ · Blazing-fast pentesting suite :'
|
||||
echo ': ▄█ █ █▀ · BSD 3-Clause License :'
|
||||
echo ': :'
|
||||
echo ': (c) 2022-2026 vmfunc, xyzeva, :'
|
||||
echo ': (c) 2022-2025 vmfunc (vmfunc), xyzeva, :'
|
||||
echo ': lunchcat alumni & contributors :'
|
||||
echo ': :'
|
||||
echo '·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·'
|
||||
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
name: profanity check
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
- name: Profanity check step
|
||||
uses: tailaiw/mind-your-language-action@v1.0.3
|
||||
env:
|
||||
|
||||
@@ -14,9 +14,9 @@ jobs:
|
||||
name: runner / markdownlint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: markdownlint
|
||||
uses: reviewdog/action-markdownlint@v0.26.2
|
||||
uses: reviewdog/action-markdownlint@v0.24.0
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
reporter: github-pr-review
|
||||
|
||||
@@ -18,9 +18,9 @@ jobs:
|
||||
name: runner / misspell
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: misspell
|
||||
uses: reviewdog/action-misspell@v1.27.0
|
||||
uses: reviewdog/action-misspell@v1.26.0
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
reporter: github-pr-review
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
name: pr bot
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, edited]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
label:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/labeler@v6
|
||||
with:
|
||||
configuration-path: .github/labeler.yml
|
||||
|
||||
size:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: label pr size
|
||||
uses: actions/github-script@v9
|
||||
with:
|
||||
script: |
|
||||
const { data: files } = await github.rest.pulls.listFiles({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: context.payload.pull_request.number,
|
||||
per_page: 100,
|
||||
});
|
||||
|
||||
const changes = files.reduce((sum, f) => sum + f.additions + f.deletions, 0);
|
||||
|
||||
let size;
|
||||
if (changes < 10) size = "size/xs";
|
||||
else if (changes < 50) size = "size/s";
|
||||
else if (changes < 200) size = "size/m";
|
||||
else if (changes < 500) size = "size/l";
|
||||
else size = "size/xl";
|
||||
|
||||
const sizeLabels = ["size/xs", "size/s", "size/m", "size/l", "size/xl"];
|
||||
const currentLabels = context.payload.pull_request.labels.map(l => l.name);
|
||||
const toRemove = currentLabels.filter(l => sizeLabels.includes(l) && l !== size);
|
||||
|
||||
for (const label of toRemove) {
|
||||
await github.rest.issues.removeLabel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.payload.pull_request.number,
|
||||
name: label,
|
||||
}).catch(() => {});
|
||||
}
|
||||
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.payload.pull_request.number,
|
||||
labels: [size],
|
||||
});
|
||||
|
||||
ci-summary:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [label, size]
|
||||
if: always()
|
||||
steps:
|
||||
- uses: actions/github-script@v9
|
||||
with:
|
||||
script: |
|
||||
const pr = context.payload.pull_request;
|
||||
const { data: checks } = await github.rest.checks.listForRef({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
ref: pr.head.sha,
|
||||
per_page: 100,
|
||||
});
|
||||
|
||||
const { data: files } = await github.rest.pulls.listFiles({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: pr.number,
|
||||
per_page: 100,
|
||||
});
|
||||
|
||||
const additions = files.reduce((sum, f) => sum + f.additions, 0);
|
||||
const deletions = files.reduce((sum, f) => sum + f.deletions, 0);
|
||||
const fileCount = files.length;
|
||||
|
||||
let body = `### pr summary\n\n`;
|
||||
body += `**${fileCount}** files changed (+${additions} -${deletions})\n\n`;
|
||||
|
||||
const goFiles = files.filter(f => f.filename.endsWith('.go')).length;
|
||||
const testFiles = files.filter(f => f.filename.endsWith('_test.go')).length;
|
||||
const ciFiles = files.filter(f => f.filename.startsWith('.github/')).length;
|
||||
const modFiles = files.filter(f => f.filename === 'go.mod' || f.filename === 'go.sum').length;
|
||||
|
||||
if (goFiles > 0 || testFiles > 0 || ciFiles > 0 || modFiles > 0) {
|
||||
body += `| category | files |\n|----------|-------|\n`;
|
||||
if (goFiles > 0) body += `| go source | ${goFiles} |\n`;
|
||||
if (testFiles > 0) body += `| tests | ${testFiles} |\n`;
|
||||
if (ciFiles > 0) body += `| ci/workflows | ${ciFiles} |\n`;
|
||||
if (modFiles > 0) body += `| deps | ${modFiles} |\n`;
|
||||
body += `\n`;
|
||||
}
|
||||
|
||||
// find existing bot comment
|
||||
const { data: comments } = await github.rest.issues.listComments({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
});
|
||||
|
||||
const marker = '<!-- sif-pr-bot -->';
|
||||
body = marker + '\n' + body;
|
||||
|
||||
const existing = comments.find(c =>
|
||||
c.user.type === 'Bot' && c.body.includes(marker)
|
||||
);
|
||||
|
||||
if (existing) {
|
||||
await github.rest.issues.updateComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
comment_id: existing.id,
|
||||
body,
|
||||
});
|
||||
} else {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
body,
|
||||
});
|
||||
}
|
||||
@@ -2,8 +2,7 @@ name: release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
branches: [main]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
@@ -19,30 +18,27 @@ jobs:
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: set up go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.25"
|
||||
|
||||
- name: extract version
|
||||
run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV
|
||||
go-version: "1.24"
|
||||
|
||||
- name: build for windows
|
||||
run: |
|
||||
GOOS=windows GOARCH=amd64 go build -ldflags="-s -w -X main.version=${{ env.VERSION }}" -o sif-windows-amd64.exe ./cmd/sif
|
||||
GOOS=windows GOARCH=386 go build -ldflags="-s -w -X main.version=${{ env.VERSION }}" -o sif-windows-386.exe ./cmd/sif
|
||||
GOOS=windows GOARCH=amd64 go build -o sif-windows-amd64.exe ./cmd/sif
|
||||
GOOS=windows GOARCH=386 go build -o sif-windows-386.exe ./cmd/sif
|
||||
|
||||
- name: build for macOS
|
||||
run: |
|
||||
GOOS=darwin GOARCH=amd64 go build -ldflags="-s -w -X main.version=${{ env.VERSION }}" -o sif-macos-amd64 ./cmd/sif
|
||||
GOOS=darwin GOARCH=arm64 go build -ldflags="-s -w -X main.version=${{ env.VERSION }}" -o sif-macos-arm64 ./cmd/sif
|
||||
GOOS=darwin GOARCH=amd64 go build -o sif-macos-amd64 ./cmd/sif
|
||||
GOOS=darwin GOARCH=arm64 go build -o sif-macos-arm64 ./cmd/sif
|
||||
|
||||
- name: build for linux
|
||||
run: |
|
||||
GOOS=linux GOARCH=amd64 go build -ldflags="-s -w -X main.version=${{ env.VERSION }}" -o sif-linux-amd64 ./cmd/sif
|
||||
GOOS=linux GOARCH=386 go build -ldflags="-s -w -X main.version=${{ env.VERSION }}" -o sif-linux-386 ./cmd/sif
|
||||
GOOS=linux GOARCH=arm64 go build -ldflags="-s -w -X main.version=${{ env.VERSION }}" -o sif-linux-arm64 ./cmd/sif
|
||||
GOOS=linux GOARCH=amd64 go build -o sif-linux-amd64 ./cmd/sif
|
||||
GOOS=linux GOARCH=386 go build -o sif-linux-386 ./cmd/sif
|
||||
GOOS=linux GOARCH=arm64 go build -o sif-linux-arm64 ./cmd/sif
|
||||
|
||||
- name: package releases with modules
|
||||
run: |
|
||||
@@ -61,6 +57,8 @@ jobs:
|
||||
|
||||
- name: build debian packages
|
||||
run: |
|
||||
VERSION="0.1.0-$(git rev-parse --short HEAD)"
|
||||
|
||||
declare -A arch_map=(
|
||||
["sif-linux-amd64"]="amd64"
|
||||
["sif-linux-386"]="i386"
|
||||
@@ -69,7 +67,7 @@ jobs:
|
||||
|
||||
for binary in sif-linux-amd64 sif-linux-386 sif-linux-arm64; do
|
||||
arch="${arch_map[$binary]}"
|
||||
pkg_dir="sif_${{ env.VERSION }}_${arch}"
|
||||
pkg_dir="sif_${VERSION}_${arch}"
|
||||
|
||||
mkdir -p "${pkg_dir}/DEBIAN"
|
||||
mkdir -p "${pkg_dir}/usr/bin"
|
||||
@@ -81,11 +79,11 @@ jobs:
|
||||
|
||||
cat > "${pkg_dir}/DEBIAN/control" << EOF
|
||||
Package: sif
|
||||
Version: ${{ env.VERSION }}
|
||||
Version: ${VERSION}
|
||||
Section: security
|
||||
Priority: optional
|
||||
Architecture: ${arch}
|
||||
Maintainer: vmfunc <celeste@linux.com>
|
||||
Maintainer: vmfunc <celeste@router.sex>
|
||||
Homepage: https://github.com/vmfunc/sif
|
||||
Description: Modular pentesting toolkit
|
||||
sif is a fast, concurrent, and extensible pentesting toolkit written in Go.
|
||||
@@ -115,71 +113,41 @@ jobs:
|
||||
artifact-name: sbom.spdx.json
|
||||
output-file: sbom.spdx.json
|
||||
|
||||
- name: generate changelog
|
||||
id: changelog
|
||||
uses: actions/github-script@v9
|
||||
- name: set release version
|
||||
run: echo "RELEASE_VERSION=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
|
||||
|
||||
- name: create release and upload assets
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
result-encoding: string
|
||||
script: |
|
||||
const { data: releases } = await github.rest.repos.listReleases({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
per_page: 1,
|
||||
});
|
||||
|
||||
const prev = releases.length > 0 ? releases[0].tag_name : '';
|
||||
const range = prev ? `${prev}...${context.ref}` : '';
|
||||
|
||||
const { data: commits } = await github.rest.repos.compareCommitsWithBasehead({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
basehead: prev ? `${prev}...${{ github.ref_name }}` : `${{ github.sha }}~10...${{ github.sha }}`,
|
||||
}).catch(() => ({ data: { commits: [] } }));
|
||||
|
||||
let log = '';
|
||||
for (const c of commits.commits || []) {
|
||||
const msg = c.commit.message.split('\n')[0];
|
||||
const sha = c.sha.substring(0, 7);
|
||||
log += `- ${msg} (${sha})\n`;
|
||||
}
|
||||
|
||||
return log || 'initial release';
|
||||
|
||||
- name: create release
|
||||
uses: softprops/action-gh-release@v3
|
||||
with:
|
||||
name: sif v${{ env.VERSION }}
|
||||
tag_name: automated-release-${{ env.RELEASE_VERSION }}
|
||||
name: Release ${{ env.RELEASE_VERSION }}
|
||||
body: |
|
||||
## what's changed
|
||||
Automated release v${{ env.RELEASE_VERSION }}
|
||||
|
||||
${{ steps.changelog.outputs.result }}
|
||||
## Assets
|
||||
|
||||
## install
|
||||
Each archive contains the sif binary and built-in modules.
|
||||
|
||||
**homebrew / linuxbrew**
|
||||
```bash
|
||||
# coming soon
|
||||
```
|
||||
- Windows (64-bit): `sif-windows-amd64.zip`
|
||||
- Windows (32-bit): `sif-windows-386.zip`
|
||||
- macOS (64-bit Intel): `sif-macos-amd64.tar.gz`
|
||||
- macOS (64-bit ARM): `sif-macos-arm64.tar.gz`
|
||||
- Linux (64-bit): `sif-linux-amd64.tar.gz`
|
||||
- Linux (32-bit): `sif-linux-386.tar.gz`
|
||||
- Linux (64-bit ARM): `sif-linux-arm64.tar.gz`
|
||||
- Debian/Ubuntu (64-bit): `sif_*_amd64.deb`
|
||||
- Debian/Ubuntu (32-bit): `sif_*_i386.deb`
|
||||
- Debian/Ubuntu (64-bit ARM): `sif_*_arm64.deb`
|
||||
|
||||
**debian / ubuntu**
|
||||
```bash
|
||||
sudo dpkg -i sif_${{ env.VERSION }}_amd64.deb
|
||||
```
|
||||
|
||||
**go install**
|
||||
```bash
|
||||
go install github.com/dropalldatabases/sif/cmd/sif@v${{ env.VERSION }}
|
||||
```
|
||||
|
||||
**binary download** - grab the right archive from below.
|
||||
|
||||
## verification
|
||||
## Verification
|
||||
|
||||
```bash
|
||||
sha256sum -c checksums-sha256.txt
|
||||
```
|
||||
|
||||
For more details, check the [commit history](https://github.com/${{ github.repository }}/commits/main).
|
||||
draft: false
|
||||
prerelease: ${{ contains(github.ref_name, '-') }}
|
||||
prerelease: false
|
||||
files: |
|
||||
sif-windows-amd64.zip
|
||||
sif-windows-386.zip
|
||||
@@ -197,7 +165,6 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: push to cloudsmith
|
||||
if: ${{ !contains(github.ref_name, '-') }}
|
||||
env:
|
||||
CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }}
|
||||
run: |
|
||||
|
||||
@@ -18,6 +18,6 @@ jobs:
|
||||
update-report-card:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: update go report card
|
||||
uses: creekorful/goreportcard-action@v1.0
|
||||
|
||||
@@ -14,11 +14,11 @@ jobs:
|
||||
build-and-test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: set up go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.25"
|
||||
go-version: "1.24"
|
||||
- name: build sif
|
||||
run: make
|
||||
- name: run sif with features
|
||||
|
||||
@@ -15,16 +15,16 @@ jobs:
|
||||
security-events: write
|
||||
id-token: write
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: run scorecard
|
||||
uses: ossf/scorecard-action@v2.4.3
|
||||
uses: ossf/scorecard-action@v2.4.0
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
publish_results: true
|
||||
- name: upload sarif results
|
||||
uses: github/codeql-action/upload-sarif@v4
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
@@ -14,9 +14,9 @@ jobs:
|
||||
name: runner / shellcheck
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: shellcheck
|
||||
uses: reviewdog/action-shellcheck@v1.32.0
|
||||
uses: reviewdog/action-shellcheck@v1.27.0
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
reporter: github-pr-review
|
||||
|
||||
@@ -15,9 +15,9 @@ jobs:
|
||||
name: runner / yamllint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: yamllint
|
||||
uses: reviewdog/action-yamllint@v1.21.0
|
||||
uses: reviewdog/action-yamllint@v1.19.0
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
reporter: github-pr-review
|
||||
|
||||
+28
-72
@@ -1,94 +1,50 @@
|
||||
---
|
||||
version: "2"
|
||||
|
||||
run:
|
||||
timeout: 5m
|
||||
issues-exit-code: 1
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- errcheck # check error returns
|
||||
- govet # suspicious constructs
|
||||
- staticcheck # advanced static analysis (absorbs gosimple in v2)
|
||||
- staticcheck # advanced static analysis
|
||||
- unused # unused code
|
||||
- gosimple # simplifications
|
||||
- ineffassign # useless assignments
|
||||
- misspell # spelling mistakes
|
||||
- gocritic # opinionated lints
|
||||
- revive # replacement for golint
|
||||
- unconvert # unnecessary type conversions
|
||||
- prealloc # slice preallocation hints
|
||||
- bodyclose # http response body not closed
|
||||
- noctx # http requests without context
|
||||
- gosec # security issues
|
||||
- errorlint # error wrapping and comparison
|
||||
- gocognit # cognitive complexity
|
||||
- nilnil # return nil, nil
|
||||
- wastedassign # assignments to variables never read
|
||||
- usetesting # os.Setenv in tests instead of t.Setenv, etc.
|
||||
|
||||
settings:
|
||||
govet:
|
||||
enable-all: true
|
||||
disable:
|
||||
# too many structs to reorder, risks breaking serialization
|
||||
- fieldalignment
|
||||
- shadow # common Go pattern, too noisy
|
||||
- unusedwrite # false positives on test data structs
|
||||
errcheck:
|
||||
check-blank: false
|
||||
exclude-functions:
|
||||
# log writes are best-effort
|
||||
- github.com/dropalldatabases/sif/internal/logger.Write
|
||||
# Close on io.Closer is idiomatic best-effort
|
||||
- (io.Closer).Close
|
||||
- (*os.File).Close
|
||||
- (*net/http.Response).Body.Close
|
||||
# fmt.Fprint* returns are rarely actionable
|
||||
- fmt.Fprint
|
||||
- fmt.Fprintf
|
||||
- fmt.Fprintln
|
||||
staticcheck:
|
||||
# QF1003/QF1012 are v2 quickfix suggestions, not bugs.
|
||||
# ST1000/ST1003 were the stylecheck linter in v1
|
||||
# (not previously enabled); skipping to match prior parity.
|
||||
checks:
|
||||
- all
|
||||
- -QF1003
|
||||
- -QF1012
|
||||
- -ST1000
|
||||
- -ST1003
|
||||
revive:
|
||||
rules:
|
||||
# stuttering names (scan.ScanResult) need breaking API changes
|
||||
- name: exported
|
||||
disabled: true
|
||||
gocritic:
|
||||
enabled-tags:
|
||||
- diagnostic
|
||||
- style
|
||||
- performance
|
||||
disabled-checks:
|
||||
- commentedOutCode # too opinionated for a project with TODOs
|
||||
- paramTypeCombine # style-only, not worth churn
|
||||
- unnamedResult # style-only
|
||||
- unnecessaryDefer # common pattern in tests
|
||||
# inverting conditions in scan logic hurts readability
|
||||
- nestingReduce
|
||||
gosec:
|
||||
excludes:
|
||||
- G104 # errcheck covers this
|
||||
- G107 # pentesting tool -- variable URLs are the whole point
|
||||
- G110 # nuclei template decompression, acceptable context
|
||||
- G304 # sif reads user-supplied wordlist paths -- intentional
|
||||
- G305 # tar extraction is traversal-guarded (HasPrefix on the
|
||||
# cleaned target); gosec flags filepath.Join regardless
|
||||
|
||||
exclusions:
|
||||
linters-settings:
|
||||
govet:
|
||||
enable-all: true
|
||||
errcheck:
|
||||
check-blank: false
|
||||
revive:
|
||||
rules:
|
||||
# test files get some slack
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- errcheck
|
||||
- noctx
|
||||
- name: exported
|
||||
arguments: [checkPrivateReceivers]
|
||||
gocritic:
|
||||
enabled-tags:
|
||||
- diagnostic
|
||||
- style
|
||||
- performance
|
||||
gosec:
|
||||
excludes:
|
||||
- G104 # errcheck covers this
|
||||
- G304 # sif reads user-supplied wordlist paths — intentional
|
||||
gocognit:
|
||||
min-complexity: 30
|
||||
|
||||
run:
|
||||
timeout: 5m
|
||||
issues-exit-code: 1
|
||||
|
||||
issues:
|
||||
max-issues-per-linter: 50
|
||||
max-same-issues: 50
|
||||
max-same-issues: 3
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2022-2025 vmfunc, xyzeva, lunchcat alumni,
|
||||
Copyright (c) 2022-2025 vmfunc (vmfunc), xyzeva, lunchcat alumni,
|
||||
and other sif contributors.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -9,12 +9,6 @@ RM ?= rm
|
||||
GOFLAGS ?=
|
||||
PREFIX ?= /usr/local
|
||||
BINDIR ?= bin
|
||||
MANDIR ?= share/man/man1
|
||||
|
||||
# stamp local builds with the nearest v* tag (or short sha), matching the
|
||||
# release ci. --match keeps the automated-release-* tags out of the version.
|
||||
VERSION ?= $(shell git describe --tags --match 'v*' --always --dirty 2>/dev/null | sed 's/^v//')
|
||||
GO_LDFLAGS = -X main.version=$(VERSION)
|
||||
|
||||
define COPYRIGHT_ASCII
|
||||
╭────────────────────────────────────────────────────────────╮
|
||||
@@ -62,7 +56,7 @@ sif: check_go_version
|
||||
@echo "📁 Current directory: $$(pwd)"
|
||||
@echo "🔧 Go flags: $(GOFLAGS)"
|
||||
@echo "📦 Building package: ./cmd/sif"
|
||||
$(GO) build -v $(GOFLAGS) -ldflags "$(GO_LDFLAGS)" ./cmd/sif
|
||||
$(GO) build -v $(GOFLAGS) ./cmd/sif
|
||||
@echo "📊 Build info:"
|
||||
@$(GO) version -m sif
|
||||
@echo "✅ sif built successfully! 🚀"
|
||||
@@ -82,9 +76,6 @@ install: check_go_version
|
||||
fi
|
||||
@mkdir -p $(DESTDIR)$(PREFIX)/$(BINDIR) || (echo "🔒 Permission denied. Trying with sudo..." && sudo mkdir -p $(DESTDIR)$(PREFIX)/$(BINDIR))
|
||||
@cp -f sif $(DESTDIR)$(PREFIX)/$(BINDIR) || (echo "🔒 Permission denied. Trying with sudo..." && sudo cp -f sif $(DESTDIR)$(PREFIX)/$(BINDIR))
|
||||
@echo "📖 Installing man page..."
|
||||
@mkdir -p $(DESTDIR)$(PREFIX)/$(MANDIR) || (echo "🔒 Permission denied. Trying with sudo..." && sudo mkdir -p $(DESTDIR)$(PREFIX)/$(MANDIR))
|
||||
@cp -f man/sif.1 $(DESTDIR)$(PREFIX)/$(MANDIR) || (echo "🔒 Permission denied. Trying with sudo..." && sudo cp -f man/sif.1 $(DESTDIR)$(PREFIX)/$(MANDIR))
|
||||
@echo "✅ sif installed successfully! 🎊"
|
||||
|
||||
uninstall:
|
||||
@@ -95,7 +86,6 @@ uninstall:
|
||||
exit 1; \
|
||||
fi
|
||||
@$(RM) $(DESTDIR)$(PREFIX)/$(BINDIR)/sif || (echo "🔒 Permission denied. Trying with sudo..." && sudo $(RM) $(DESTDIR)$(PREFIX)/$(BINDIR)/sif)
|
||||
@$(RM) $(DESTDIR)$(PREFIX)/$(MANDIR)/sif.1 || (echo "🔒 Permission denied. Trying with sudo..." && sudo $(RM) $(DESTDIR)$(PREFIX)/$(MANDIR)/sif.1)
|
||||
@echo "✅ sif uninstalled successfully!"
|
||||
|
||||
.PHONY: all check_go_version sif clean install uninstall
|
||||
@@ -11,7 +11,7 @@
|
||||
[](https://search.nixos.org/packages?query=sif)
|
||||
[](https://github.com/vmfunc/homebrew-sif)
|
||||
[](https://cloudsmith.io/~sif/repos/deb/packages/)
|
||||
[](https://discord.gg/Yksy9J2BvE)
|
||||
[](https://discord.gg/sifcli)
|
||||
|
||||
**[install](#install) · [usage](#usage) · [modules](#modules) · [docs](docs/) · [contribute](#contribute)**
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
sif is a modular pentesting toolkit written in go. it's designed to be fast, concurrent, and extensible. run multiple scan types against targets with a single command.
|
||||
|
||||
```bash
|
||||
./sif -u https://example.com -headers -sh -cms -framework -git
|
||||
./sif -u https://example.com -all
|
||||
```
|
||||
|
||||
## install
|
||||
@@ -56,7 +56,7 @@ environment.systemPackages = [ pkgs.sif ];
|
||||
nix profile install nixpkgs#sif
|
||||
|
||||
# or just run it without installing
|
||||
nix run nixpkgs#sif -- -u https://example.com -headers -sh -framework
|
||||
nix run nixpkgs#sif -- -u https://example.com -all
|
||||
```
|
||||
|
||||
the repo also ships a flake if you want to build from source:
|
||||
@@ -115,36 +115,18 @@ makepkg -si
|
||||
# shodan host intelligence (requires SHODAN_API_KEY env var)
|
||||
./sif -u https://example.com -shodan
|
||||
|
||||
# securitytrails domain discovery (requires SECURITYTRAILS_API_KEY env var)
|
||||
# discovers subdomains + associated domains, then scans all of them
|
||||
./sif -u https://example.com -securitytrails -headers
|
||||
|
||||
# sql recon + lfi scanning
|
||||
./sif -u https://example.com -sql -lfi
|
||||
|
||||
# framework detection (with cve lookup)
|
||||
./sif -u https://example.com -framework
|
||||
|
||||
# a broad sweep
|
||||
./sif -u https://example.com -dirlist small -dnslist small -ports common -headers -sh -cms -framework -git -whois
|
||||
# everything
|
||||
./sif -u https://example.com -all
|
||||
```
|
||||
|
||||
run `./sif -h` for all options.
|
||||
|
||||
## commands
|
||||
|
||||
a couple of subcommands run without scanning:
|
||||
|
||||
```bash
|
||||
# print the version (release builds are stamped; local builds use git describe)
|
||||
./sif version
|
||||
|
||||
# show the latest release notes (also -pn)
|
||||
./sif patchnote
|
||||
```
|
||||
|
||||
the first time you run a new release, sif prints that release's notes once. set `SIF_NO_PATCHNOTES=1` to turn that off.
|
||||
|
||||
## modules
|
||||
|
||||
sif has a modular architecture. modules are defined in yaml and can be extended by users.
|
||||
@@ -161,13 +143,11 @@ sif has a modular architecture. modules are defined in yaml and can be extended
|
||||
| `-js` | javascript analysis |
|
||||
| `-c3` | cloud storage misconfiguration |
|
||||
| `-headers` | http header analysis |
|
||||
| `-sh` | security header analysis (missing/weak headers) |
|
||||
| `-st` | subdomain takeover detection |
|
||||
| `-cms` | cms detection |
|
||||
| `-whois` | whois lookups |
|
||||
| `-git` | exposed git repository detection |
|
||||
| `-shodan` | shodan lookup (requires SHODAN_API_KEY) |
|
||||
| `-securitytrails` | domain discovery + target expansion (requires SECURITYTRAILS_API_KEY) |
|
||||
| `-sql` | sql recon |
|
||||
| `-lfi` | local file inclusion |
|
||||
| `-framework` | framework detection with cve lookup |
|
||||
|
||||
+1
-28
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -13,38 +13,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/charmbracelet/log"
|
||||
"github.com/dropalldatabases/sif"
|
||||
"github.com/dropalldatabases/sif/internal/config"
|
||||
"github.com/dropalldatabases/sif/internal/patchnotes"
|
||||
ver "github.com/dropalldatabases/sif/internal/version"
|
||||
|
||||
// Register framework detectors
|
||||
_ "github.com/dropalldatabases/sif/internal/scan/frameworks/detectors"
|
||||
)
|
||||
|
||||
// version is stamped at release time via -ldflags "-X main.version=...";
|
||||
// ver.Resolve falls back to the build info or "dev" for other builds.
|
||||
var version = "dev"
|
||||
|
||||
func main() {
|
||||
version = ver.Resolve(version)
|
||||
sif.Version = version
|
||||
|
||||
if len(os.Args) > 1 {
|
||||
switch os.Args[1] {
|
||||
case "patchnote", "patchnotes", "-pn", "--patchnotes":
|
||||
patchnotes.Print("")
|
||||
return
|
||||
case "version", "-version", "--version":
|
||||
fmt.Printf("sif %s\n", version)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
settings := config.Parse()
|
||||
|
||||
app, err := sif.New(settings)
|
||||
@@ -52,10 +29,6 @@ func main() {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if !settings.ApiMode {
|
||||
patchnotes.ShowOnce(version)
|
||||
}
|
||||
|
||||
err = app.Run()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
||||
+3
-11
@@ -4,7 +4,7 @@ setting up a development environment for sif.
|
||||
|
||||
## prerequisites
|
||||
|
||||
- go 1.25 or later
|
||||
- go 1.23 or later
|
||||
- git
|
||||
- make
|
||||
|
||||
@@ -28,7 +28,8 @@ sif/
|
||||
│ ├── logger/ # logging utilities
|
||||
│ ├── modules/ # module system
|
||||
│ ├── scan/ # built-in scans
|
||||
│ └── styles/ # terminal styling
|
||||
│ ├── styles/ # terminal styling
|
||||
│ └── worker/ # worker pool
|
||||
├── modules/ # built-in yaml modules
|
||||
│ ├── http/ # http-based modules
|
||||
│ ├── info/ # information gathering
|
||||
@@ -137,15 +138,6 @@ the module system is in `internal/modules/`:
|
||||
go test ./internal/...
|
||||
```
|
||||
|
||||
### integration tests
|
||||
|
||||
run the scanners against a local testbed that plants the artifacts each one
|
||||
should find (network-free, behind a build tag):
|
||||
|
||||
```bash
|
||||
go test -tags=integration ./internal/scan/...
|
||||
```
|
||||
|
||||
### functional test
|
||||
|
||||
```bash
|
||||
|
||||
@@ -36,7 +36,7 @@ download `sif-windows-amd64.exe` from releases and add to your PATH.
|
||||
|
||||
## from source
|
||||
|
||||
requires go 1.25+
|
||||
requires go 1.23+
|
||||
|
||||
```bash
|
||||
git clone https://github.com/dropalldatabases/sif.git
|
||||
|
||||
+4
-15
@@ -98,27 +98,16 @@ analyzes javascript files for security issues.
|
||||
|
||||
## http headers (-headers)
|
||||
|
||||
dumps the target's response headers.
|
||||
|
||||
## security headers (-sh)
|
||||
|
||||
flags missing or weak security headers and headers that leak server internals.
|
||||
analyzes security headers.
|
||||
|
||||
### checks
|
||||
|
||||
- strict-transport-security (https only)
|
||||
- content-security-policy
|
||||
- x-frame-options
|
||||
- x-content-type-options (expects nosniff)
|
||||
- referrer-policy
|
||||
- x-content-type-options
|
||||
- strict-transport-security
|
||||
- x-xss-protection
|
||||
- permissions-policy
|
||||
- cross-origin-opener-policy
|
||||
|
||||
### flagged as disclosure
|
||||
|
||||
- server
|
||||
- x-powered-by
|
||||
- x-aspnet-version / x-aspnetmvc-version
|
||||
|
||||
## cms detection (-cms)
|
||||
|
||||
|
||||
+1
-31
@@ -95,20 +95,12 @@ scopes: `common` (top ports), `full` (all ports)
|
||||
|
||||
### http headers
|
||||
|
||||
`-headers` - dump the target's response headers
|
||||
`-headers` - analyze security headers
|
||||
|
||||
```bash
|
||||
./sif -u https://example.com -headers
|
||||
```
|
||||
|
||||
### security headers
|
||||
|
||||
`-sh` - flag missing/weak security headers (hsts, csp, x-frame-options, ...) and headers that leak server internals
|
||||
|
||||
```bash
|
||||
./sif -u https://example.com -sh
|
||||
```
|
||||
|
||||
### cloud storage
|
||||
|
||||
`-c3` - check for cloud storage misconfigurations
|
||||
@@ -259,28 +251,6 @@ enable api mode for json output:
|
||||
|
||||
output is a json object with scan results.
|
||||
|
||||
## commands
|
||||
|
||||
these run without scanning a target.
|
||||
|
||||
### version
|
||||
|
||||
print the sif version. release builds are stamped via ldflags, local `make` builds derive it from `git describe`, and `go install`ed builds read it from the module build info:
|
||||
|
||||
```bash
|
||||
./sif version
|
||||
```
|
||||
|
||||
### patchnote
|
||||
|
||||
show the latest release's notes, fetched from github (also `-pn`):
|
||||
|
||||
```bash
|
||||
./sif patchnote
|
||||
```
|
||||
|
||||
the first time you run a new release sif also prints that release's notes once. set `SIF_NO_PATCHNOTES=1` to disable that.
|
||||
|
||||
## examples
|
||||
|
||||
### quick recon
|
||||
|
||||
@@ -1,35 +1,34 @@
|
||||
module github.com/dropalldatabases/sif
|
||||
|
||||
go 1.25.7
|
||||
go 1.24.2
|
||||
|
||||
require (
|
||||
github.com/antchfx/htmlquery v1.3.6
|
||||
github.com/charmbracelet/glamour v0.10.0
|
||||
github.com/antchfx/htmlquery v1.3.5
|
||||
github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834
|
||||
github.com/charmbracelet/log v1.0.0
|
||||
github.com/likexian/whois v1.15.7
|
||||
github.com/charmbracelet/log v0.2.4
|
||||
github.com/likexian/whois v1.15.1
|
||||
github.com/projectdiscovery/goflags v0.1.74
|
||||
github.com/projectdiscovery/nuclei/v3 v3.8.0
|
||||
github.com/projectdiscovery/utils v0.10.1
|
||||
github.com/projectdiscovery/nuclei/v3 v3.7.0
|
||||
github.com/projectdiscovery/utils v0.9.0
|
||||
github.com/rocketlaunchr/google-search v1.1.6
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
aead.dev/minisign v0.3.0 // indirect
|
||||
aead.dev/minisign v0.2.0 // indirect
|
||||
carvel.dev/ytt v0.52.0 // indirect
|
||||
code.gitea.io/sdk/gitea v0.17.0 // indirect
|
||||
dario.cat/mergo v1.0.2 // indirect
|
||||
filippo.io/edwards25519 v1.1.1 // indirect
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
git.mills.io/prologic/smtpd v0.0.0-20210710122116-a525b76c287a // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0 // indirect
|
||||
github.com/Azure/go-ntlmssp v0.1.1 // indirect
|
||||
github.com/Azure/go-ntlmssp v0.1.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible // indirect
|
||||
github.com/Masterminds/semver/v3 v3.4.0 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/Mzack9999/gcache v0.0.0-20230410081825-519e28eab057 // indirect
|
||||
github.com/Mzack9999/go-http-digest-auth-client v0.6.1-0.20220414142836-eb8883508809 // indirect
|
||||
@@ -42,7 +41,7 @@ require (
|
||||
github.com/VividCortex/ewma v1.2.0 // indirect
|
||||
github.com/akrylysov/pogreb v0.10.2 // indirect
|
||||
github.com/alecthomas/chroma v0.10.0 // indirect
|
||||
github.com/alecthomas/chroma/v2 v2.20.0 // indirect
|
||||
github.com/alecthomas/chroma/v2 v2.14.0 // indirect
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
|
||||
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
|
||||
github.com/alexsnet/go-vnc v0.1.0 // indirect
|
||||
@@ -51,60 +50,59 @@ require (
|
||||
github.com/andybalholm/cascadia v1.3.3 // indirect
|
||||
github.com/andygrunwald/go-jira v1.16.1 // indirect
|
||||
github.com/antchfx/xmlquery v1.4.4 // indirect
|
||||
github.com/antchfx/xpath v1.3.6 // indirect
|
||||
github.com/antchfx/xpath v1.3.5 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.41.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.36.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.29.17 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.70 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.82 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.99.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.36 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.17 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.17 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.82.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.25.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.34.0 // indirect
|
||||
github.com/aws/smithy-go v1.24.2 // indirect
|
||||
github.com/aws/smithy-go v1.22.4 // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/aymerick/douceur v0.2.0 // indirect
|
||||
github.com/bahlo/generic-list-go v0.2.0 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.22.0 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.13.0 // indirect
|
||||
github.com/bits-and-blooms/bloom/v3 v3.5.0 // indirect
|
||||
github.com/bluele/gcache v0.0.2 // indirect
|
||||
github.com/bodgit/plumbing v1.3.0 // indirect
|
||||
github.com/bodgit/sevenzip v1.6.1 // indirect
|
||||
github.com/bodgit/windows v1.0.1 // indirect
|
||||
github.com/brianvoe/gofakeit/v7 v7.2.1 // indirect
|
||||
github.com/buger/jsonparser v1.1.2 // indirect
|
||||
github.com/bytedance/gopkg v0.1.3 // indirect
|
||||
github.com/bytedance/sonic v1.15.0 // indirect
|
||||
github.com/bytedance/sonic/loader v0.5.0 // indirect
|
||||
github.com/caddyserver/certmagic v0.25.0 // indirect
|
||||
github.com/caddyserver/zerossl v0.1.3 // indirect
|
||||
github.com/buger/jsonparser v1.1.1 // indirect
|
||||
github.com/bytedance/sonic v1.14.0 // indirect
|
||||
github.com/bytedance/sonic/loader v0.3.0 // indirect
|
||||
github.com/caddyserver/certmagic v0.19.2 // indirect
|
||||
github.com/censys/censys-sdk-go v0.19.1 // indirect
|
||||
github.com/cespare/xxhash v1.1.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/charmbracelet/colorprofile v0.3.2 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.10.1 // indirect
|
||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
|
||||
github.com/charmbracelet/glamour v0.10.0 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.8.0 // indirect
|
||||
github.com/charmbracelet/x/cellbuf v0.0.13 // indirect
|
||||
github.com/charmbracelet/x/exp/slice v0.0.0-20250908092851-c2208eb08494 // indirect
|
||||
github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf // indirect
|
||||
github.com/charmbracelet/x/term v0.2.1 // indirect
|
||||
github.com/cheggaaa/pb/v3 v3.1.7 // indirect
|
||||
github.com/cheggaaa/pb/v3 v3.1.6 // indirect
|
||||
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
||||
github.com/cloudflare/cfssl v1.6.4 // indirect
|
||||
github.com/cloudflare/circl v1.6.3 // indirect
|
||||
github.com/cloudwego/base64x v0.1.6 // indirect
|
||||
github.com/cloudflare/circl v1.6.1 // indirect
|
||||
github.com/cloudwego/base64x v0.1.5 // indirect
|
||||
github.com/cnf/structhash v0.0.0-20250313080605-df4c6cc74a9a // indirect
|
||||
github.com/containerd/errdefs v1.0.0 // indirect
|
||||
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.6.1 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.5.1 // indirect
|
||||
github.com/davidmz/go-pageant v1.0.2 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/dimchansky/utfbom v1.1.1 // indirect
|
||||
@@ -117,7 +115,6 @@ require (
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/ebitengine/purego v0.10.0 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/ericlagergren/decimal v0.0.0-20240411145413-00de7ca16731 // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
@@ -126,7 +123,7 @@ require (
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/free5gc/util v1.0.5-0.20230511064842-2e120956883b // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||
github.com/gaissmai/bart v0.26.1 // indirect
|
||||
github.com/gaissmai/bart v0.26.0 // indirect
|
||||
github.com/geoffgarside/ber v1.1.0 // indirect
|
||||
github.com/getkin/kin-openapi v0.132.0 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
@@ -134,16 +131,15 @@ require (
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
|
||||
github.com/go-fed/httpsig v1.1.0 // indirect
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.9.0 // indirect
|
||||
github.com/go-git/go-git/v5 v5.19.1 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.6.2 // indirect
|
||||
github.com/go-git/go-git/v5 v5.16.5 // indirect
|
||||
github.com/go-ldap/ldap/v3 v3.4.11 // indirect
|
||||
github.com/go-logfmt/logfmt v0.6.1 // indirect
|
||||
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||
github.com/go-openapi/swag v0.23.0 // indirect
|
||||
github.com/go-pdf/fpdf v0.9.0 // indirect
|
||||
github.com/go-pg/pg/v10 v10.15.0 // indirect
|
||||
github.com/go-pg/zerochecker v0.2.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
@@ -166,7 +162,7 @@ require (
|
||||
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/golang/snappy v1.0.0 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/certificate-transparency-go v1.3.2 // indirect
|
||||
github.com/google/go-github v17.0.0+incompatible // indirect
|
||||
github.com/google/go-github/v30 v30.1.0 // indirect
|
||||
@@ -181,7 +177,7 @@ require (
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.8 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||
github.com/hashicorp/go-version v1.8.0 // indirect
|
||||
github.com/hashicorp/go-version v1.7.0 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/hbakhtiyor/strsim v0.0.0-20190107154042-4d2bbb273edf // indirect
|
||||
github.com/hdm/jarm-go v0.0.7 // indirect
|
||||
@@ -208,28 +204,28 @@ require (
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/kitabisa/go-ci v1.0.3 // indirect
|
||||
github.com/klauspost/compress v1.18.2 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
||||
github.com/klauspost/pgzip v1.2.6 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/labstack/echo/v4 v4.13.4 // indirect
|
||||
github.com/labstack/gommon v0.4.2 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/leslie-qiwa/flat v0.0.0-20230424180412-f9d1cf014baa // indirect
|
||||
github.com/lib/pq v1.11.2 // indirect
|
||||
github.com/libdns/libdns v1.1.1 // indirect
|
||||
github.com/lib/pq v1.10.9 // indirect
|
||||
github.com/libdns/libdns v0.2.1 // indirect
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
|
||||
github.com/logrusorgru/aurora/v4 v4.0.0 // indirect
|
||||
github.com/lor00x/goldap v0.0.0-20240304151906-8d785c64d1c8 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20250827001030-24949be3fa54 // indirect
|
||||
github.com/mackerelio/go-osstat v0.2.6 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20250821153705-5981dea3221d // indirect
|
||||
github.com/mackerelio/go-osstat v0.2.4 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.28 // indirect
|
||||
github.com/maypok86/otter/v2 v2.2.1 // indirect
|
||||
github.com/mholt/acmez/v3 v3.1.3 // indirect
|
||||
github.com/mholt/acmez v1.2.0 // indirect
|
||||
github.com/mholt/archives v0.1.5 // indirect
|
||||
github.com/microcosm-cc/bluemonday v1.0.27 // indirect
|
||||
github.com/microsoft/go-mssqldb v1.9.2 // indirect
|
||||
@@ -257,45 +253,45 @@ require (
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
||||
github.com/perimeterx/marshmallow v1.1.5 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.23 // indirect
|
||||
github.com/pjbgf/sha1cd v0.6.0 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.2 // indirect
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
||||
github.com/praetorian-inc/fingerprintx v1.1.15 // indirect
|
||||
github.com/projectdiscovery/asnmap v1.1.1 // indirect
|
||||
github.com/projectdiscovery/blackrock v0.0.1 // indirect
|
||||
github.com/projectdiscovery/cdncheck v1.2.31 // indirect
|
||||
github.com/projectdiscovery/cdncheck v1.2.20 // indirect
|
||||
github.com/projectdiscovery/clistats v0.1.1 // indirect
|
||||
github.com/projectdiscovery/dsl v0.8.14 // indirect
|
||||
github.com/projectdiscovery/fastdialer v0.5.6 // indirect
|
||||
github.com/projectdiscovery/dsl v0.8.12 // indirect
|
||||
github.com/projectdiscovery/fastdialer v0.5.3 // indirect
|
||||
github.com/projectdiscovery/fasttemplate v0.0.2 // indirect
|
||||
github.com/projectdiscovery/freeport v0.0.7 // indirect
|
||||
github.com/projectdiscovery/gcache v0.0.0-20241015120333-12546c6e3f4c // indirect
|
||||
github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb // indirect
|
||||
github.com/projectdiscovery/gologger v1.1.68 // indirect
|
||||
github.com/projectdiscovery/gologger v1.1.67 // indirect
|
||||
github.com/projectdiscovery/gostruct v0.0.2 // indirect
|
||||
github.com/projectdiscovery/gozero v0.1.1-0.20251027191944-a4ea43320b81 // indirect
|
||||
github.com/projectdiscovery/hmap v0.0.100 // indirect
|
||||
github.com/projectdiscovery/httpx v1.9.0 // indirect
|
||||
github.com/projectdiscovery/interactsh v1.3.1 // indirect
|
||||
github.com/projectdiscovery/hmap v0.0.99 // indirect
|
||||
github.com/projectdiscovery/httpx v1.8.1 // indirect
|
||||
github.com/projectdiscovery/interactsh v1.2.4 // indirect
|
||||
github.com/projectdiscovery/ldapserver v1.0.2-0.20240219154113-dcc758ebc0cb // indirect
|
||||
github.com/projectdiscovery/machineid v0.0.0-20250715113114-c77eb3567582 // indirect
|
||||
github.com/projectdiscovery/mapcidr v1.1.97 // indirect
|
||||
github.com/projectdiscovery/n3iwf v0.0.0-20230523120440-b8cd232ff1f5 // indirect
|
||||
github.com/projectdiscovery/networkpolicy v0.1.36 // indirect
|
||||
github.com/projectdiscovery/ratelimit v0.0.85 // indirect
|
||||
github.com/projectdiscovery/networkpolicy v0.1.34 // indirect
|
||||
github.com/projectdiscovery/ratelimit v0.0.83 // indirect
|
||||
github.com/projectdiscovery/rawhttp v0.1.90 // indirect
|
||||
github.com/projectdiscovery/rdap v0.9.1-0.20221108103045-9865884d1917 // indirect
|
||||
github.com/projectdiscovery/retryabledns v1.0.114 // indirect
|
||||
github.com/projectdiscovery/retryablehttp-go v1.3.8 // indirect
|
||||
github.com/projectdiscovery/retryabledns v1.0.113 // indirect
|
||||
github.com/projectdiscovery/retryablehttp-go v1.3.5 // indirect
|
||||
github.com/projectdiscovery/sarif v0.0.1 // indirect
|
||||
github.com/projectdiscovery/tlsx v1.2.2 // indirect
|
||||
github.com/projectdiscovery/uncover v1.2.0 // indirect
|
||||
github.com/projectdiscovery/useragent v0.0.107 // indirect
|
||||
github.com/projectdiscovery/wappalyzergo v0.2.76 // indirect
|
||||
github.com/projectdiscovery/wappalyzergo v0.2.65 // indirect
|
||||
github.com/projectdiscovery/yamldoc-go v1.0.6 // indirect
|
||||
github.com/redis/go-redis/v9 v9.11.0 // indirect
|
||||
github.com/refraction-networking/utls v1.8.2 // indirect
|
||||
github.com/refraction-networking/utls v1.8.1 // indirect
|
||||
github.com/remeh/sizedwaitgroup v1.0.0 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/rs/xid v1.6.0 // indirect
|
||||
@@ -304,7 +300,8 @@ require (
|
||||
github.com/segmentio/ksuid v1.0.4 // indirect
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
|
||||
github.com/shirou/gopsutil/v4 v4.26.3 // indirect
|
||||
github.com/shirou/gopsutil/v3 v3.24.5 // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||
github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 // indirect
|
||||
github.com/sijms/go-ora/v2 v2.9.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
@@ -315,8 +312,8 @@ require (
|
||||
github.com/spf13/cast v1.9.2 // indirect
|
||||
github.com/syndtr/goleveldb v1.0.0 // indirect
|
||||
github.com/temoto/robotstxt v1.1.2 // indirect
|
||||
github.com/tidwall/btree v1.8.1 // indirect
|
||||
github.com/tidwall/buntdb v1.3.2 // indirect
|
||||
github.com/tidwall/btree v1.7.0 // indirect
|
||||
github.com/tidwall/buntdb v1.3.1 // indirect
|
||||
github.com/tidwall/gjson v1.18.0 // indirect
|
||||
github.com/tidwall/grect v0.1.4 // indirect
|
||||
github.com/tidwall/match v1.2.0 // indirect
|
||||
@@ -324,8 +321,8 @@ require (
|
||||
github.com/tidwall/rtred v0.1.2 // indirect
|
||||
github.com/tidwall/tinyqueue v0.1.1 // indirect
|
||||
github.com/tim-ywliu/nested-logrus-formatter v1.3.2 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.16 // indirect
|
||||
github.com/tklauser/numcpus v0.11.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.15 // indirect
|
||||
github.com/tklauser/numcpus v0.10.0 // indirect
|
||||
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect
|
||||
github.com/trivago/tgo v1.0.7 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
@@ -338,7 +335,7 @@ require (
|
||||
github.com/vmihailenco/tagparser v0.1.2 // indirect
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
github.com/vulncheck-oss/go-exploit v1.51.0 // indirect
|
||||
github.com/weppos/publicsuffix-go v0.50.3 // indirect
|
||||
github.com/weppos/publicsuffix-go v0.50.3-0.20260104170930-90713dec78f2 // indirect
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||
@@ -353,38 +350,37 @@ require (
|
||||
github.com/ysmood/gson v0.7.3 // indirect
|
||||
github.com/ysmood/leakless v0.9.0 // indirect
|
||||
github.com/yuin/goldmark v1.7.13 // indirect
|
||||
github.com/yuin/goldmark-emoji v1.0.6 // indirect
|
||||
github.com/yuin/goldmark-emoji v1.0.5 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
github.com/zcalusic/sysinfo v1.1.3 // indirect
|
||||
github.com/zeebo/blake3 v0.2.4 // indirect
|
||||
github.com/zcalusic/sysinfo v1.0.2 // indirect
|
||||
github.com/zeebo/blake3 v0.2.3 // indirect
|
||||
github.com/zmap/rc2 v0.0.0-20190804163417-abaa70531248 // indirect
|
||||
github.com/zmap/zcrypto v0.0.0-20240803002437-3a861682ac77 // indirect
|
||||
github.com/zmap/zgrab2 v0.1.8 // indirect
|
||||
gitlab.com/gitlab-org/api/client-go v0.130.1 // indirect
|
||||
go.etcd.io/bbolt v1.4.3 // indirect
|
||||
go.mongodb.org/mongo-driver v1.17.9 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.etcd.io/bbolt v1.4.0 // indirect
|
||||
go.mongodb.org/mongo-driver v1.17.4 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 // indirect
|
||||
go.opentelemetry.io/otel v1.41.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.41.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.41.0 // indirect
|
||||
go.opentelemetry.io/otel v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
go.uber.org/zap/exp v0.3.0 // indirect
|
||||
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
|
||||
goftp.io/server/v2 v2.0.1 // indirect
|
||||
golang.org/x/arch v0.3.0 // indirect
|
||||
golang.org/x/crypto v0.50.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect
|
||||
golang.org/x/mod v0.35.0 // indirect
|
||||
golang.org/x/net v0.53.0 // indirect
|
||||
golang.org/x/crypto v0.47.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250911091902-df9299821621 // indirect
|
||||
golang.org/x/mod v0.31.0 // indirect
|
||||
golang.org/x/net v0.49.0 // indirect
|
||||
golang.org/x/oauth2 v0.34.0 // indirect
|
||||
golang.org/x/sync v0.20.0 // indirect
|
||||
golang.org/x/sys v0.43.0 // indirect
|
||||
golang.org/x/term v0.42.0 // indirect
|
||||
golang.org/x/text v0.36.0 // indirect
|
||||
golang.org/x/sync v0.19.0 // indirect
|
||||
golang.org/x/sys v0.40.0 // indirect
|
||||
golang.org/x/term v0.39.0 // indirect
|
||||
golang.org/x/text v0.33.0 // indirect
|
||||
golang.org/x/time v0.14.0 // indirect
|
||||
golang.org/x/tools v0.44.0 // indirect
|
||||
golang.org/x/tools v0.40.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
aead.dev/minisign v0.2.0 h1:kAWrq/hBRu4AARY6AlciO83xhNnW9UaC8YipS2uhLPk=
|
||||
aead.dev/minisign v0.2.0/go.mod h1:zdq6LdSd9TbuSxchxwhpA9zEb9YXcVGoE8JakuiGaIQ=
|
||||
aead.dev/minisign v0.3.0 h1:8Xafzy5PEVZqYDNP60yJHARlW1eOQtsKNp/Ph2c0vRA=
|
||||
aead.dev/minisign v0.3.0/go.mod h1:NLvG3Uoq3skkRMDuc3YHpWUTMTrSExqm+Ij73W13F6Y=
|
||||
carvel.dev/ytt v0.52.0 h1:tkJPL8Gun5snVfypNXbmMKwnbwMyspcTi3Ypyso3nRY=
|
||||
carvel.dev/ytt v0.52.0/go.mod h1:QgmuU7E15EXW1r2wxTt7zExVz14IHwEG4WNMmaFBkJo=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
@@ -41,8 +40,8 @@ code.gitea.io/sdk/gitea v0.17.0/go.mod h1:ndkDk99BnfiUCCYEUhpNzi0lpmApXlwRFqClBl
|
||||
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
|
||||
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
filippo.io/edwards25519 v1.1.1 h1:YpjwWWlNmGIDyXOn8zLzqiD+9TyIlPhGFG96P39uBpw=
|
||||
filippo.io/edwards25519 v1.1.1/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
git.mills.io/prologic/smtpd v0.0.0-20210710122116-a525b76c287a h1:3i+FJ7IpSZHL+VAjtpQeZCRhrpP0odl5XfoLBY4fxJ8=
|
||||
git.mills.io/prologic/smtpd v0.0.0-20210710122116-a525b76c287a/go.mod h1:C7hXLmFmPYPjIDGfQl1clsmQ5TMEQfmzWTrJk475bUs=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U=
|
||||
@@ -63,8 +62,8 @@ github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0 h1:nVocQV40OQne5613E
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0/go.mod h1:7QJP7dr2wznCMeqIrhMgWGf7XpAQnVrJqDm9nvV3Cu4=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/Azure/go-ntlmssp v0.1.1 h1:l+FM/EEMb0U9QZE7mKNEDw5Mu3mFiaa2GKOoTSsNDPw=
|
||||
github.com/Azure/go-ntlmssp v0.1.1/go.mod h1:NYqdhxd/8aAct/s4qSYZEerdPuH1liG2/X9DiVTbhpk=
|
||||
github.com/Azure/go-ntlmssp v0.1.0 h1:DjFo6YtWzNqNvQdrwEyr/e4nhU3vRiwenz5QX7sFz+A=
|
||||
github.com/Azure/go-ntlmssp v0.1.0/go.mod h1:NYqdhxd/8aAct/s4qSYZEerdPuH1liG2/X9DiVTbhpk=
|
||||
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM=
|
||||
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs=
|
||||
@@ -75,8 +74,8 @@ github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbi
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
|
||||
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||
github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
|
||||
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
@@ -108,15 +107,15 @@ github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1o
|
||||
github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4=
|
||||
github.com/akrylysov/pogreb v0.10.2 h1:e6PxmeyEhWyi2AKOBIJzAEi4HkiC+lKyCocRGlnDi78=
|
||||
github.com/akrylysov/pogreb v0.10.2/go.mod h1:pNs6QmpQ1UlTJKDezuRWmaqkgUE2TuU0YTWyqJZ7+lI=
|
||||
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
|
||||
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||
github.com/alecthomas/assert/v2 v2.7.0 h1:QtqSACNS3tF7oasA8CU6A6sXZSBDqnm7RfpLl9bZqbE=
|
||||
github.com/alecthomas/assert/v2 v2.7.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||
github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek=
|
||||
github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s=
|
||||
github.com/alecthomas/chroma/v2 v2.20.0 h1:sfIHpxPyR07/Oylvmcai3X/exDlE8+FA820NTz+9sGw=
|
||||
github.com/alecthomas/chroma/v2 v2.20.0/go.mod h1:e7tViK0xh/Nf4BYHl00ycY6rV7b8iXBksI9E359yNmA=
|
||||
github.com/alecthomas/chroma/v2 v2.14.0 h1:R3+wzpnUArGcQz7fCETQBzO5n9IMNi13iIs46aU4V9E=
|
||||
github.com/alecthomas/chroma/v2 v2.14.0/go.mod h1:QolEbTfmUHIMVpBqxeDnNBj2uoeI4EbYP4i6n68SG4I=
|
||||
github.com/alecthomas/kingpin/v2 v2.3.1/go.mod h1:oYL5vtsvEHZGHxU7DMp32Dvx+qL+ptGn6lWaot2vCNE=
|
||||
github.com/alecthomas/repr v0.5.1 h1:E3G4t2QbHTSNpPKBgMTln5KLkZHLOcU7r37J4pXBuIg=
|
||||
github.com/alecthomas/repr v0.5.1/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
|
||||
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
@@ -145,8 +144,8 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||
github.com/antchfx/htmlquery v1.2.3/go.mod h1:B0ABL+F5irhhMWg54ymEZinzMSi0Kt3I2if0BLYa3V0=
|
||||
github.com/antchfx/htmlquery v1.3.0/go.mod h1:zKPDVTMhfOmcwxheXUsx4rKJy8KEY/PU6eXr/2SebQ8=
|
||||
github.com/antchfx/htmlquery v1.3.6 h1:RNHHL7YehO5XdO8IM8CynwLKONwRHWkrghbYhQIk9ag=
|
||||
github.com/antchfx/htmlquery v1.3.6/go.mod h1:kcVUqancxPygm26X2rceEcagZFFVkLEE7xgLkGSDl/4=
|
||||
github.com/antchfx/htmlquery v1.3.5 h1:aYthDDClnG2a2xePf6tys/UyyM/kRcsFRm+ifhFKoU0=
|
||||
github.com/antchfx/htmlquery v1.3.5/go.mod h1:5oyIPIa3ovYGtLqMPNjBF2Uf25NPCKsMjCnQ8lvjaoA=
|
||||
github.com/antchfx/xmlquery v1.2.4/go.mod h1:KQQuESaxSlqugE2ZBcM/qn+ebIpt+d+4Xx7YcSGAIrM=
|
||||
github.com/antchfx/xmlquery v1.3.15/go.mod h1:zMDv5tIGjOxY/JCNNinnle7V/EwthZ5IT8eeCGJKRWA=
|
||||
github.com/antchfx/xmlquery v1.4.4 h1:mxMEkdYP3pjKSftxss4nUHfjBhnMk4imGoR96FRY2dg=
|
||||
@@ -156,16 +155,16 @@ github.com/antchfx/xpath v1.1.8/go.mod h1:Yee4kTMuNiPYJ7nSNorELQMr1J33uOpXDMByNY
|
||||
github.com/antchfx/xpath v1.2.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
||||
github.com/antchfx/xpath v1.2.4/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
||||
github.com/antchfx/xpath v1.3.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
||||
github.com/antchfx/xpath v1.3.6 h1:s0y+ElRRtTQdfHP609qFu0+c6bglDv20pqOViQjjdPI=
|
||||
github.com/antchfx/xpath v1.3.6/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
||||
github.com/antchfx/xpath v1.3.5 h1:PqbXLC3TkfeZyakF5eeh3NTWEbYl4VHNVeufANzDbKQ=
|
||||
github.com/antchfx/xpath v1.3.5/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||
github.com/aws/aws-sdk-go-v2 v1.41.5 h1:dj5kopbwUsVUVFgO4Fi5BIT3t4WyqIDjGKCangnV/yY=
|
||||
github.com/aws/aws-sdk-go-v2 v1.41.5/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 h1:eBMB84YGghSocM7PsjmmPffTa+1FBUeNvGvFou6V/4o=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8/go.mod h1:lyw7GFp3qENLh7kwzf7iMzAxDn+NzjXEAGjKS2UOKqI=
|
||||
github.com/aws/aws-sdk-go-v2 v1.36.5 h1:0OF9RiEMEdDdZEMqF9MRjevyxAQcf6gY+E7vwBILFj0=
|
||||
github.com/aws/aws-sdk-go-v2 v1.36.5/go.mod h1:EYrzvCCN9CMUTa5+6lf6MM4tq3Zjp8UhSGR/cBsjai0=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 h1:12SpdwU8Djs+YGklkinSSlcrPyj3H4VifVsKf78KbwA=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11/go.mod h1:dd+Lkp6YmMryke+qxW/VnKyhMBDTYP41Q2Bb+6gNZgY=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.29.17 h1:jSuiQ5jEe4SAMH6lLRMY9OVC+TqJLP5655pBGjmnjr0=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.29.17/go.mod h1:9P4wwACpbeXs9Pm9w1QTh6BwWwJjwYvJ1iCt5QbCXh8=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.70 h1:ONnH5CM16RTXRkS8Z1qg7/s2eDOhHhaXVd72mmyv4/0=
|
||||
@@ -174,32 +173,32 @@ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32 h1:KAXP9JSHO1vKGCr5f4O6Wm
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32/go.mod h1:h4Sg6FQdexC1yYG9RDnOvLbW1a/P986++/Y/a+GyEM8=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.82 h1:EO13QJTCD1Ig2IrQnoHTRrn981H9mB7afXsZ89WptI4=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.82/go.mod h1:AGh1NCg0SH+uyJamiJA5tTQcql4MMRDXGRdMmCxCXzY=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 h1:Rgg6wvjjtX8bNHcvi9OnXWwcE0a2vGpbwmtICOsvcf4=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21/go.mod h1:A/kJFst/nm//cyqonihbdpQZwiUhhzpqTsdbhDdRF9c=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 h1:PEgGVtPoB6NTpPrBgqSE5hE/o47Ij9qk/SEZFbUOe9A=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21/go.mod h1:p+hz+PRAYlY3zcpJhPwXlLC4C+kqn70WIHwnzAfs6ps=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36 h1:SsytQyTMHMDPspp+spo7XwXTP44aJZZAC7fBV2C5+5s=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36/go.mod h1:Q1lnJArKRXkenyog6+Y+zr7WDpk4e6XlR6gs20bbeNo=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36 h1:i2vNHQiXUvKhs3quBR6aqlgJaiaexz/aNvdCktW/kAM=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36/go.mod h1:UdyGa7Q91id/sdyHPwth+043HhmP6yP9MBHgbZM0xo8=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 h1:rWyie/PxDRIdhNf4DzRk0lvjVOqFJuNnO8WwaIRVxzQ=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22/go.mod h1:zd/JsJ4P7oGfUhXn1VyLqaRZwPmZwg44Jf2dS84Dm3Y=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 h1:5EniKhLZe4xzL7a+fU3C2tfUN4nWIqlLesfrjkuPFTY=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 h1:JRaIgADQS/U6uXDqlPiefP32yXTda7Kqfx+LgspooZM=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13/go.mod h1:CEuVn5WqOMilYl+tbccq8+N2ieCy0gVn3OtRb0vBNNM=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 h1:c31//R3xgIJMSC8S6hEVq+38DcvUlgFY0FM6mSI5oto=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21/go.mod h1:r6+pf23ouCB718FUxaqzZdbpYFyDtehyZcmP5KL9FkA=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 h1:ZlvrNcHSFFWURB8avufQq9gFsheUgjVD9536obIknfM=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21/go.mod h1:cv3TNhVrssKR0O/xxLJVRfd2oazSnZnkUeTf6ctUwfQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.99.0 h1:hlSuz394kV0vhv9drL5lhuEFbEOEP1VyQpy15qWh1Pk=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.99.0/go.mod h1:uoA43SdFwacedBfSgfFSjjCvYe8aYBS7EnU5GZ/YKMM=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.36 h1:GMYy2EOWfzdP3wfVAGXBNKY5vK4K8vMET4sYOYltmqs=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.36/go.mod h1:gDhdAV6wL3PmPqBhiPbnlS447GoWs8HTTOYef9/9Inw=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 h1:CXV68E2dNqhuynZJPB80bhPQwAKqBWVer887figW6Jc=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4/go.mod h1:/xFi9KtvBXP97ppCz1TAEvU1Uf66qvid89rbem3wCzQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.4 h1:nAP2GYbfh8dd2zGZqFRSMlq+/F6cMPBUuCsGAMkN074=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.4/go.mod h1:LT10DsiGjLWh4GbjInf9LQejkYEhBgBCjLG5+lvk4EE=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.17 h1:t0E6FzREdtCsiLIoLCWsYliNsRBgyGD/MCK571qk4MI=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.17/go.mod h1:ygpklyoaypuyDvOM5ujWGrYWpAK3h7ugnmKCU/76Ys4=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.17 h1:qcLWgdhq45sDM9na4cvXax9dyLitn8EYBRl8Ak4XtG4=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.17/go.mod h1:M+jkjBFZ2J6DJrjMv2+vkBbuht6kxJYtJiwoVgX4p4U=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.82.0 h1:JubM8CGDDFaAOmBrd8CRYNr49ZNgEAiLwGwgNMdS0nw=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.82.0/go.mod h1:kUklwasNoCn5YpyAqC/97r6dzTA1SRKJfKq16SXeoDU=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.25.5 h1:AIRJ3lfb2w/1/8wOOSqYb9fUKGwQbtysJ2H1MofRUPg=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.25.5/go.mod h1:b7SiVprpU+iGazDUqvRSLf5XmCdn+JtT1on7uNL6Ipc=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3 h1:BpOxT3yhLwSJ77qIY3DoHAQjZsc4HEGfMCE4NGy3uFg=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3/go.mod h1:vq/GQR1gOFLquZMSrxUK/cpvKCNVYibNyJ1m7JrU88E=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.34.0 h1:NFOJ/NXEGV4Rq//71Hs1jC/NvPs1ezajK+yQmkwnPV0=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.34.0/go.mod h1:7ph2tGpfQvwzgistp2+zga9f+bCjlQJPkPUmMgDSD7w=
|
||||
github.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng=
|
||||
github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
|
||||
github.com/aws/smithy-go v1.22.4 h1:uqXzVZNuNexwc/xrh6Tb56u89WDlJY6HS+KC0S4QSjw=
|
||||
github.com/aws/smithy-go v1.22.4/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||
github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8=
|
||||
@@ -212,8 +211,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/bits-and-blooms/bitset v1.22.0 h1:Tquv9S8+SGaS3EhyA+up3FXzmkhxPGjQQCkcs2uw7w4=
|
||||
github.com/bits-and-blooms/bitset v1.22.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE=
|
||||
github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/bits-and-blooms/bloom/v3 v3.5.0 h1:AKDvi1V3xJCmSR6QhcBfHbCN4Vf8FfxeWkMNQfmAGhY=
|
||||
github.com/bits-and-blooms/bloom/v3 v3.5.0/go.mod h1:Y8vrn7nk1tPIlmLtW2ZPV+W7StdVMor6bC1xgpjMZFs=
|
||||
github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw=
|
||||
@@ -230,19 +229,16 @@ github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||
github.com/buger/jsonparser v1.1.2 h1:frqHqw7otoVbk5M8LlE/L7HTnIq2v9RX6EJ48i9AxJk=
|
||||
github.com/buger/jsonparser v1.1.2/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
||||
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
|
||||
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
||||
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M=
|
||||
github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
|
||||
github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE=
|
||||
github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k=
|
||||
github.com/bytedance/sonic/loader v0.5.0 h1:gXH3KVnatgY7loH5/TkeVyXPfESoqSBSBEiDd5VjlgE=
|
||||
github.com/bytedance/sonic/loader v0.5.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo=
|
||||
github.com/caddyserver/certmagic v0.25.0 h1:VMleO/XA48gEWes5l+Fh6tRWo9bHkhwAEhx63i+F5ic=
|
||||
github.com/caddyserver/certmagic v0.25.0/go.mod h1:m9yB7Mud24OQbPHOiipAoyKPn9pKHhpSJxXR1jydBxA=
|
||||
github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA=
|
||||
github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4=
|
||||
github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ=
|
||||
github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA=
|
||||
github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
|
||||
github.com/caddyserver/certmagic v0.19.2 h1:HZd1AKLx4592MalEGQS39DKs2ZOAJCEM/xYPMQ2/ui0=
|
||||
github.com/caddyserver/certmagic v0.19.2/go.mod h1:fsL01NomQ6N+kE2j37ZCnig2MFosG+MIO4ztnmG/zz8=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
|
||||
@@ -257,26 +253,26 @@ github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/charmbracelet/colorprofile v0.3.2 h1:9J27WdztfJQVAQKX2WOlSSRB+5gaKqqITmrvb1uTIiI=
|
||||
github.com/charmbracelet/colorprofile v0.3.2/go.mod h1:mTD5XzNeWHj8oqHb+S1bssQb7vIHbepiebQ2kPKVKbI=
|
||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs=
|
||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk=
|
||||
github.com/charmbracelet/glamour v0.10.0 h1:MtZvfwsYCx8jEPFJm3rIBFIMZUfUJ765oX8V6kXldcY=
|
||||
github.com/charmbracelet/glamour v0.10.0/go.mod h1:f+uf+I/ChNmqo087elLnVdCiVgjSKWuXa/l6NU2ndYk=
|
||||
github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834 h1:ZR7e0ro+SZZiIZD7msJyA+NjkCNNavuiPBLgerbOziE=
|
||||
github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834/go.mod h1:aKC/t2arECF6rNOnaKaVU6y4t4ZeHQzqfxedE/VkVhA=
|
||||
github.com/charmbracelet/log v1.0.0 h1:HVVVMmfOorfj3BA9i8X8UL69Hoz9lI0PYwXfJvOdRc4=
|
||||
github.com/charmbracelet/log v1.0.0/go.mod h1:uYgY3SmLpwJWxmlrPwXvzVYujxis1vAKRV/0VQB7yWA=
|
||||
github.com/charmbracelet/x/ansi v0.10.1 h1:rL3Koar5XvX0pHGfovN03f5cxLbCF2YvLeyz7D2jVDQ=
|
||||
github.com/charmbracelet/x/ansi v0.10.1/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE=
|
||||
github.com/charmbracelet/log v0.2.4 h1:3pKtq5/Y5QMKtcZt7kDqD1p9w7lICzHYQACBFY4ocHA=
|
||||
github.com/charmbracelet/log v0.2.4/go.mod h1:nQGK8tvc4pS9cvVEH/pWJiZ50eUq1aoXUOjGpXvdD0k=
|
||||
github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE=
|
||||
github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q=
|
||||
github.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k=
|
||||
github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
|
||||
github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a h1:G99klV19u0QnhiizODirwVksQB91TJKV/UaTnACcG30=
|
||||
github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
|
||||
github.com/charmbracelet/x/exp/slice v0.0.0-20250908092851-c2208eb08494 h1:O5se1NwLfawEafCaxy3HztOFWgXlYgtLDQnjTTuRsBI=
|
||||
github.com/charmbracelet/x/exp/slice v0.0.0-20250908092851-c2208eb08494/go.mod h1:vI5nDVMWi6veaYH+0Fmvpbe/+cv/iJfMntdh+N0+Tms=
|
||||
github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf h1:rLG0Yb6MQSDKdB52aGX55JT1oi0P0Kuaj7wi1bLUpnI=
|
||||
github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf/go.mod h1:B3UgsnsBZS/eX42BlaNiJkD1pPOUa+oF1IYC6Yd2CEU=
|
||||
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
|
||||
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
|
||||
github.com/cheggaaa/pb/v3 v3.1.7 h1:2FsIW307kt7A/rz/ZI2lvPO+v3wKazzE4K/0LtTWsOI=
|
||||
github.com/cheggaaa/pb/v3 v3.1.7/go.mod h1:/Ji89zfVPeC/u5j8ukD0MBPHt2bzTYp74lQ7KlgFWTQ=
|
||||
github.com/cheggaaa/pb/v3 v3.1.6 h1:h0x+vd7EiUohAJ29DJtJy+SNAc55t/elW3jCD086EXk=
|
||||
github.com/cheggaaa/pb/v3 v3.1.6/go.mod h1:urxmfVtaxT+9aWk92DbsvXFZtNSWQSO5TRAp+MJ3l1s=
|
||||
github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
|
||||
github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs=
|
||||
github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
|
||||
@@ -292,10 +288,11 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
||||
github.com/cloudflare/cfssl v1.6.4 h1:NMOvfrEjFfC63K3SGXgAnFdsgkmiq4kATme5BfcqrO8=
|
||||
github.com/cloudflare/cfssl v1.6.4/go.mod h1:8b3CQMxfWPAeom3zBnGJ6sd+G1NkL5TXqmDXacb+1J0=
|
||||
github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I=
|
||||
github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
|
||||
github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
|
||||
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
|
||||
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
|
||||
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
|
||||
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||
github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
|
||||
github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cnf/structhash v0.0.0-20250313080605-df4c6cc74a9a h1:Ohw57yVY2dBTt+gsC6aZdteyxwlxfbtgkFEMTEkwgSw=
|
||||
github.com/cnf/structhash v0.0.0-20250313080605-df4c6cc74a9a/go.mod h1:pCxVEbcm3AMg7ejXyorUXi6HQCzOIBf7zEDVPtw0/U4=
|
||||
@@ -307,8 +304,8 @@ github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151X
|
||||
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
|
||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||
github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE=
|
||||
github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc=
|
||||
github.com/cyphar/filepath-securejoin v0.5.1 h1:eYgfMq5yryL4fbWfkLpFFy2ukSELzaJOTaUTuh+oF48=
|
||||
github.com/cyphar/filepath-securejoin v0.5.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
@@ -328,8 +325,8 @@ github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYC
|
||||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
|
||||
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/docker/cli v29.2.0+incompatible h1:9oBd9+YM7rxjZLfyMGxjraKBKE4/nVyvVfN4qNl9XRM=
|
||||
github.com/docker/cli v29.2.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v27.4.1+incompatible h1:VzPiUlRJ/xh+otB75gva3r05isHMo5wXDfPRi5/b4hI=
|
||||
github.com/docker/cli v27.4.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI=
|
||||
github.com/docker/docker v28.3.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
|
||||
@@ -342,8 +339,6 @@ github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdf
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/ebitengine/purego v0.10.0 h1:QIw4xfpWT6GWTzaW5XEKy3HXoqrJGx1ijYHzTF0/ISU=
|
||||
github.com/ebitengine/purego v0.10.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||
github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o=
|
||||
github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
@@ -373,8 +368,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.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||
github.com/gaissmai/bart v0.26.1 h1:+w4rnLGNlA2GDVn382Tfe3jOsK5vOr5n4KmigJ9lbTo=
|
||||
github.com/gaissmai/bart v0.26.1/go.mod h1:GREWQfTLRWz/c5FTOsIw+KkscuFkIV5t8Rp7Nd1Td5c=
|
||||
github.com/gaissmai/bart v0.26.0 h1:xOZ57E9hJLBiQaSyeZa9wgWhGuzfGACgqp4BE77OkO0=
|
||||
github.com/gaissmai/bart v0.26.0/go.mod h1:GREWQfTLRWz/c5FTOsIw+KkscuFkIV5t8Rp7Nd1Td5c=
|
||||
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.132.0 h1:3ISeLMsQzcb5v26yeJrBcdTCEQTag36ZjaGk7MIRUwk=
|
||||
@@ -391,12 +386,12 @@ github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI=
|
||||
github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
||||
github.com/go-git/go-billy/v5 v5.9.0 h1:jItGXszUDRtR/AlferWPTMN4j38BQ88XnXKbilmmBPA=
|
||||
github.com/go-git/go-billy/v5 v5.9.0/go.mod h1:jCnQMLj9eUgGU7+ludSTYoZL/GGmii14RxKFj7ROgHw=
|
||||
github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=
|
||||
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||
github.com/go-git/go-git/v5 v5.19.1 h1:nX27AnaU43/K5bKktKwgBmR9lawoYVe1Ckg0rgzzN00=
|
||||
github.com/go-git/go-git/v5 v5.19.1/go.mod h1:Pb1v0c7/g8aGQJwx9Us09W85yGoyvSwuhEGMH7zjDKQ=
|
||||
github.com/go-git/go-git/v5 v5.16.5 h1:mdkuqblwr57kVfXri5TTH+nMFLNUxIj9Z7F5ykFbw5s=
|
||||
github.com/go-git/go-git/v5 v5.16.5/go.mod h1:QOMLpNf1qxuSY4StA/ArOdfFR2TrKEjJiye2kel2m+M=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
@@ -411,8 +406,8 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
github.com/go-logfmt/logfmt v0.6.1 h1:4hvbpePJKnIzH1B+8OR/JPbTx37NktoI9LE2QZBBkvE=
|
||||
github.com/go-logfmt/logfmt v0.6.1/go.mod h1:EV2pOAQoZaT1ZXZbqDl5hrymndi4SY9ED9/z6CO0XAk=
|
||||
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
|
||||
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
@@ -425,8 +420,6 @@ github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1
|
||||
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
|
||||
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
|
||||
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
|
||||
github.com/go-pdf/fpdf v0.9.0 h1:PPvSaUuo1iMi9KkaAn90NuKi+P4gwMedWPHhj8YlJQw=
|
||||
github.com/go-pdf/fpdf v0.9.0/go.mod h1:oO8N111TkmKb9D7VvWGLvLJlaZUQVPM+6V42pp3iV4Y=
|
||||
github.com/go-pg/pg/v10 v10.15.0 h1:6DQwbaxJz/e4wvgzbxBkBLiL/Uuk87MGgHhkURtzx24=
|
||||
github.com/go-pg/pg/v10 v10.15.0/go.mod h1:FIn/x04hahOf9ywQ1p68rXqaDVbTRLYlu4MQR0lhoB8=
|
||||
github.com/go-pg/zerochecker v0.2.0 h1:pp7f72c3DobMWOb2ErtZsnrPaSvHd2W4o9//8HtF4mU=
|
||||
@@ -513,8 +506,8 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs=
|
||||
github.com/golang/snappy v1.0.0/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=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/certificate-transparency-go v1.3.2 h1:9ahSNZF2o7SYMaKaXhAumVEzXB2QaayzII9C8rv7v+A=
|
||||
@@ -588,8 +581,8 @@ github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b
|
||||
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
|
||||
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-version v1.5.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4=
|
||||
github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
|
||||
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||
@@ -673,10 +666,13 @@ github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0
|
||||
github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
|
||||
github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
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.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=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
@@ -699,14 +695,14 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/leslie-qiwa/flat v0.0.0-20230424180412-f9d1cf014baa h1:KQKuQDgA3DZX6C396lt3WDYB9Um1gLITLbvficVbqXk=
|
||||
github.com/leslie-qiwa/flat v0.0.0-20230424180412-f9d1cf014baa/go.mod h1:HbwNE4XGwjgtUELkvQaAOjWrpianHYZdQVNqSdYW3UM=
|
||||
github.com/lib/pq v1.11.2 h1:x6gxUeu39V0BHZiugWe8LXZYZ+Utk7hSJGThs8sdzfs=
|
||||
github.com/lib/pq v1.11.2/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA=
|
||||
github.com/libdns/libdns v1.1.1 h1:wPrHrXILoSHKWJKGd0EiAVmiJbFShguILTg9leS/P/U=
|
||||
github.com/libdns/libdns v1.1.1/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
|
||||
github.com/likexian/gokit v0.25.16 h1:wwBeUIN/OdoPp6t00xTnZE8Di/+s969Bl5N2Kw6bzP8=
|
||||
github.com/likexian/gokit v0.25.16/go.mod h1:Wqd4f+iifV0qxA1N3MqePJTUsmRy/lpst9/yXriDx/4=
|
||||
github.com/likexian/whois v1.15.7 h1:sajjDhi2bVD71AHJhjV7jLYxN92H4AWhTwxM8hmj7c0=
|
||||
github.com/likexian/whois v1.15.7/go.mod h1:kdPQtYb+7SQVftBEbCblDadUkycN7Mg1k1/Li/rwvmc=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis=
|
||||
github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
|
||||
github.com/likexian/gokit v0.25.13 h1:p2Uw3+6fGG53CwdU2Dz0T6bOycdb2+bAFAa3ymwWVkM=
|
||||
github.com/likexian/gokit v0.25.13/go.mod h1:qQhEWFBEfqLCO3/vOEo2EDKd+EycekVtUK4tex+l2H4=
|
||||
github.com/likexian/whois v1.15.1 h1:6vTMI8n9s1eJdmcO4R9h1x99aQWIZZX1CD3am68gApU=
|
||||
github.com/likexian/whois v1.15.1/go.mod h1:/nxmQ6YXvLz+qTxC/QFtEJNAt0zLuRxJrKiWpBJX8X0=
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
github.com/logrusorgru/aurora/v4 v4.0.0 h1:sRjfPpun/63iADiSvGGjgA1cAYegEWMPCJdUpJYn9JA=
|
||||
@@ -716,10 +712,10 @@ github.com/lor00x/goldap v0.0.0-20240304151906-8d785c64d1c8 h1:z9RDOBcFcf3f2hSfK
|
||||
github.com/lor00x/goldap v0.0.0-20240304151906-8d785c64d1c8/go.mod h1:37YR9jabpiIxsb8X9VCIx8qFOjTDIIrIHHODa8C4gz0=
|
||||
github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=
|
||||
github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/lufia/plan9stats v0.0.0-20250827001030-24949be3fa54 h1:mFWunSatvkQQDhpdyuFAYwyAan3hzCuma+Pz8sqvOfg=
|
||||
github.com/lufia/plan9stats v0.0.0-20250827001030-24949be3fa54/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg=
|
||||
github.com/mackerelio/go-osstat v0.2.6 h1:gs4U8BZeS1tjrL08tt5VUliVvSWP26Ai2Ob8Lr7f2i0=
|
||||
github.com/mackerelio/go-osstat v0.2.6/go.mod h1:lRy8V9ZuHpuRVZh+vyTkODeDPl3/d5MgXHtLSaqG8bA=
|
||||
github.com/lufia/plan9stats v0.0.0-20250821153705-5981dea3221d h1:vFzYZc8yji+9DmNRhpEbs8VBK4CgV/DPfGzeVJSSp/8=
|
||||
github.com/lufia/plan9stats v0.0.0-20250821153705-5981dea3221d/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg=
|
||||
github.com/mackerelio/go-osstat v0.2.4 h1:qxGbdPkFo65PXOb/F/nhDKpF2nGmGaCFDLXoZjJTtUs=
|
||||
github.com/mackerelio/go-osstat v0.2.4/go.mod h1:Zy+qzGdZs3A9cuIqmgbJvwbmLQH9dJvtio5ZjJTbdlQ=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
@@ -735,8 +731,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/maypok86/otter/v2 v2.2.1 h1:hnGssisMFkdisYcvQ8L019zpYQcdtPse+g0ps2i7cfI=
|
||||
github.com/maypok86/otter/v2 v2.2.1/go.mod h1:1NKY9bY+kB5jwCXBJfE59u+zAwOt6C7ni1FTlFFMqVs=
|
||||
github.com/mholt/acmez/v3 v3.1.3 h1:gUl789rjbJSuM5hYzOFnNaGgWPV1xVfnOs59o0dZEcc=
|
||||
github.com/mholt/acmez/v3 v3.1.3/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ=
|
||||
github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30=
|
||||
github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE=
|
||||
github.com/mholt/archives v0.1.5 h1:Fh2hl1j7VEhc6DZs2DLMgiBNChUux154a1G+2esNvzQ=
|
||||
github.com/mholt/archives v0.1.5/go.mod h1:3TPMmBLPsgszL+1As5zECTuKwKvIfj6YcwWPpeTAXF4=
|
||||
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
|
||||
@@ -758,10 +754,6 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||
github.com/moby/moby/api v1.53.0 h1:PihqG1ncw4W+8mZs69jlwGXdaYBeb5brF6BL7mPIS/w=
|
||||
github.com/moby/moby/api v1.53.0/go.mod h1:8mb+ReTlisw4pS6BRzCMts5M49W5M7bKt1cJy/YbAqc=
|
||||
github.com/moby/moby/client v0.2.2 h1:Pt4hRMCAIlyjL3cr8M5TrXCwKzguebPAc2do2ur7dEM=
|
||||
github.com/moby/moby/client v0.2.2/go.mod h1:2EkIPVNCqR05CMIzL1mfA07t0HvVUUOl85pasRz/GmQ=
|
||||
github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=
|
||||
github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs=
|
||||
github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
|
||||
@@ -828,8 +820,8 @@ github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX
|
||||
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
|
||||
github.com/pierrec/lz4/v4 v4.1.23 h1:oJE7T90aYBGtFNrI8+KbETnPymobAhzRrR8Mu8n1yfU=
|
||||
github.com/pierrec/lz4/v4 v4.1.23/go.mod h1:EoQMVJgeeEOMsCqCzqFm2O0cJvljX2nGZjcRIPL34O4=
|
||||
github.com/pjbgf/sha1cd v0.6.0 h1:3WJ8Wz8gvDz29quX1OcEmkAlUg9diU4GxJHqs0/XiwU=
|
||||
github.com/pjbgf/sha1cd v0.6.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM=
|
||||
github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4=
|
||||
github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@@ -847,14 +839,14 @@ 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.2.31 h1:8iD/MLDdMdMziM3RA5FkjUxO6kIwwgAoxWaL6RBIIl0=
|
||||
github.com/projectdiscovery/cdncheck v1.2.31/go.mod h1:6/B6caF1+97hR9cICMlzIYR8hpAN/y3AlJPHI2q48PQ=
|
||||
github.com/projectdiscovery/cdncheck v1.2.20 h1:sMzoCi5TR7qQsH4LW0NF219PmX/lYjWUeoB2Iiddwcs=
|
||||
github.com/projectdiscovery/cdncheck v1.2.20/go.mod h1:gpeX5OrzaC4DmeUGDcKrC7cPUXQvRGTY/Ui0XrVfdzU=
|
||||
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.8.14 h1:g9szcXk2RRdVf2rsHEzbTXOPxiny3haKonSncU6pg2w=
|
||||
github.com/projectdiscovery/dsl v0.8.14/go.mod h1:LYImt/EiBzqTWG1RswT3Yl0DZbfjUP93Nvq2Z/G7dcE=
|
||||
github.com/projectdiscovery/fastdialer v0.5.6 h1:kIBFmzbXrua41uf4fGsQClTZmT7cm7E3vVgcSj8gs6Q=
|
||||
github.com/projectdiscovery/fastdialer v0.5.6/go.mod h1:QxvCe02Jii+j8vA3hWYkymgZIY8cqMgs2s3Jbz6mvbs=
|
||||
github.com/projectdiscovery/dsl v0.8.12 h1:gQL8k5zPok+5JGc7poiXzHCElNY/WnaTKoRB2wI3CYA=
|
||||
github.com/projectdiscovery/dsl v0.8.12/go.mod h1:pdMfUTNHMxlt6M94CSrCpZ1QObTP44rLqWifMMWW+IA=
|
||||
github.com/projectdiscovery/fastdialer v0.5.3 h1:Io57Q37ouFzrPK53ZdzK6jsELgqjIMCWcoDs+lRDGMA=
|
||||
github.com/projectdiscovery/fastdialer v0.5.3/go.mod h1:euoxS1E93LDnl0OnNN0UALedAFF+EehBxyU3z+79l0g=
|
||||
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=
|
||||
@@ -865,18 +857,18 @@ github.com/projectdiscovery/go-smb2 v0.0.0-20240129202741-052cc450c6cb h1:rutG90
|
||||
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.68 h1:KfdIO/3X7BtHssWZuqhxPZ+A946epCCx2cz+3NnRAnU=
|
||||
github.com/projectdiscovery/gologger v1.1.68/go.mod h1:Xae0t4SeqJVa0RQGK9iECx/+HfXhvq70nqOQp2BuW+o=
|
||||
github.com/projectdiscovery/gologger v1.1.67 h1:GZU3AjYiJvcwJT5TlfIv+152/TVmaz62Zyn3/wWXlig=
|
||||
github.com/projectdiscovery/gologger v1.1.67/go.mod h1:35oeQP6wvj58S+o+Km6boED/t786FXQkI0exhFHJbNE=
|
||||
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.1.1-0.20251027191944-a4ea43320b81 h1:yHh46pJovYbyiaHCV7oIDinFmy+Fyq36H1BowJgb0M0=
|
||||
github.com/projectdiscovery/gozero v0.1.1-0.20251027191944-a4ea43320b81/go.mod h1:9lmGPBDGZVANzCGjQg+V32n8Y3Cgjo/4kT0E88lsVTI=
|
||||
github.com/projectdiscovery/hmap v0.0.100 h1:DBZ3Req9lWf4P1YC9PRa4eiMvLY0Uxud43NRBcocPfs=
|
||||
github.com/projectdiscovery/hmap v0.0.100/go.mod h1:2O06pR8pHOP9wSmxAoxuM45U7E+UqOqOdlSIeddM0bA=
|
||||
github.com/projectdiscovery/httpx v1.9.0 h1:5yn4ik/LqZ+v3MLgU7+CZJQyND9osW9NmZ3squylxsc=
|
||||
github.com/projectdiscovery/httpx v1.9.0/go.mod h1:jGTRyUHddo2WyK4klWIwQXgGF1Lu39XVyzlue4H3pX8=
|
||||
github.com/projectdiscovery/interactsh v1.3.1 h1:5HzeVGVCAX/cjTguJ+7ClOmML5r97Ty7op9s+/F7BiM=
|
||||
github.com/projectdiscovery/interactsh v1.3.1/go.mod h1:MXQ11EoBPROb4bEw+WP9e4DX4fMhrpS6EwfMfZomBsw=
|
||||
github.com/projectdiscovery/hmap v0.0.99 h1:XPfLnD3CUrMqVCIdpK9ozD7Xmp3simx3T+2j4WWhHnU=
|
||||
github.com/projectdiscovery/hmap v0.0.99/go.mod h1:koyUJi83K5G3w35ZLFXOYZIyYJsO+6hQrgDDN1RBrVE=
|
||||
github.com/projectdiscovery/httpx v1.8.1 h1:50NTzbgnqCgTJ1uawvusJq8Q6g0HM8TwEcxZgWdq5d4=
|
||||
github.com/projectdiscovery/httpx v1.8.1/go.mod h1:ws3cY6c7guy99M1eCYRbyaN57K0pEOguTZymMdxRZzc=
|
||||
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/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-20250715113114-c77eb3567582 h1:eR+0HE//Ciyfwy3HC7fjRyKShSJHYoX2Pv7pPshjK/Q=
|
||||
@@ -885,20 +877,20 @@ github.com/projectdiscovery/mapcidr v1.1.97 h1:7FkxNNVXp+m1rIu5Nv/2SrF9k4+LwP8Qu
|
||||
github.com/projectdiscovery/mapcidr v1.1.97/go.mod h1:9dgTJh1SP02gYZdpzMjm6vtYFkEHQHoTyaVNvaeJ7lA=
|
||||
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.36 h1:88EAYvEplBmn4vlGKenZJtzsGkEWALX3QzPiY930GtA=
|
||||
github.com/projectdiscovery/networkpolicy v0.1.36/go.mod h1:lrm+DXxtH0cGpM4OKhILC+9ktnzrXVYcM0S2Jk+gQcc=
|
||||
github.com/projectdiscovery/nuclei/v3 v3.8.0 h1:UfIDjoHBsvACtvO4x8XIp6COffH+0G4sqco1qrijZqw=
|
||||
github.com/projectdiscovery/nuclei/v3 v3.8.0/go.mod h1:xBCCFK5nMafAuf3sWyOojzL9pKN91tj4Uwj2TK7HhOM=
|
||||
github.com/projectdiscovery/ratelimit v0.0.85 h1:TrqYis/+6Djac20n3kgFXQbN/xj7ywObJpH3xDOd+40=
|
||||
github.com/projectdiscovery/ratelimit v0.0.85/go.mod h1:enLZ8XGL02WPBhuoHAhgvMgOpuU9ALhFpFgCps5lxmM=
|
||||
github.com/projectdiscovery/networkpolicy v0.1.34 h1:TRwNbgMwdx3NC190TKSLwtTvr0JAIZAlnWkOhW0yBME=
|
||||
github.com/projectdiscovery/networkpolicy v0.1.34/go.mod h1:GJ20E7fJoA2vk8ZBSa1Cvc5WyP8RxglF5bZmYgK8jag=
|
||||
github.com/projectdiscovery/nuclei/v3 v3.7.0 h1:XA3QbY9kkYhXNQclykMGlfY0OuEfLjRw5gRctPsC91U=
|
||||
github.com/projectdiscovery/nuclei/v3 v3.7.0/go.mod h1:F0vcGrhwsVzZGuWluMrIeqgzSamBw6sd+YrCeCfi52k=
|
||||
github.com/projectdiscovery/ratelimit v0.0.83 h1:hfb36QvznBrjA4FNfpFE8AYRVBYrfJh8qHVROLQgl54=
|
||||
github.com/projectdiscovery/ratelimit v0.0.83/go.mod h1:z076BrLkBb5yS7uhHNoCTf8X/BvFSGRxwQ8EzEL9afM=
|
||||
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/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.114 h1:COyNKzhA7oa3C/1639WRXeXsKrUJx06paVbN64IHZ3E=
|
||||
github.com/projectdiscovery/retryabledns v1.0.114/go.mod h1:+DyanDr8naxQ2dRO9c4Ezo3NHHXhz8L0tTSRYWhiwyA=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.3.8 h1:TA075ioaVyaM65R3dSzKSbOCiJSvFrlGScxzScu4ik8=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.3.8/go.mod h1:/vas835LvB4aqK9vCPGSgKF7Q7hY/BRcIJ/TgM2sPAY=
|
||||
github.com/projectdiscovery/retryabledns v1.0.113 h1:s+DAzdJ8XhLxRgt5636H0HG9OqHsGRjX9wTrLSTMqlQ=
|
||||
github.com/projectdiscovery/retryabledns v1.0.113/go.mod h1:+DyanDr8naxQ2dRO9c4Ezo3NHHXhz8L0tTSRYWhiwyA=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.3.5 h1:6UXSJOEeeSE/IpI4xPrKRhSLkk3itNajfbgH91WtPPc=
|
||||
github.com/projectdiscovery/retryablehttp-go v1.3.5/go.mod h1:2ma5Itx44tgfZCtHqnI7xbWEmsLXt1qXh+oOaJfmA+g=
|
||||
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=
|
||||
@@ -909,10 +901,10 @@ github.com/projectdiscovery/uncover v1.2.0 h1:31tjYa0v8FB8Ch8hJTxb+2t63vsljdOo0O
|
||||
github.com/projectdiscovery/uncover v1.2.0/go.mod h1:ozqKb++p39Kmh1SmwIpbQ9p0aVGPXuwsb4/X2Kvx6ms=
|
||||
github.com/projectdiscovery/useragent v0.0.107 h1:45gSBda052fv2Gtxtnpx7cu2rWtUpZEQRGAoYGP6F5M=
|
||||
github.com/projectdiscovery/useragent v0.0.107/go.mod h1:yv5ZZLDT/kq6P+NvBcCPq6sjEVQtZGgO+OvvHzZ+WtY=
|
||||
github.com/projectdiscovery/utils v0.10.1 h1:9luYfL7PpN1L/cLO4bAES4+ltDaEBKOUnRiTn920XfM=
|
||||
github.com/projectdiscovery/utils v0.10.1/go.mod h1:x3jGS2YIxnUYxlpB9HWBKf0k+AE83nYCGRX/YStC8G8=
|
||||
github.com/projectdiscovery/wappalyzergo v0.2.76 h1:6zQt6Jmi/hIwD8InWswkk1yhJGWaVEAEzshTGiTGbeM=
|
||||
github.com/projectdiscovery/wappalyzergo v0.2.76/go.mod h1:hRsnKNleH693FFJsBOD5NMUDbxw/Q94f0Oq2OV04Q6M=
|
||||
github.com/projectdiscovery/utils v0.9.0 h1:eu9vdbP0VYXI9nGSLfnOpUqBeW9/B/iSli7U8gPKZw8=
|
||||
github.com/projectdiscovery/utils v0.9.0/go.mod h1:zcVu1QTlMi5763qCol/L3ROnbd/UPSBP8fI5PmcnF6s=
|
||||
github.com/projectdiscovery/wappalyzergo v0.2.65 h1:5hWGkuortLiq0whmVIfxbbE9pDl7Zd5e1rVRIEimOyk=
|
||||
github.com/projectdiscovery/wappalyzergo v0.2.65/go.mod h1:Oc+U2RPJObmpi6LW5lTMEDiKagcKZNkEfZfwrVMURa0=
|
||||
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/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
@@ -941,8 +933,8 @@ github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0ua
|
||||
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
|
||||
github.com/redis/go-redis/v9 v9.11.0 h1:E3S08Gl/nJNn5vkxd2i78wZxWAPNZgUNTp8WIJUAiIs=
|
||||
github.com/redis/go-redis/v9 v9.11.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
|
||||
github.com/refraction-networking/utls v1.8.2 h1:j4Q1gJj0xngdeH+Ox/qND11aEfhpgoEvV+S9iJ2IdQo=
|
||||
github.com/refraction-networking/utls v1.8.2/go.mod h1:jkSOEkLqn+S/jtpEHPOsVv/4V4EVnelwbMQl4vCWXAM=
|
||||
github.com/refraction-networking/utls v1.8.1 h1:yNY1kapmQU8JeM1sSw2H2asfTIwWxIkrMJI0pRUOCAo=
|
||||
github.com/refraction-networking/utls v1.8.1/go.mod h1:jkSOEkLqn+S/jtpEHPOsVv/4V4EVnelwbMQl4vCWXAM=
|
||||
github.com/remeh/sizedwaitgroup v1.0.0 h1:VNGGFwNo/R5+MJBf6yrsr110p0m4/OX4S3DCy7Kyl5E=
|
||||
github.com/remeh/sizedwaitgroup v1.0.0/go.mod h1:3j2R4OIe/SeS6YDhICBy22RWjJC5eNCJ1V+9+NVNYlo=
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
@@ -968,8 +960,12 @@ github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/shirou/gopsutil/v4 v4.26.3 h1:2ESdQt90yU3oXF/CdOlRCJxrP+Am1aBYubTMTfxJ1qc=
|
||||
github.com/shirou/gopsutil/v4 v4.26.3/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ=
|
||||
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
|
||||
github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
|
||||
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
|
||||
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
|
||||
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
|
||||
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
|
||||
github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 h1:17JxqqJY66GmZVHkmAsGEkcIu0oCe3AM420QDgGwZx0=
|
||||
github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466/go.mod h1:9dIRpgIY7hVhoqfe0/FcYp0bpInZaT7dc3BYOprrIUE=
|
||||
github.com/sijms/go-ora/v2 v2.9.0 h1:+iQbUeTeCOFMb5BsOMgUhV8KWyrv9yjKpcK4x7+MFrg=
|
||||
@@ -1015,8 +1011,6 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||
@@ -1028,10 +1022,10 @@ github.com/temoto/robotstxt v1.1.2 h1:W2pOjSJ6SWvldyEuiFXNxz3xZ8aiWX5LbfDiOFd7Fx
|
||||
github.com/temoto/robotstxt v1.1.2/go.mod h1:+1AmkuG3IYkh1kv0d2qEB9Le88ehNO0zwOr3ujewlOo=
|
||||
github.com/tidwall/assert v0.1.0 h1:aWcKyRBUAdLoVebxo95N7+YZVTFF/ASTr7BN4sLP6XI=
|
||||
github.com/tidwall/assert v0.1.0/go.mod h1:QLYtGyeqse53vuELQheYl9dngGCJQ+mTtlxcktb+Kj8=
|
||||
github.com/tidwall/btree v1.8.1 h1:27ehoXvm5AG/g+1VxLS1SD3vRhp/H7LuEfwNvddEdmA=
|
||||
github.com/tidwall/btree v1.8.1/go.mod h1:jBbTdUWhSZClZWoDg54VnvV7/54modSOzDN7VXftj1A=
|
||||
github.com/tidwall/buntdb v1.3.2 h1:qd+IpdEGs0pZci37G4jF51+fSKlkuUTMXuHhXL1AkKg=
|
||||
github.com/tidwall/buntdb v1.3.2/go.mod h1:lZZrZUWzlyDJKlLQ6DKAy53LnG7m5kHyrEHvvcDmBpU=
|
||||
github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI=
|
||||
github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY=
|
||||
github.com/tidwall/buntdb v1.3.1 h1:HKoDF01/aBhl9RjYtbaLnvX9/OuenwvQiC3OP1CcL4o=
|
||||
github.com/tidwall/buntdb v1.3.1/go.mod h1:lZZrZUWzlyDJKlLQ6DKAy53LnG7m5kHyrEHvvcDmBpU=
|
||||
github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
||||
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
@@ -1051,10 +1045,10 @@ github.com/tidwall/tinyqueue v0.1.1 h1:SpNEvEggbpyN5DIReaJ2/1ndroY8iyEGxPYxoSaym
|
||||
github.com/tidwall/tinyqueue v0.1.1/go.mod h1:O/QNHwrnjqr6IHItYrzoHAKYhBkLI67Q096fQP5zMYw=
|
||||
github.com/tim-ywliu/nested-logrus-formatter v1.3.2 h1:jugNJ2/CNCI79SxOJCOhwUHeN3O7/7/bj+ZRGOFlCSw=
|
||||
github.com/tim-ywliu/nested-logrus-formatter v1.3.2/go.mod h1:oGPmcxZB65j9Wo7mCnQKSrKEJtVDqyjD666SGmyStXI=
|
||||
github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA=
|
||||
github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI=
|
||||
github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw=
|
||||
github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ=
|
||||
github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4=
|
||||
github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4=
|
||||
github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso=
|
||||
github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ=
|
||||
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
|
||||
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs=
|
||||
github.com/trivago/tgo v1.0.7 h1:uaWH/XIy9aWYWpjm2CU3RpcqZXmX2ysQ9/Go+d9gyrM=
|
||||
@@ -1086,8 +1080,8 @@ github.com/weppos/publicsuffix-go v0.12.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8L
|
||||
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.40.2/go.mod h1:XsLZnULC3EJ1Gvk9GVjuCTZ8QUu9ufE4TZpOizDShko=
|
||||
github.com/weppos/publicsuffix-go v0.50.3 h1:eT5dcjHQcVDNc0igpFEsGHKIip30feuB2zuuI9eJxiE=
|
||||
github.com/weppos/publicsuffix-go v0.50.3/go.mod h1:/rOa781xBykZhHK/I3QeHo92qdDKVmKZKF7s8qAEM/4=
|
||||
github.com/weppos/publicsuffix-go v0.50.3-0.20260104170930-90713dec78f2 h1:LiQSn5u8Nc6V/GixI+SWxt+YkNIyfKIlkVRULSw2Zt0=
|
||||
github.com/weppos/publicsuffix-go v0.50.3-0.20260104170930-90713dec78f2/go.mod h1:CbQCKDtXF8UcT7hrxeMa0MDjwhpOI9iYOU7cfq+yo8k=
|
||||
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=
|
||||
@@ -1135,18 +1129,19 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||
github.com/yuin/goldmark v1.7.13 h1:GPddIs617DnBLFFVJFgpo1aBfe/4xcvMc3SB5t/D0pA=
|
||||
github.com/yuin/goldmark v1.7.13/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
|
||||
github.com/yuin/goldmark-emoji v1.0.6 h1:QWfF2FYaXwL74tfGOW5izeiZepUDroDJfWubQI9HTHs=
|
||||
github.com/yuin/goldmark-emoji v1.0.6/go.mod h1:ukxJDKFpdFb5x0a5HqbdlcKtebh086iJpI31LTKmWuA=
|
||||
github.com/yuin/goldmark-emoji v1.0.5 h1:EMVWyCGPlXJfUXBXpuMu+ii3TIaxbVBnEX9uaDC4cIk=
|
||||
github.com/yuin/goldmark-emoji v1.0.5/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U=
|
||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
github.com/zcalusic/sysinfo v1.1.3 h1:u/AVENkuoikKuIZ4sUEJ6iibpmQP6YpGD8SSMCrqAF0=
|
||||
github.com/zcalusic/sysinfo v1.1.3/go.mod h1:NX+qYnWGtJVPV0yWldff9uppNKU4h40hJIRPf/pGLv4=
|
||||
github.com/zcalusic/sysinfo v1.0.2 h1:nwTTo2a+WQ0NXwo0BGRojOJvJ/5XKvQih+2RrtWqfxc=
|
||||
github.com/zcalusic/sysinfo v1.0.2/go.mod h1:kluzTYflRWo6/tXVMJPdEjShsbPpsFRyy+p1mBQPC30=
|
||||
github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
|
||||
github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
||||
github.com/zeebo/blake3 v0.2.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI=
|
||||
github.com/zeebo/blake3 v0.2.4/go.mod h1:7eeQ6d2iXWRGF6npfaxl2CU+xy2Fjo2gxeyZGCRUjcE=
|
||||
github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg=
|
||||
github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ=
|
||||
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
|
||||
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
|
||||
github.com/zmap/rc2 v0.0.0-20131011165748-24b9757f5521/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE=
|
||||
@@ -1165,33 +1160,33 @@ github.com/zmap/zgrab2 v0.1.8/go.mod h1:5d8HSmUwvllx4q1qG50v/KXphkg45ZzWdaQtgTFn
|
||||
github.com/zmap/zlint/v3 v3.0.0/go.mod h1:paGwFySdHIBEMJ61YjoqT4h7Ge+fdYG4sUQhnTb1lJ8=
|
||||
gitlab.com/gitlab-org/api/client-go v0.130.1 h1:1xF5C5Zq3sFeNg3PzS2z63oqrxifne3n/OnbI7nptRc=
|
||||
gitlab.com/gitlab-org/api/client-go v0.130.1/go.mod h1:ZhSxLAWadqP6J9lMh40IAZOlOxBLPRh7yFOXR/bMJWM=
|
||||
go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=
|
||||
go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E=
|
||||
go.mongodb.org/mongo-driver v1.17.9 h1:IexDdCuuNJ3BHrELgBlyaH9p60JXAvdzWR128q+U5tU=
|
||||
go.mongodb.org/mongo-driver v1.17.9/go.mod h1:LlOhpH5NUEfhxcAwG0UEkMqwYcc4JU18gtCdGudk/tQ=
|
||||
go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk=
|
||||
go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk=
|
||||
go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw=
|
||||
go.mongodb.org/mongo-driver v1.17.4/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 h1:Hf9xI/XLML9ElpiHVDNwvqI0hIFlzV8dgIr35kV1kRU=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0/go.mod h1:NfchwuyNoMcZ5MLHwPrODwUF1HWCXWrL31s8gSAdIKY=
|
||||
go.opentelemetry.io/otel v1.41.0 h1:YlEwVsGAlCvczDILpUXpIpPSL/VPugt7zHThEMLce1c=
|
||||
go.opentelemetry.io/otel v1.41.0/go.mod h1:Yt4UwgEKeT05QbLwbyHXEwhnjxNO6D8L5PQP51/46dE=
|
||||
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
|
||||
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 h1:aTL7F04bJHUlztTsNGJ2l+6he8c+y/b//eR0jjjemT4=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0/go.mod h1:kldtb7jDTeol0l3ewcmd8SDvx3EmIE7lyvqbasU3QC4=
|
||||
go.opentelemetry.io/otel/metric v1.41.0 h1:rFnDcs4gRzBcsO9tS8LCpgR0dxg4aaxWlJxCno7JlTQ=
|
||||
go.opentelemetry.io/otel/metric v1.41.0/go.mod h1:xPvCwd9pU0VN8tPZYzDZV/BMj9CM9vs00GuBjeKhJps=
|
||||
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
|
||||
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
|
||||
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
|
||||
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
|
||||
go.opentelemetry.io/otel/trace v1.41.0 h1:Vbk2co6bhj8L59ZJ6/xFTskY+tGAbOnCtQGVVa9TIN0=
|
||||
go.opentelemetry.io/otel/trace v1.41.0/go.mod h1:U1NU4ULCoxeDKc09yCWdWe+3QoyweJcISEVa1RBzOis=
|
||||
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
|
||||
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
||||
go.opentelemetry.io/proto/otlp v1.8.0 h1:fRAZQDcAFHySxpJ1TwlA1cJ4tvcrw7nXl9xWWC8N5CE=
|
||||
go.opentelemetry.io/proto/otlp v1.8.0/go.mod h1:tIeYOeNBU4cvmPqpaji1P+KbB4Oloai8wN4rWzRrFF0=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
@@ -1200,10 +1195,6 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
go.uber.org/zap/exp v0.3.0 h1:6JYzdifzYkGmTdRR59oYH+Ng7k49H9qVpWwNSsGJj3U=
|
||||
go.uber.org/zap/exp v0.3.0/go.mod h1:5I384qq7XGxYyByIhHm6jg5CHkGY0nsTfbDLgDDlgJQ=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc=
|
||||
go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU=
|
||||
goftp.io/server/v2 v2.0.1 h1:H+9UbCX2N206ePDSVNCjBftOKOgil6kQ5RAQNx5hJwE=
|
||||
@@ -1234,8 +1225,8 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf
|
||||
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.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
|
||||
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
|
||||
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
||||
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
||||
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=
|
||||
@@ -1246,8 +1237,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM=
|
||||
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80=
|
||||
golang.org/x/exp v0.0.0-20250911091902-df9299821621 h1:2id6c1/gto0kaHYyrixvknJ8tUK/Qs5IsmBtrc+FtgU=
|
||||
golang.org/x/exp v0.0.0-20250911091902-df9299821621/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@@ -1273,8 +1264,8 @@ 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.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM=
|
||||
golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU=
|
||||
golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
|
||||
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -1331,8 +1322,8 @@ 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.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
|
||||
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
|
||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
||||
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=
|
||||
@@ -1361,8 +1352,8 @@ 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/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
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=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -1429,8 +1420,8 @@ 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.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
|
||||
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
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=
|
||||
@@ -1446,8 +1437,8 @@ 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.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY=
|
||||
golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY=
|
||||
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
|
||||
golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=
|
||||
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=
|
||||
@@ -1466,8 +1457,8 @@ 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/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
||||
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
||||
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=
|
||||
@@ -1522,8 +1513,8 @@ 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.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c=
|
||||
golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI=
|
||||
golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
|
||||
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -1658,6 +1649,7 @@ mellium.im/sasl v0.3.2 h1:PT6Xp7ccn9XaXAnJ03FcEjmAn7kK1x7aoXV6F+Vmrl0=
|
||||
mellium.im/sasl v0.3.2/go.mod h1:NKXDi1zkr+BlMHLQjY3ofYuU4KSPFxknb8mfEu6SveY=
|
||||
moul.io/http2curl v1.0.0 h1:6XwpyZOYsgZJrU8exnG87ncVkU1FVCcTRpwzOkTDUi8=
|
||||
moul.io/http2curl v1.0.0/go.mod h1:f6cULg+e4Md/oW1cYmwW4IWQOVl2lGbmCNGOHvzX2kE=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -39,11 +39,9 @@ type Settings struct {
|
||||
Template string
|
||||
CMS bool
|
||||
Headers bool
|
||||
SecurityHeaders bool
|
||||
CloudStorage bool
|
||||
SubdomainTakeover bool
|
||||
Shodan bool
|
||||
SecurityTrails bool
|
||||
SQL bool
|
||||
LFI bool
|
||||
Framework bool
|
||||
@@ -91,11 +89,9 @@ func Parse() *Settings {
|
||||
flagSet.BoolVar(&settings.JavaScript, "js", false, "Enable JavaScript scans"),
|
||||
flagSet.BoolVar(&settings.CMS, "cms", false, "Enable CMS detection"),
|
||||
flagSet.BoolVar(&settings.Headers, "headers", false, "Enable HTTP Header Analysis"),
|
||||
flagSet.BoolVarP(&settings.SecurityHeaders, "security-headers", "sh", false, "Enable security header analysis (missing/weak headers)"),
|
||||
flagSet.BoolVar(&settings.CloudStorage, "c3", false, "Enable C3 Misconfiguration Scan"),
|
||||
flagSet.BoolVar(&settings.SubdomainTakeover, "st", false, "Enable Subdomain Takeover Check"),
|
||||
flagSet.BoolVar(&settings.Shodan, "shodan", false, "Enable Shodan lookup (requires SHODAN_API_KEY env var)"),
|
||||
flagSet.BoolVar(&settings.SecurityTrails, "securitytrails", false, "Enable SecurityTrails domain discovery (requires SECURITYTRAILS_API_KEY env var)"),
|
||||
flagSet.BoolVar(&settings.SQL, "sql", false, "Enable SQL reconnaissance (admin panels, error disclosure)"),
|
||||
flagSet.BoolVar(&settings.LFI, "lfi", false, "Enable LFI (Local File Inclusion) reconnaissance"),
|
||||
flagSet.BoolVar(&settings.Framework, "framework", false, "Enable framework detection"),
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -37,7 +37,7 @@ var defaultLogger = &Logger{
|
||||
// Init creates the log directory if it doesn't exist.
|
||||
func Init(dir string) error {
|
||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||
if err := os.Mkdir(dir, 0o750); err != nil {
|
||||
if err = os.Mkdir(dir, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -62,7 +62,7 @@ func (l *Logger) getWriter(path string) (*bufio.Writer, error) {
|
||||
return w, nil
|
||||
}
|
||||
|
||||
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o600)
|
||||
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -124,10 +124,7 @@ func (l *Logger) Close() error {
|
||||
|
||||
// CreateFile initializes a log file for the given URL and writes the header.
|
||||
func CreateFile(logFiles *[]string, url string, dir string) error {
|
||||
sanitizedURL := url
|
||||
if _, after, ok := strings.Cut(url, "://"); ok {
|
||||
sanitizedURL = after
|
||||
}
|
||||
sanitizedURL := strings.Split(url, "://")[1]
|
||||
path := filepath.Join(dir, sanitizedURL+".log")
|
||||
|
||||
header := fmt.Sprintf(" _____________\n__________(_)__ __/\n__ ___/_ /__ /_ \n_(__ )_ / _ __/ \n/____/ /_/ /_/ \n\nsif log file for %s\nhttps://sif.sh\n\n", url)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -228,9 +228,9 @@ func checkMatchers(matchers []Matcher, resp *http.Response, body string) bool {
|
||||
}
|
||||
|
||||
// Default to AND condition across matchers
|
||||
for i := range matchers {
|
||||
matched := checkMatcher(&matchers[i], resp, body)
|
||||
if matchers[i].Negative {
|
||||
for _, m := range matchers {
|
||||
matched := checkMatcher(m, resp, body)
|
||||
if m.Negative {
|
||||
matched = !matched
|
||||
}
|
||||
if !matched {
|
||||
@@ -242,7 +242,7 @@ func checkMatchers(matchers []Matcher, resp *http.Response, body string) bool {
|
||||
}
|
||||
|
||||
// checkMatcher evaluates a single matcher.
|
||||
func checkMatcher(m *Matcher, resp *http.Response, body string) bool {
|
||||
func checkMatcher(m Matcher, resp *http.Response, body string) bool {
|
||||
part := getPart(m.Part, resp, body)
|
||||
|
||||
switch m.Type {
|
||||
@@ -352,7 +352,8 @@ func runExtractors(extractors []Extractor, resp *http.Response, body string) map
|
||||
for _, e := range extractors {
|
||||
part := getPart(e.Part, resp, body)
|
||||
|
||||
if e.Type == "regex" {
|
||||
switch e.Type {
|
||||
case "regex":
|
||||
for _, pattern := range e.Regex {
|
||||
re, err := regexp.Compile(pattern)
|
||||
if err != nil {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -16,7 +16,7 @@
|
||||
: SIF - Blazing-fast pentesting suite :
|
||||
: Blaze - BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -14,22 +14,22 @@ package format
|
||||
|
||||
import (
|
||||
"github.com/dropalldatabases/sif/internal/styles"
|
||||
nucleiout "github.com/projectdiscovery/nuclei/v3/pkg/output"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/output"
|
||||
)
|
||||
|
||||
func FormatLine(event *nucleiout.ResultEvent) string {
|
||||
line := event.TemplateID
|
||||
func FormatLine(event *output.ResultEvent) string {
|
||||
output := event.TemplateID
|
||||
|
||||
if event.MatcherName != "" {
|
||||
line += ":" + styles.Highlight.Render(event.MatcherName)
|
||||
output += ":" + styles.Highlight.Render(event.MatcherName)
|
||||
} else if event.ExtractorName != "" {
|
||||
line += ":" + styles.Highlight.Render(event.ExtractorName)
|
||||
output += ":" + styles.Highlight.Render(event.ExtractorName)
|
||||
}
|
||||
|
||||
line += " [" + event.Type + "]"
|
||||
line += " [" + formatSeverity(event.Info.SeverityHolder.Severity.String()) + "]"
|
||||
output += " [" + event.Type + "]"
|
||||
output += " [" + formatSeverity(event.Info.SeverityHolder.Severity.String()) + "]"
|
||||
|
||||
return line
|
||||
return output
|
||||
}
|
||||
|
||||
func formatSeverity(severity string) string {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -15,14 +15,11 @@ package templates
|
||||
import (
|
||||
"archive/tar"
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/charmbracelet/log"
|
||||
)
|
||||
@@ -40,12 +37,7 @@ func Install(logger *log.Logger) error {
|
||||
|
||||
logger.Infof("nuclei-templates directory not found. Installing...")
|
||||
|
||||
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, fmt.Sprintf(archive, ref), http.NoBody)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
resp, err := http.Get(fmt.Sprintf(archive, ref))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -55,55 +47,37 @@ func Install(logger *log.Logger) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if cerr := tarball.Close(); cerr != nil {
|
||||
logger.Warnf("closing gzip reader: %v", cerr)
|
||||
}
|
||||
}()
|
||||
defer tarball.Close()
|
||||
|
||||
data := tar.NewReader(tarball)
|
||||
|
||||
dest, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cleanDest := filepath.Clean(dest)
|
||||
|
||||
for {
|
||||
header, err := data.Next()
|
||||
if errors.Is(err, io.EOF) {
|
||||
if errors.Is(io.EOF, err) {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// guard against path traversal ("Zip Slip"): the resolved path must
|
||||
// stay within the extraction directory before any filesystem op.
|
||||
target := filepath.Join(cleanDest, header.Name)
|
||||
if !strings.HasPrefix(target, cleanDest+string(os.PathSeparator)) {
|
||||
return fmt.Errorf("invalid archive entry %q: escapes extraction directory", header.Name)
|
||||
}
|
||||
|
||||
switch header.Typeflag {
|
||||
case tar.TypeDir:
|
||||
if err := os.Mkdir(target, 0o750); err != nil {
|
||||
if err := os.Mkdir(header.Name, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
case tar.TypeReg:
|
||||
file, err := os.Create(target)
|
||||
file, err := os.Create(header.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := io.Copy(file, data); err != nil {
|
||||
file.Close()
|
||||
return err
|
||||
}
|
||||
file.Close()
|
||||
}
|
||||
}
|
||||
|
||||
if err := os.Rename(fmt.Sprintf("nuclei-templates-%s", ref), "nuclei-templates"); err != nil {
|
||||
if err = os.Rename(fmt.Sprintf("nuclei-templates-%s", ref), "nuclei-templates"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
|
||||
+12
-39
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -28,13 +28,12 @@ const (
|
||||
|
||||
// Progress displays a progress bar for operations with known counts
|
||||
type Progress struct {
|
||||
total int64
|
||||
current int64
|
||||
message string
|
||||
lastItem string
|
||||
mu sync.Mutex
|
||||
paused bool
|
||||
lastShown int // last printed milestone bucket in non-tty mode
|
||||
total int64
|
||||
current int64
|
||||
message string
|
||||
lastItem string
|
||||
mu sync.Mutex
|
||||
paused bool
|
||||
}
|
||||
|
||||
// NewProgress creates a new progress bar
|
||||
@@ -106,35 +105,10 @@ func (p *Progress) render() {
|
||||
if !IsTTY {
|
||||
current := atomic.LoadInt64(&p.current)
|
||||
total := p.total
|
||||
if total <= 0 {
|
||||
return
|
||||
}
|
||||
percent := int(current * 100 / total)
|
||||
|
||||
// map current to a milestone bucket (0=none,1..5). concurrent workers
|
||||
// hammer the same bucket, so only print when the bucket advances.
|
||||
bucket := 0
|
||||
switch {
|
||||
case current >= total:
|
||||
bucket = 5
|
||||
case percent >= 75:
|
||||
bucket = 4
|
||||
case percent >= 50:
|
||||
bucket = 3
|
||||
case percent >= 25:
|
||||
bucket = 2
|
||||
case current >= 1:
|
||||
bucket = 1
|
||||
}
|
||||
|
||||
p.mu.Lock()
|
||||
advanced := bucket > p.lastShown
|
||||
if advanced {
|
||||
p.lastShown = bucket
|
||||
}
|
||||
p.mu.Unlock()
|
||||
|
||||
if advanced {
|
||||
// Print at 0%, 25%, 50%, 75%, 100%
|
||||
if current == 1 || percent == 25 || percent == 50 || percent == 75 || current == total {
|
||||
fmt.Printf(" [%d%%] %d/%d\n", percent, current, total)
|
||||
}
|
||||
return
|
||||
@@ -164,12 +138,11 @@ func (p *Progress) render() {
|
||||
|
||||
bar := ""
|
||||
for i := 0; i < progressWidth; i++ {
|
||||
switch {
|
||||
case i < filled:
|
||||
if i < filled {
|
||||
bar += progressFilled
|
||||
case i == filled && current < total:
|
||||
} else if i == filled && current < total {
|
||||
bar += progressCurrent
|
||||
default:
|
||||
} else {
|
||||
bar += progressEmpty
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
: :
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
*/
|
||||
|
||||
package output
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// the non-tty milestone path divides current*100/total, so a zero-total bar
|
||||
// used to panic with integer divide-by-zero when piped or redirected.
|
||||
func TestProgressZeroTotalNoPanic(t *testing.T) {
|
||||
p := NewProgress(0, "scanning")
|
||||
p.Increment("item")
|
||||
p.Set(0, "item")
|
||||
p.Done()
|
||||
}
|
||||
|
||||
func TestProgressCounts(t *testing.T) {
|
||||
p := NewProgress(4, "scanning")
|
||||
for i := 0; i < 4; i++ {
|
||||
p.Increment("x")
|
||||
}
|
||||
if p.current != 4 {
|
||||
t.Errorf("current = %d, want 4", p.current)
|
||||
}
|
||||
}
|
||||
|
||||
// many concurrent workers used to spam the same milestone bucket (e.g. ten
|
||||
// "[25%] .../1000" lines). each bucket must now print at most once.
|
||||
func TestProgressNonTTYDedupesMilestones(t *testing.T) {
|
||||
savedTTY, savedAPI := IsTTY, apiMode
|
||||
IsTTY, apiMode = false, false
|
||||
defer func() { IsTTY, apiMode = savedTTY, savedAPI }()
|
||||
|
||||
out := captureStdout(t, func() {
|
||||
p := NewProgress(1000, "scanning")
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < 40; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for j := 0; j < 25; j++ {
|
||||
p.Increment("x")
|
||||
}
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
})
|
||||
|
||||
lines := strings.Count(out, "\n")
|
||||
if lines > 5 {
|
||||
t.Errorf("printed %d milestone lines, want <=5:\n%s", lines, out)
|
||||
}
|
||||
}
|
||||
|
||||
func captureStdout(t *testing.T, fn func()) string {
|
||||
t.Helper()
|
||||
r, w, err := os.Pipe()
|
||||
if err != nil {
|
||||
t.Fatalf("pipe: %v", err)
|
||||
}
|
||||
saved := os.Stdout
|
||||
os.Stdout = w
|
||||
|
||||
done := make(chan string, 1)
|
||||
go func() {
|
||||
buf := make([]byte, 0, 4096)
|
||||
tmp := make([]byte, 1024)
|
||||
for {
|
||||
n, rerr := r.Read(tmp)
|
||||
buf = append(buf, tmp[:n]...)
|
||||
if rerr != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
done <- string(buf)
|
||||
}()
|
||||
|
||||
fn()
|
||||
os.Stdout = saved
|
||||
w.Close()
|
||||
return <-done
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
/*
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
: :
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
*/
|
||||
|
||||
// Package patchnotes shows release notes pulled from the github releases.
|
||||
package patchnotes
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/charmbracelet/glamour"
|
||||
)
|
||||
|
||||
const releasesAPI = "https://api.github.com/repos/vmfunc/sif/releases"
|
||||
|
||||
type release struct {
|
||||
TagName string `json:"tag_name"`
|
||||
Name string `json:"name"`
|
||||
Body string `json:"body"`
|
||||
URL string `json:"html_url"`
|
||||
}
|
||||
|
||||
func fetch(ctx context.Context, path string) (*release, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, releasesAPI+path, http.NoBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set("Accept", "application/vnd.github+json")
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("github returned %s", resp.Status)
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(io.LimitReader(resp.Body, 5*1024*1024))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var r release
|
||||
if err := json.Unmarshal(body, &r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &r, nil
|
||||
}
|
||||
|
||||
// render turns a release's markdown body into styled terminal output, falling
|
||||
// back to the raw body if glamour can't render it.
|
||||
func render(r *release) string {
|
||||
out, err := glamour.Render(r.Body, "dark")
|
||||
if err != nil {
|
||||
return r.Body
|
||||
}
|
||||
return fmt.Sprintf("%s\n%s", r.TagName, out)
|
||||
}
|
||||
|
||||
// Print fetches the latest release and writes its notes to stdout. tag may be
|
||||
// empty for the latest release, or a "vX" tag for a specific one.
|
||||
func Print(tag string) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
path := "/latest"
|
||||
if tag != "" {
|
||||
path = "/tags/" + tag
|
||||
}
|
||||
|
||||
r, err := fetch(ctx, path)
|
||||
if err != nil {
|
||||
fmt.Printf("couldn't fetch patch notes: %v\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Print(render(r))
|
||||
}
|
||||
|
||||
// ShowOnce prints the running version's notes the first time that version runs,
|
||||
// then records it so it isn't shown again. best-effort: dev builds, the
|
||||
// SIF_NO_PATCHNOTES opt-out, and any network failure stay silent.
|
||||
func ShowOnce(version string) {
|
||||
// only clean release tags (e.g. 2026.6.7) map to a github release; skip dev
|
||||
// and pseudo-versions (a commit/dirty build) so we don't make a doomed call.
|
||||
if version == "" || version == "dev" || strings.ContainsAny(version, "-+") || os.Getenv("SIF_NO_PATCHNOTES") != "" {
|
||||
return
|
||||
}
|
||||
|
||||
path, err := statePath()
|
||||
if err != nil || hasSeen(path, version) {
|
||||
return
|
||||
}
|
||||
// record before fetching so a flaky network doesn't nag on every run
|
||||
recordSeen(path, version)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
|
||||
r, err := fetch(ctx, "/tags/v"+version)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fmt.Printf("\nwhat's new in this release:\n%s", render(r))
|
||||
}
|
||||
|
||||
func statePath() (string, error) {
|
||||
dir, err := os.UserConfigDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(dir, "sif", "seen_version"), nil
|
||||
}
|
||||
|
||||
func hasSeen(path, version string) bool {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return strings.TrimSpace(string(data)) == version
|
||||
}
|
||||
|
||||
func recordSeen(path, version string) {
|
||||
if err := os.MkdirAll(filepath.Dir(path), 0o750); err != nil {
|
||||
return
|
||||
}
|
||||
_ = os.WriteFile(path, []byte(version), 0o600)
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
: :
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
*/
|
||||
|
||||
package patchnotes
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSeenRoundTrip(t *testing.T) {
|
||||
path := filepath.Join(t.TempDir(), "sif", "seen_version")
|
||||
|
||||
if hasSeen(path, "2026.6.7") {
|
||||
t.Fatal("nothing recorded yet, hasSeen should be false")
|
||||
}
|
||||
|
||||
recordSeen(path, "2026.6.7")
|
||||
if !hasSeen(path, "2026.6.7") {
|
||||
t.Error("recorded version should read back as seen")
|
||||
}
|
||||
if hasSeen(path, "2026.6.8") {
|
||||
t.Error("a different version should not be seen")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenderIncludesTag(t *testing.T) {
|
||||
out := render(&release{TagName: "v2026.6.7", Body: "## what's changed\n- a thing"})
|
||||
if !strings.Contains(out, "v2026.6.7") {
|
||||
t.Errorf("rendered notes should include the tag, got %q", out)
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -15,10 +15,9 @@ package builtin
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/dropalldatabases/sif/internal/modules"
|
||||
"github.com/dropalldatabases/sif/internal/scan/frameworks"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type FrameworksModule struct{}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -15,7 +15,6 @@ package builtin
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/dropalldatabases/sif/internal/modules"
|
||||
"github.com/dropalldatabases/sif/internal/scan"
|
||||
)
|
||||
@@ -52,8 +51,7 @@ func (m *NucleiModule) Execute(ctx context.Context, target string, opts modules.
|
||||
}
|
||||
|
||||
// Process nuclei results into module findings
|
||||
for i := range nucleiResults {
|
||||
event := &nucleiResults[i]
|
||||
for _, event := range nucleiResults {
|
||||
severity := "info"
|
||||
|
||||
switch event.Info.SeverityHolder.Severity.String() {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -21,5 +21,4 @@ func Register() {
|
||||
modules.Register(&FrameworksModule{})
|
||||
modules.Register(&NucleiModule{})
|
||||
modules.Register(&WhoisModule{})
|
||||
modules.Register(&SecurityTrailsModule{})
|
||||
}
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
: :
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
*/
|
||||
|
||||
package builtin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/dropalldatabases/sif/internal/modules"
|
||||
"github.com/dropalldatabases/sif/internal/scan"
|
||||
)
|
||||
|
||||
type SecurityTrailsModule struct{}
|
||||
|
||||
func (m *SecurityTrailsModule) Info() modules.Info {
|
||||
return modules.Info{
|
||||
ID: "securitytrails-lookup",
|
||||
Name: "SecurityTrails Domain Discovery",
|
||||
Author: "sif",
|
||||
Severity: "info",
|
||||
Description: "Queries SecurityTrails API for subdomains and associated domains (requires SECURITYTRAILS_API_KEY)",
|
||||
Tags: []string{"recon", "osint", "dns", "subdomains"},
|
||||
}
|
||||
}
|
||||
|
||||
func (m *SecurityTrailsModule) Type() modules.ModuleType {
|
||||
return modules.TypeScript
|
||||
}
|
||||
|
||||
func (m *SecurityTrailsModule) Execute(ctx context.Context, target string, opts modules.Options) (*modules.Result, error) {
|
||||
stResult, err := scan.SecurityTrails(target, opts.Timeout, opts.LogDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := &modules.Result{
|
||||
ModuleID: m.Info().ID,
|
||||
Target: target,
|
||||
Findings: []modules.Finding{},
|
||||
}
|
||||
|
||||
if stResult == nil {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
finding := modules.Finding{
|
||||
URL: target,
|
||||
Severity: "info",
|
||||
Evidence: fmt.Sprintf("discovered %d subdomains and %d associated domains",
|
||||
len(stResult.Subdomains), len(stResult.AssociatedDomains)),
|
||||
Extracted: map[string]string{
|
||||
"domain": stResult.Domain,
|
||||
"subdomain_count": fmt.Sprintf("%d", len(stResult.Subdomains)),
|
||||
"associated_count": fmt.Sprintf("%d", len(stResult.AssociatedDomains)),
|
||||
},
|
||||
}
|
||||
|
||||
if len(stResult.Subdomains) > 0 {
|
||||
finding.Extracted["subdomains"] = strings.Join(stResult.Subdomains, ", ")
|
||||
}
|
||||
|
||||
if len(stResult.AssociatedDomains) > 0 {
|
||||
finding.Extracted["associated_domains"] = strings.Join(stResult.AssociatedDomains, ", ")
|
||||
}
|
||||
|
||||
result.Findings = append(result.Findings, finding)
|
||||
return result, nil
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -15,10 +15,9 @@ package builtin
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/dropalldatabases/sif/internal/modules"
|
||||
"github.com/dropalldatabases/sif/internal/scan"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type ShodanModule struct{}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -14,7 +14,6 @@ package builtin
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/dropalldatabases/sif/internal/modules"
|
||||
"github.com/dropalldatabases/sif/internal/scan"
|
||||
)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -13,7 +13,6 @@
|
||||
package scan
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -31,9 +30,9 @@ type CloudStorageResult struct {
|
||||
}
|
||||
|
||||
func CloudStorage(url string, timeout time.Duration, logdir string) ([]CloudStorageResult, error) {
|
||||
fmt.Println(styles.Separator.Render("Starting " + styles.Status.Render("Cloud Storage Misconfiguration Scan") + "..."))
|
||||
fmt.Println(styles.Separator.Render("☁️ Starting " + styles.Status.Render("Cloud Storage Misconfiguration Scan") + "..."))
|
||||
|
||||
sanitizedURL := stripScheme(url)
|
||||
sanitizedURL := strings.Split(url, "://")[1]
|
||||
|
||||
if logdir != "" {
|
||||
if err := logger.WriteHeader(sanitizedURL, logdir, "Cloud Storage Misconfiguration Scan"); err != nil {
|
||||
@@ -43,7 +42,7 @@ func CloudStorage(url string, timeout time.Duration, logdir string) ([]CloudStor
|
||||
}
|
||||
|
||||
cloudlog := log.NewWithOptions(os.Stderr, log.Options{
|
||||
Prefix: "C3",
|
||||
Prefix: "C3 ☁️",
|
||||
}).With("url", url)
|
||||
|
||||
client := &http.Client{
|
||||
@@ -55,7 +54,7 @@ func CloudStorage(url string, timeout time.Duration, logdir string) ([]CloudStor
|
||||
var results []CloudStorageResult
|
||||
|
||||
for _, bucket := range potentialBuckets {
|
||||
isPublic, err := checkS3Bucket(context.TODO(), bucket, client)
|
||||
isPublic, err := checkS3Bucket(bucket, client)
|
||||
if err != nil {
|
||||
cloudlog.Errorf("Error checking S3 bucket %s: %v", bucket, err)
|
||||
continue
|
||||
@@ -70,7 +69,7 @@ func CloudStorage(url string, timeout time.Duration, logdir string) ([]CloudStor
|
||||
if isPublic {
|
||||
cloudlog.Warnf("Public S3 bucket found: %s", styles.Highlight.Render(bucket))
|
||||
if logdir != "" {
|
||||
_ = logger.Write(sanitizedURL, logdir, fmt.Sprintf("Public S3 bucket found: %s\n", bucket))
|
||||
logger.Write(sanitizedURL, logdir, fmt.Sprintf("Public S3 bucket found: %s\n", bucket))
|
||||
}
|
||||
} else {
|
||||
cloudlog.Infof("S3 bucket is not public/found: %s", bucket)
|
||||
@@ -81,27 +80,27 @@ func CloudStorage(url string, timeout time.Duration, logdir string) ([]CloudStor
|
||||
}
|
||||
|
||||
func extractPotentialBuckets(url string) []string {
|
||||
// TODO: handle non-adjacent label combos and strip the tld
|
||||
// This is a simple implementation.
|
||||
// TODO: add more cases
|
||||
parts := strings.Split(url, ".")
|
||||
var buckets []string
|
||||
for i, part := range parts {
|
||||
buckets = append(buckets, part, part+"-s3", "s3-"+part)
|
||||
buckets = append(buckets, part)
|
||||
buckets = append(buckets, part+"-s3")
|
||||
buckets = append(buckets, "s3-"+part)
|
||||
|
||||
if i < len(parts)-1 {
|
||||
domainExtension := part + "-" + parts[i+1]
|
||||
buckets = append(buckets, domainExtension, parts[i+1]+"-"+part)
|
||||
buckets = append(buckets, domainExtension)
|
||||
buckets = append(buckets, parts[i+1]+"-"+part)
|
||||
}
|
||||
}
|
||||
return buckets
|
||||
}
|
||||
|
||||
func checkS3Bucket(ctx context.Context, bucket string, client *http.Client) (bool, error) {
|
||||
func checkS3Bucket(bucket string, client *http.Client) (bool, error) {
|
||||
url := fmt.Sprintf("https://%s.s3.amazonaws.com", bucket)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, http.NoBody)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
resp, err := client.Get(url)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
+5
-16
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -13,7 +13,6 @@
|
||||
package scan
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
@@ -35,7 +34,7 @@ func CMS(url string, timeout time.Duration, logdir string) (*CMSResult, error) {
|
||||
spin := output.NewSpinner("Detecting content management system")
|
||||
spin.Start()
|
||||
|
||||
sanitizedURL := stripScheme(url)
|
||||
sanitizedURL := strings.Split(url, "://")[1]
|
||||
|
||||
if logdir != "" {
|
||||
if err := logger.WriteHeader(sanitizedURL, logdir, "CMS detection"); err != nil {
|
||||
@@ -49,13 +48,7 @@ func CMS(url string, timeout time.Duration, logdir string) (*CMSResult, error) {
|
||||
Timeout: timeout,
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, url, http.NoBody)
|
||||
if err != nil {
|
||||
spin.Stop()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
resp, err := client.Get(url)
|
||||
if err != nil {
|
||||
spin.Stop()
|
||||
return nil, err
|
||||
@@ -99,7 +92,7 @@ func CMS(url string, timeout time.Duration, logdir string) (*CMSResult, error) {
|
||||
spin.Stop()
|
||||
log.Info("No CMS detected")
|
||||
log.Complete(0, "detected")
|
||||
return nil, nil //nolint:nilnil // no CMS found is not an error
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func detectWordPress(url string, client *http.Client, bodyString string) bool {
|
||||
@@ -125,11 +118,7 @@ func detectWordPress(url string, client *http.Client, bodyString string) bool {
|
||||
}
|
||||
|
||||
for _, file := range wpFiles {
|
||||
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, url+file, http.NoBody)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
resp, err := client.Get(url + file)
|
||||
if err == nil {
|
||||
found := resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusFound
|
||||
resp.Body.Close()
|
||||
|
||||
+10
-23
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -14,10 +14,10 @@ package scan
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -26,13 +26,11 @@ import (
|
||||
"github.com/dropalldatabases/sif/internal/output"
|
||||
)
|
||||
|
||||
// directoryURL is a var so integration tests can repoint it at a fixture.
|
||||
var directoryURL = "https://raw.githubusercontent.com/dropalldatabases/sif-runtime/main/dirlist/"
|
||||
|
||||
const (
|
||||
smallFile = "directory-list-2.3-small.txt"
|
||||
mediumFile = "directory-list-2.3-medium.txt"
|
||||
bigFile = "directory-list-2.3-big.txt"
|
||||
directoryURL = "https://raw.githubusercontent.com/dropalldatabases/sif-runtime/main/dirlist/"
|
||||
smallFile = "directory-list-2.3-small.txt"
|
||||
mediumFile = "directory-list-2.3-medium.txt"
|
||||
bigFile = "directory-list-2.3-big.txt"
|
||||
)
|
||||
|
||||
type DirectoryResult struct {
|
||||
@@ -45,7 +43,7 @@ func Dirlist(size string, url string, timeout time.Duration, threads int, logdir
|
||||
log := output.Module("DIRLIST")
|
||||
log.Start()
|
||||
|
||||
sanitizedURL := stripScheme(url)
|
||||
sanitizedURL := strings.Split(url, "://")[1]
|
||||
|
||||
if logdir != "" {
|
||||
if err := logger.WriteHeader(sanitizedURL, logdir, size+" directory fuzzing"); err != nil {
|
||||
@@ -64,12 +62,7 @@ func Dirlist(size string, url string, timeout time.Duration, threads int, logdir
|
||||
list = directoryURL + bigFile
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, list, http.NoBody)
|
||||
if err != nil {
|
||||
log.Error("Error creating directory list request: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
resp, err := http.Get(list)
|
||||
if err != nil {
|
||||
log.Error("Error downloading directory list: %s", err)
|
||||
return nil, err
|
||||
@@ -106,12 +99,7 @@ func Dirlist(size string, url string, timeout time.Duration, threads int, logdir
|
||||
progress.Increment(directory)
|
||||
|
||||
charmlog.Debugf("%s", directory)
|
||||
dirReq, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, url+"/"+directory, http.NoBody)
|
||||
if err != nil {
|
||||
charmlog.Debugf("Error creating request for %s: %s", directory, err)
|
||||
continue
|
||||
}
|
||||
resp, err := client.Do(dirReq)
|
||||
resp, err := client.Get(url + "/" + directory)
|
||||
if err != nil {
|
||||
charmlog.Debugf("Error %s: %s", directory, err)
|
||||
continue
|
||||
@@ -123,7 +111,7 @@ func Dirlist(size string, url string, timeout time.Duration, threads int, logdir
|
||||
progress.Resume()
|
||||
|
||||
if logdir != "" {
|
||||
_ = logger.Write(sanitizedURL, logdir, fmt.Sprintf("%s [%s]\n", strconv.Itoa(resp.StatusCode), directory))
|
||||
logger.Write(sanitizedURL, logdir, fmt.Sprintf("%s [%s]\n", strconv.Itoa(resp.StatusCode), directory))
|
||||
}
|
||||
|
||||
result := DirectoryResult{
|
||||
@@ -134,7 +122,6 @@ func Dirlist(size string, url string, timeout time.Duration, threads int, logdir
|
||||
results = append(results, result)
|
||||
mu.Unlock()
|
||||
}
|
||||
resp.Body.Close()
|
||||
}
|
||||
}(thread)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -14,9 +14,9 @@ package scan
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -25,10 +25,8 @@ import (
|
||||
"github.com/dropalldatabases/sif/internal/output"
|
||||
)
|
||||
|
||||
// dnsURL is a var so integration tests can repoint it at a fixture.
|
||||
var dnsURL = "https://raw.githubusercontent.com/dropalldatabases/sif-runtime/main/dnslist/"
|
||||
|
||||
const (
|
||||
dnsURL = "https://raw.githubusercontent.com/dropalldatabases/sif-runtime/main/dnslist/"
|
||||
dnsSmallFile = "subdomains-100.txt"
|
||||
dnsMediumFile = "subdomains-1000.txt"
|
||||
dnsBigFile = "subdomains-10000.txt"
|
||||
@@ -49,12 +47,7 @@ func Dnslist(size string, url string, timeout time.Duration, threads int, logdir
|
||||
list = dnsURL + dnsBigFile
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, list, http.NoBody)
|
||||
if err != nil {
|
||||
log.Error("Error creating request: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
resp, err := http.Get(list)
|
||||
if err != nil {
|
||||
log.Error("Error downloading DNS list: %s", err)
|
||||
return nil, err
|
||||
@@ -68,7 +61,7 @@ func Dnslist(size string, url string, timeout time.Duration, threads int, logdir
|
||||
dns = append(dns, scanner.Text())
|
||||
}
|
||||
|
||||
sanitizedURL := stripScheme(url)
|
||||
sanitizedURL := strings.Split(url, "://")[1]
|
||||
|
||||
if logdir != "" {
|
||||
if err := logger.WriteHeader(sanitizedURL, logdir, size+" subdomain fuzzing"); err != nil {
|
||||
@@ -102,19 +95,13 @@ func Dnslist(size string, url string, timeout time.Duration, threads int, logdir
|
||||
charmlog.Debugf("Looking up: %s", domain)
|
||||
|
||||
// Check HTTP
|
||||
httpReq, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, "http://"+domain+"."+sanitizedURL, http.NoBody)
|
||||
if err != nil {
|
||||
charmlog.Debugf("Error %s: %s", domain, err)
|
||||
continue
|
||||
}
|
||||
resp, err := client.Do(httpReq)
|
||||
resp, err := client.Get("http://" + domain + "." + sanitizedURL)
|
||||
if err != nil {
|
||||
charmlog.Debugf("Error %s: %s", domain, err)
|
||||
} else {
|
||||
mu.Lock()
|
||||
urls = append(urls, resp.Request.URL.String())
|
||||
mu.Unlock()
|
||||
resp.Body.Close()
|
||||
|
||||
progress.Pause()
|
||||
log.Success("found: %s.%s [http]", output.Highlight.Render(domain), sanitizedURL)
|
||||
@@ -126,26 +113,20 @@ func Dnslist(size string, url string, timeout time.Duration, threads int, logdir
|
||||
}
|
||||
|
||||
// Check HTTPS
|
||||
httpsReq, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, "https://"+domain+"."+sanitizedURL, http.NoBody)
|
||||
if err != nil {
|
||||
charmlog.Debugf("Error %s: %s", domain, err)
|
||||
continue
|
||||
}
|
||||
resp, err = client.Do(httpsReq)
|
||||
resp, err = client.Get("https://" + domain + "." + sanitizedURL)
|
||||
if err != nil {
|
||||
charmlog.Debugf("Error %s: %s", domain, err)
|
||||
} else {
|
||||
mu.Lock()
|
||||
urls = append(urls, resp.Request.URL.String())
|
||||
mu.Unlock()
|
||||
resp.Body.Close()
|
||||
|
||||
progress.Pause()
|
||||
log.Success("found: %s.%s [https]", output.Highlight.Render(domain), sanitizedURL)
|
||||
progress.Resume()
|
||||
|
||||
if logdir != "" {
|
||||
_ = logger.Write(sanitizedURL, logdir, fmt.Sprintf("[https] %s.%s\n", domain, sanitizedURL))
|
||||
logger.Write(sanitizedURL, logdir, fmt.Sprintf("[https] %s.%s\n", domain, sanitizedURL))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-16
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -17,10 +17,10 @@ package scan
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -59,7 +59,7 @@ func Dork(url string, timeout time.Duration, threads int, logdir string) ([]Dork
|
||||
spin := output.NewSpinner("Running Google dorks")
|
||||
spin.Start()
|
||||
|
||||
sanitizedURL := stripScheme(url)
|
||||
sanitizedURL := strings.Split(url, "://")[1]
|
||||
|
||||
if logdir != "" {
|
||||
if err := logger.WriteHeader(sanitizedURL, logdir, "URL dorking"); err != nil {
|
||||
@@ -69,14 +69,7 @@ func Dork(url string, timeout time.Duration, threads int, logdir string) ([]Dork
|
||||
}
|
||||
}
|
||||
|
||||
ctx := context.TODO()
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, dorkURL+dorkFile, http.NoBody)
|
||||
if err != nil {
|
||||
spin.Stop()
|
||||
output.Error("Error creating dork list request: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
resp, err := http.Get(dorkURL + dorkFile)
|
||||
if err != nil {
|
||||
spin.Stop()
|
||||
output.Error("Error downloading dork list: %s", err)
|
||||
@@ -92,7 +85,6 @@ func Dork(url string, timeout time.Duration, threads int, logdir string) ([]Dork
|
||||
|
||||
// util.InitProgressBar()
|
||||
var wg sync.WaitGroup
|
||||
var mu sync.Mutex
|
||||
wg.Add(threads)
|
||||
|
||||
dorkResults := []DorkResult{}
|
||||
@@ -106,7 +98,7 @@ func Dork(url string, timeout time.Duration, threads int, logdir string) ([]Dork
|
||||
continue
|
||||
}
|
||||
|
||||
results, err := googlesearch.Search(context.TODO(), fmt.Sprintf("%s %s", dork, sanitizedURL))
|
||||
results, err := googlesearch.Search(nil, fmt.Sprintf("%s %s", dork, sanitizedURL))
|
||||
if err != nil {
|
||||
log.Debugf("error searching for dork %s: %v", dork, err)
|
||||
continue
|
||||
@@ -116,7 +108,7 @@ func Dork(url string, timeout time.Duration, threads int, logdir string) ([]Dork
|
||||
output.Success("%s dork results found for dork %s", output.Status.Render(strconv.Itoa(len(results))), output.Highlight.Render(dork))
|
||||
spin.Start()
|
||||
if logdir != "" {
|
||||
_ = logger.Write(sanitizedURL, logdir, strconv.Itoa(len(results))+" dork results found for dork ["+dork+"]\n")
|
||||
logger.Write(sanitizedURL, logdir, strconv.Itoa(len(results))+" dork results found for dork ["+dork+"]\n")
|
||||
}
|
||||
|
||||
result := DorkResult{
|
||||
@@ -124,9 +116,7 @@ func Dork(url string, timeout time.Duration, threads int, logdir string) ([]Dork
|
||||
Count: len(results),
|
||||
}
|
||||
|
||||
mu.Lock()
|
||||
dorkResults = append(dorkResults, result)
|
||||
mu.Unlock()
|
||||
}
|
||||
}
|
||||
}(thread)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
: :
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
*/
|
||||
|
||||
package frameworks
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestVersionAffected(t *testing.T) {
|
||||
tests := []struct {
|
||||
version string
|
||||
affected string
|
||||
want bool
|
||||
}{
|
||||
{"4.2", "4.2", true},
|
||||
{"4.2.1", "4.2", true},
|
||||
{"4.2.13", "4.2", true},
|
||||
{"4.20", "4.2", false}, // the boundary bug: 4.20 is not a 4.2.x release
|
||||
{"4.20.0", "4.2", false},
|
||||
{"5.0", "4.2", false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
if got := versionAffected(tt.version, tt.affected); got != tt.want {
|
||||
t.Errorf("versionAffected(%q, %q) = %v, want %v", tt.version, tt.affected, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -13,11 +13,9 @@
|
||||
package frameworks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -49,12 +47,7 @@ func DetectFramework(url string, timeout time.Duration, logdir string) (*Framewo
|
||||
|
||||
client := &http.Client{Timeout: timeout}
|
||||
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, url, http.NoBody)
|
||||
if err != nil {
|
||||
spin.Stop()
|
||||
return nil, err
|
||||
}
|
||||
resp, err := client.Do(req) //nolint:bodyclose // closed via defer below
|
||||
resp, err := client.Get(url)
|
||||
if err != nil {
|
||||
spin.Stop()
|
||||
return nil, err
|
||||
@@ -73,7 +66,7 @@ func DetectFramework(url string, timeout time.Duration, logdir string) (*Framewo
|
||||
if len(detectors) == 0 {
|
||||
spin.Stop()
|
||||
log.Warn("No framework detectors registered")
|
||||
return nil, nil //nolint:nilnil // no detectors registered is not an error
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Run all detectors concurrently
|
||||
@@ -100,11 +93,9 @@ func DetectFramework(url string, timeout time.Duration, logdir string) (*Framewo
|
||||
}()
|
||||
|
||||
// Find the best match
|
||||
// results arrive in goroutine-completion order; tie-break on name so the
|
||||
// winner is deterministic when two detectors land on the same confidence.
|
||||
var best detectionResult
|
||||
for r := range results {
|
||||
if r.confidence > best.confidence || (r.confidence == best.confidence && r.name < best.name) {
|
||||
if r.confidence > best.confidence {
|
||||
best = r
|
||||
}
|
||||
}
|
||||
@@ -114,7 +105,7 @@ func DetectFramework(url string, timeout time.Duration, logdir string) (*Framewo
|
||||
if best.confidence <= detectionThreshold {
|
||||
log.Info("No framework detected with sufficient confidence")
|
||||
log.Complete(0, "detected")
|
||||
return nil, nil //nolint:nilnil // no framework detected is not an error
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Get version match details
|
||||
@@ -133,7 +124,7 @@ func DetectFramework(url string, timeout time.Duration, logdir string) (*Framewo
|
||||
logEntry += fmt.Sprintf(" CVEs: %v\n", cves)
|
||||
logEntry += fmt.Sprintf(" Recommendations: %v\n", suggestions)
|
||||
}
|
||||
_ = logger.Write(url, logdir, logEntry)
|
||||
logger.Write(url, logdir, logEntry)
|
||||
}
|
||||
|
||||
log.Success("Detected %s framework (version: %s, confidence: %.2f)",
|
||||
@@ -172,7 +163,7 @@ func getVulnerabilities(framework, version string) ([]string, []string) {
|
||||
|
||||
for _, entry := range entries {
|
||||
for _, affectedVer := range entry.AffectedVersions {
|
||||
if versionAffected(version, affectedVer) {
|
||||
if version == affectedVer || hasPrefix(version, affectedVer) {
|
||||
cves = append(cves, fmt.Sprintf("%s (%s)", entry.CVE, entry.Severity))
|
||||
for _, rec := range entry.Recommendations {
|
||||
if !seenRecs[rec] {
|
||||
@@ -188,9 +179,7 @@ func getVulnerabilities(framework, version string) ([]string, []string) {
|
||||
return cves, recommendations
|
||||
}
|
||||
|
||||
// versionAffected reports whether version falls under an affected-version
|
||||
// entry. the entry is a version prefix, matched only on dotted boundaries, so
|
||||
// "4.2" covers 4.2 and 4.2.1 but not 4.20.
|
||||
func versionAffected(version, affected string) bool {
|
||||
return version == affected || strings.HasPrefix(version, affected+".")
|
||||
// hasPrefix is a simple prefix check without importing strings.
|
||||
func hasPrefix(s, prefix string) bool {
|
||||
return len(s) >= len(prefix) && s[:len(prefix)] == prefix
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -13,7 +13,7 @@
|
||||
/*
|
||||
|
||||
BSD 3-Clause License
|
||||
(c) 2022-2026 vmfunc, xyzeva & contributors
|
||||
(c) 2022-2025 vmfunc, xyzeva & contributors
|
||||
|
||||
*/
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -13,7 +13,7 @@
|
||||
/*
|
||||
|
||||
BSD 3-Clause License
|
||||
(c) 2022-2026 vmfunc, xyzeva & contributors
|
||||
(c) 2022-2025 vmfunc, xyzeva & contributors
|
||||
|
||||
*/
|
||||
|
||||
@@ -47,11 +47,9 @@ func init() {
|
||||
fw.Register(&codeigniterDetector{})
|
||||
}
|
||||
|
||||
// sigmoidConfidence maps the matched-weight fraction to a 0-1 confidence,
|
||||
// centered at 0.3 so a single weak signature match no longer clears the 0.5
|
||||
// detection threshold (it used to: sigmoid(0) was 0.5, so any match "detected").
|
||||
// sigmoidConfidence converts a weighted score to a 0-1 confidence value.
|
||||
func sigmoidConfidence(score float32) float32 {
|
||||
return float32(1.0 / (1.0 + math.Exp(-(float64(score)-0.3)*10.0)))
|
||||
return float32(1.0 / (1.0 + math.Exp(-float64(score)*6.0)))
|
||||
}
|
||||
|
||||
// laravelDetector detects Laravel framework.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -13,7 +13,7 @@
|
||||
/*
|
||||
|
||||
BSD 3-Clause License
|
||||
(c) 2022-2026 vmfunc, xyzeva & contributors
|
||||
(c) 2022-2025 vmfunc, xyzeva & contributors
|
||||
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
: :
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
*/
|
||||
|
||||
package detectors
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestSigmoidConfidence(t *testing.T) {
|
||||
// a weak match (small matched-weight fraction) must stay below the 0.5
|
||||
// detection threshold; a strong match must clear it. the old curve put any
|
||||
// match above 0.5, which is what false-detected magento on a plain page.
|
||||
if c := sigmoidConfidence(0); c >= 0.5 {
|
||||
t.Errorf("no match conf = %.3f, want < 0.5", c)
|
||||
}
|
||||
if c := sigmoidConfidence(0.2); c >= 0.5 {
|
||||
t.Errorf("weak match conf = %.3f, want < 0.5", c)
|
||||
}
|
||||
if c := sigmoidConfidence(0.5); c <= 0.5 {
|
||||
t.Errorf("strong match conf = %.3f, want > 0.5", c)
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -13,7 +13,7 @@
|
||||
/*
|
||||
|
||||
BSD 3-Clause License
|
||||
(c) 2022-2026 vmfunc, xyzeva & contributors
|
||||
(c) 2022-2025 vmfunc, xyzeva & contributors
|
||||
|
||||
*/
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -13,7 +13,7 @@
|
||||
/*
|
||||
|
||||
BSD 3-Clause License
|
||||
(c) 2022-2026 vmfunc, xyzeva & contributors
|
||||
(c) 2022-2025 vmfunc, xyzeva & contributors
|
||||
|
||||
*/
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -13,7 +13,7 @@
|
||||
/*
|
||||
|
||||
BSD 3-Clause License
|
||||
(c) 2022-2026 vmfunc, xyzeva & contributors
|
||||
(c) 2022-2025 vmfunc, xyzeva & contributors
|
||||
|
||||
*/
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -202,7 +202,7 @@ func ExtractVersionOptimized(body string, framework string) VersionMatch {
|
||||
|
||||
// isValidVersionString checks if a version string looks like a valid semver
|
||||
func isValidVersionString(v string) bool {
|
||||
if v == "" || len(v) > 20 {
|
||||
if len(v) == 0 || len(v) > 20 {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
|
||||
+8
-25
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -14,7 +14,6 @@ package scan
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -26,10 +25,10 @@ import (
|
||||
"github.com/dropalldatabases/sif/internal/output"
|
||||
)
|
||||
|
||||
// gitURL is a var so integration tests can repoint it at a fixture.
|
||||
var gitURL = "https://raw.githubusercontent.com/dropalldatabases/sif-runtime/main/git/"
|
||||
|
||||
const gitFile = "git.txt"
|
||||
const (
|
||||
gitURL = "https://raw.githubusercontent.com/dropalldatabases/sif-runtime/main/git/"
|
||||
gitFile = "git.txt"
|
||||
)
|
||||
|
||||
func Git(url string, timeout time.Duration, threads int, logdir string) ([]string, error) {
|
||||
log := output.Module("GIT")
|
||||
@@ -38,7 +37,7 @@ func Git(url string, timeout time.Duration, threads int, logdir string) ([]strin
|
||||
spin := output.NewSpinner("Scanning for exposed git repositories")
|
||||
spin.Start()
|
||||
|
||||
sanitizedURL := stripScheme(url)
|
||||
sanitizedURL := strings.Split(url, "://")[1]
|
||||
|
||||
if logdir != "" {
|
||||
if err := logger.WriteHeader(sanitizedURL, logdir, "git directory fuzzing"); err != nil {
|
||||
@@ -48,13 +47,7 @@ func Git(url string, timeout time.Duration, threads int, logdir string) ([]strin
|
||||
}
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, gitURL+gitFile, http.NoBody)
|
||||
if err != nil {
|
||||
spin.Stop()
|
||||
log.Error("Error creating git list request: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
resp, err := http.Get(gitURL + gitFile)
|
||||
if err != nil {
|
||||
spin.Stop()
|
||||
log.Error("Error downloading git list: %s", err)
|
||||
@@ -74,7 +67,6 @@ func Git(url string, timeout time.Duration, threads int, logdir string) ([]strin
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
var mu sync.Mutex
|
||||
wg.Add(threads)
|
||||
|
||||
foundUrls := []string{}
|
||||
@@ -88,15 +80,9 @@ func Git(url string, timeout time.Duration, threads int, logdir string) ([]strin
|
||||
}
|
||||
|
||||
charmlog.Debugf("%s", repourl)
|
||||
gitReq, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, url+"/"+repourl, http.NoBody)
|
||||
if err != nil {
|
||||
charmlog.Debugf("Error creating request for %s: %s", repourl, err)
|
||||
continue
|
||||
}
|
||||
resp, err := client.Do(gitReq)
|
||||
resp, err := client.Get(url + "/" + repourl)
|
||||
if err != nil {
|
||||
charmlog.Debugf("Error %s: %s", repourl, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if resp.StatusCode == 200 && !strings.HasPrefix(resp.Header.Get("Content-Type"), "text/html") {
|
||||
@@ -107,11 +93,8 @@ func Git(url string, timeout time.Duration, threads int, logdir string) ([]strin
|
||||
logger.Write(sanitizedURL, logdir, strconv.Itoa(resp.StatusCode)+" git found at ["+repourl+"]\n")
|
||||
}
|
||||
|
||||
mu.Lock()
|
||||
foundUrls = append(foundUrls, resp.Request.URL.String())
|
||||
mu.Unlock()
|
||||
}
|
||||
resp.Body.Close()
|
||||
}
|
||||
}(thread)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -13,8 +13,8 @@
|
||||
package scan
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/dropalldatabases/sif/internal/logger"
|
||||
@@ -30,7 +30,7 @@ func Headers(url string, timeout time.Duration, logdir string) ([]HeaderResult,
|
||||
log := output.Module("HEADERS")
|
||||
log.Start()
|
||||
|
||||
sanitizedURL := stripScheme(url)
|
||||
sanitizedURL := strings.Split(url, "://")[1]
|
||||
|
||||
if logdir != "" {
|
||||
if err := logger.WriteHeader(sanitizedURL, logdir, "HTTP Header Analysis"); err != nil {
|
||||
@@ -43,11 +43,7 @@ func Headers(url string, timeout time.Duration, logdir string) ([]HeaderResult,
|
||||
Timeout: timeout,
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, url, http.NoBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
resp, err := client.Get(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,219 +0,0 @@
|
||||
//go:build integration
|
||||
|
||||
/*
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
: :
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
*/
|
||||
|
||||
// These tests run the real scanners against a local server standing in for a
|
||||
// deliberately-vulnerable app, asserting the findings each one should produce.
|
||||
// They're behind the `integration` build tag so the default `go test` stays
|
||||
// network-free; run with `go test -tags=integration ./internal/scan/...`.
|
||||
package scan
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// newVulnApp serves the planted artifacts each scanner is meant to find, plus
|
||||
// the wordlists the remote-list scanners fetch.
|
||||
func newVulnApp() *httptest.Server {
|
||||
mux := http.NewServeMux()
|
||||
|
||||
// wordlists the remote-list scanners download
|
||||
mux.HandleFunc("/git.txt", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte(".git/HEAD\n.git/config\n"))
|
||||
})
|
||||
mux.HandleFunc("/directory-list-2.3-small.txt", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("admin\nlogin\nnope\n"))
|
||||
})
|
||||
|
||||
// an exposed git repo: HEAD is a real find, config is html so it's excluded
|
||||
mux.HandleFunc("/.git/HEAD", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/octet-stream")
|
||||
w.Write([]byte("ref: refs/heads/main\n"))
|
||||
})
|
||||
mux.HandleFunc("/.git/config", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
w.Write([]byte("<html>nope</html>"))
|
||||
})
|
||||
|
||||
// live directories for dirlist
|
||||
mux.HandleFunc("/admin", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })
|
||||
mux.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })
|
||||
|
||||
// an exposed db admin panel for sql recon
|
||||
mux.HandleFunc("/phpmyadmin/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("<title>phpMyAdmin</title>"))
|
||||
})
|
||||
|
||||
// homepage doubles as the cms fingerprint and the lfi sink
|
||||
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
if strings.Contains(r.URL.RawQuery, "passwd") || strings.Contains(r.URL.RawQuery, "etc") {
|
||||
w.Write([]byte("root:x:0:0:root:/root:/bin/bash\n"))
|
||||
return
|
||||
}
|
||||
w.Header().Set("X-Powered-By", "PHP/8.1.0")
|
||||
w.Write([]byte(`<html><head><link href="/wp-content/themes/x/style.css"></head><body>hi</body></html>`))
|
||||
})
|
||||
|
||||
return httptest.NewServer(mux)
|
||||
}
|
||||
|
||||
func TestIntegrationGit(t *testing.T) {
|
||||
srv := newVulnApp()
|
||||
defer srv.Close()
|
||||
orig := gitURL
|
||||
gitURL = srv.URL + "/"
|
||||
defer func() { gitURL = orig }()
|
||||
|
||||
found, err := Git(srv.URL, 5*time.Second, 2, "")
|
||||
if err != nil {
|
||||
t.Fatalf("Git: %v", err)
|
||||
}
|
||||
if len(found) != 1 {
|
||||
t.Fatalf("expected 1 git find (HEAD, not the html config), got %d: %v", len(found), found)
|
||||
}
|
||||
if !strings.HasSuffix(found[0], ".git/HEAD") {
|
||||
t.Errorf("expected .git/HEAD, got %s", found[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntegrationDirlist(t *testing.T) {
|
||||
srv := newVulnApp()
|
||||
defer srv.Close()
|
||||
orig := directoryURL
|
||||
directoryURL = srv.URL + "/"
|
||||
defer func() { directoryURL = orig }()
|
||||
|
||||
results, err := Dirlist("small", srv.URL, 5*time.Second, 3, "")
|
||||
if err != nil {
|
||||
t.Fatalf("Dirlist: %v", err)
|
||||
}
|
||||
|
||||
got := map[string]bool{}
|
||||
for _, r := range results {
|
||||
got[r.Url] = true
|
||||
}
|
||||
if !hasSuffixIn(got, "/admin") || !hasSuffixIn(got, "/login") {
|
||||
t.Errorf("expected admin and login to be found, got %v", results)
|
||||
}
|
||||
if hasSuffixIn(got, "/nope") {
|
||||
t.Errorf("404 path nope should not be reported, got %v", results)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntegrationCMS(t *testing.T) {
|
||||
srv := newVulnApp()
|
||||
defer srv.Close()
|
||||
|
||||
result, err := CMS(srv.URL, 5*time.Second, "")
|
||||
if err != nil {
|
||||
t.Fatalf("CMS: %v", err)
|
||||
}
|
||||
if result == nil || result.Name != "WordPress" {
|
||||
t.Errorf("expected WordPress, got %+v", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntegrationHeaders(t *testing.T) {
|
||||
srv := newVulnApp()
|
||||
defer srv.Close()
|
||||
|
||||
results, err := Headers(srv.URL, 5*time.Second, "")
|
||||
if err != nil {
|
||||
t.Fatalf("Headers: %v", err)
|
||||
}
|
||||
if len(results) == 0 {
|
||||
t.Error("expected at least one header back")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntegrationSQL(t *testing.T) {
|
||||
srv := newVulnApp()
|
||||
defer srv.Close()
|
||||
|
||||
result, err := SQL(srv.URL, 5*time.Second, 5, "")
|
||||
if err != nil {
|
||||
t.Fatalf("SQL: %v", err)
|
||||
}
|
||||
if result == nil || len(result.AdminPanels) == 0 {
|
||||
t.Fatalf("expected an admin panel finding, got %+v", result)
|
||||
}
|
||||
if result.AdminPanels[0].Type != "phpMyAdmin" {
|
||||
t.Errorf("expected phpMyAdmin, got %s", result.AdminPanels[0].Type)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntegrationLFI(t *testing.T) {
|
||||
srv := newVulnApp()
|
||||
defer srv.Close()
|
||||
|
||||
result, err := LFI(srv.URL, 5*time.Second, 5, "")
|
||||
if err != nil {
|
||||
t.Fatalf("LFI: %v", err)
|
||||
}
|
||||
if result == nil || len(result.Vulnerabilities) == 0 {
|
||||
t.Errorf("expected an lfi finding from the passwd sink, got %+v", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntegrationPorts(t *testing.T) {
|
||||
// a real listener stands in for an open port; a tiny server hands its number
|
||||
// to Ports via the commonPorts wordlist.
|
||||
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatalf("listen: %v", err)
|
||||
}
|
||||
defer ln.Close()
|
||||
port := ln.Addr().(*net.TCPAddr).Port
|
||||
|
||||
list := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte(strconv.Itoa(port) + "\n"))
|
||||
}))
|
||||
defer list.Close()
|
||||
orig := commonPorts
|
||||
commonPorts = list.URL
|
||||
defer func() { commonPorts = orig }()
|
||||
|
||||
open, err := Ports(context.Background(), "common", "tcp://127.0.0.1", 2*time.Second, 1, "")
|
||||
if err != nil {
|
||||
t.Fatalf("Ports: %v", err)
|
||||
}
|
||||
found := false
|
||||
for _, p := range open {
|
||||
if p == strconv.Itoa(port) {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Errorf("expected open port %d in %v", port, open)
|
||||
}
|
||||
}
|
||||
|
||||
func hasSuffixIn(set map[string]bool, suffix string) bool {
|
||||
for k := range set {
|
||||
if strings.HasSuffix(k, suffix) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -24,7 +24,6 @@ package frameworks
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
@@ -42,13 +41,7 @@ func GetPagesRouterScripts(scriptUrl string) ([]string, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, scriptUrl, http.NoBody)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
resp, err := http.Get(scriptUrl)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return nil, err
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -14,7 +14,6 @@ package js
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"slices"
|
||||
@@ -48,12 +47,7 @@ func JavascriptScan(url string, timeout time.Duration, threads int, logdir strin
|
||||
spin.Stop()
|
||||
return nil, err
|
||||
}
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, url, http.NoBody)
|
||||
if err != nil {
|
||||
spin.Stop()
|
||||
return nil, err
|
||||
}
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
spin.Stop()
|
||||
return nil, err
|
||||
@@ -115,12 +109,7 @@ func JavascriptScan(url string, timeout time.Duration, threads int, logdir strin
|
||||
supabaseResults := make([]supabaseScanResult, 0, len(scripts))
|
||||
for _, script := range scripts {
|
||||
charmlog.Debugf("Scanning %s", script)
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, script, http.NoBody)
|
||||
if err != nil {
|
||||
charmlog.Warnf("Failed to create request: %s", err)
|
||||
continue
|
||||
}
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
resp, err := http.Get(script)
|
||||
if err != nil {
|
||||
charmlog.Warnf("Failed to fetch script: %s", err)
|
||||
continue
|
||||
@@ -135,7 +124,7 @@ func JavascriptScan(url string, timeout time.Duration, threads int, logdir strin
|
||||
content := string(bodyBytes)
|
||||
|
||||
charmlog.Debugf("Running supabase scanner on %s", script)
|
||||
scriptSupabaseResults, err := ScanSupabase(content, script, timeout)
|
||||
scriptSupabaseResults, err := ScanSupabase(content, script)
|
||||
|
||||
if err != nil {
|
||||
charmlog.Errorf("Error while scanning supabase: %s", err)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -16,7 +16,6 @@ package js
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
@@ -70,8 +69,8 @@ type supabaseOpenAPIResponse struct {
|
||||
}
|
||||
|
||||
// getSupabaseArrayResponse fetches a Supabase endpoint that returns an array.
|
||||
func getSupabaseArrayResponse(projectId, path, apikey string, auth *string, timeout time.Duration) (*supabaseArrayResponse, error) {
|
||||
body, resp, err := doSupabaseRequest(projectId, path, apikey, auth, timeout) //nolint:bodyclose // closed in doSupabaseRequest
|
||||
func getSupabaseArrayResponse(projectId, path, apikey string, auth *string) (*supabaseArrayResponse, error) {
|
||||
body, resp, err := doSupabaseRequest(projectId, path, apikey, auth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -95,8 +94,8 @@ func getSupabaseArrayResponse(projectId, path, apikey string, auth *string, time
|
||||
}
|
||||
|
||||
// getSupabaseOpenAPI fetches the OpenAPI spec from Supabase.
|
||||
func getSupabaseOpenAPI(projectId, apikey string, auth *string, timeout time.Duration) (*supabaseOpenAPIResponse, error) {
|
||||
body, _, err := doSupabaseRequest(projectId, "/rest/v1/", apikey, auth, timeout) //nolint:bodyclose // closed in doSupabaseRequest
|
||||
func getSupabaseOpenAPI(projectId, apikey string, auth *string) (*supabaseOpenAPIResponse, error) {
|
||||
body, _, err := doSupabaseRequest(projectId, "/rest/v1/", apikey, auth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -109,10 +108,10 @@ func getSupabaseOpenAPI(projectId, apikey string, auth *string, timeout time.Dur
|
||||
}
|
||||
|
||||
// doSupabaseRequest performs a GET request to the Supabase API.
|
||||
func doSupabaseRequest(projectId, path, apikey string, auth *string, timeout time.Duration) ([]byte, *http.Response, error) {
|
||||
client := http.Client{Timeout: timeout}
|
||||
func doSupabaseRequest(projectId, path, apikey string, auth *string) ([]byte, *http.Response, error) {
|
||||
client := http.Client{}
|
||||
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, "https://"+projectId+".supabase.co"+path, http.NoBody)
|
||||
req, err := http.NewRequest("GET", "https://"+projectId+".supabase.co"+path, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -142,9 +141,9 @@ func doSupabaseRequest(projectId, path, apikey string, auth *string, timeout tim
|
||||
return body, resp, nil
|
||||
}
|
||||
|
||||
func ScanSupabase(jsContent string, jsUrl string, timeout time.Duration) ([]supabaseScanResult, error) {
|
||||
func ScanSupabase(jsContent string, jsUrl string) ([]supabaseScanResult, error) {
|
||||
supabaselog := log.NewWithOptions(os.Stderr, log.Options{
|
||||
Prefix: "JavaScript > Supabase",
|
||||
Prefix: "🚧 JavaScript > Supabase ⚡️",
|
||||
}).With("url", jsUrl)
|
||||
|
||||
var results = []supabaseScanResult{}
|
||||
@@ -171,7 +170,7 @@ func ScanSupabase(jsContent string, jsUrl string, timeout time.Duration) ([]supa
|
||||
|
||||
supabaselog.Debugf("JWT body: %s", decoded)
|
||||
var supabaseJwt *supabaseJwtBody
|
||||
err = json.Unmarshal(decoded, &supabaseJwt)
|
||||
err = json.Unmarshal([]byte(decoded), &supabaseJwt)
|
||||
if err != nil {
|
||||
supabaselog.Debugf("Failed to json parse JWT %s: %s", jwt, err)
|
||||
continue
|
||||
@@ -182,9 +181,9 @@ func ScanSupabase(jsContent string, jsUrl string, timeout time.Duration) ([]supa
|
||||
}
|
||||
|
||||
supabaselog.Infof("Found valid supabase project %s with role %s", *supabaseJwt.ProjectId, *supabaseJwt.Role)
|
||||
client := http.Client{Timeout: timeout}
|
||||
client := http.Client{}
|
||||
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodPost, "https://"+*supabaseJwt.ProjectId+".supabase.co/auth/v1/signup", bytes.NewBufferString(`{"email":"automated`+strconv.Itoa(int(time.Now().Unix()))+`@sif.sh","password":"automatedacct"}`))
|
||||
req, err := http.NewRequest("POST", "https://"+*supabaseJwt.ProjectId+".supabase.co/auth/v1/signup", bytes.NewBufferString(`{"email":"automated`+strconv.Itoa(int(time.Now().Unix()))+`@sif.sh","password":"automatedacct"}`))
|
||||
if err != nil {
|
||||
supabaselog.Errorf("Error while creating HTTP req for creating user: %s", err)
|
||||
continue
|
||||
@@ -219,7 +218,7 @@ func ScanSupabase(jsContent string, jsUrl string, timeout time.Duration) ([]supa
|
||||
|
||||
var collections = []supabaseCollection{}
|
||||
|
||||
openAPI, err := getSupabaseOpenAPI(*supabaseJwt.ProjectId, jwt, &auth, timeout)
|
||||
openAPI, err := getSupabaseOpenAPI(*supabaseJwt.ProjectId, jwt, &auth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -238,7 +237,7 @@ func ScanSupabase(jsContent string, jsUrl string, timeout time.Duration) ([]supa
|
||||
continue
|
||||
}
|
||||
|
||||
sampleResp, err := getSupabaseArrayResponse(*supabaseJwt.ProjectId, "/rest/v1"+path, jwt, &auth, timeout)
|
||||
sampleResp, err := getSupabaseArrayResponse(*supabaseJwt.ProjectId, "/rest/v1"+path, jwt, &auth)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
+5
-10
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -13,12 +13,12 @@
|
||||
package scan
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -118,7 +118,7 @@ func LFI(targetURL string, timeout time.Duration, threads int, logdir string) (*
|
||||
spin := output.NewSpinner("Scanning for LFI vulnerabilities")
|
||||
spin.Start()
|
||||
|
||||
sanitizedURL := stripScheme(targetURL)
|
||||
sanitizedURL := strings.Split(targetURL, "://")[1]
|
||||
|
||||
if logdir != "" {
|
||||
if err := logger.WriteHeader(sanitizedURL, logdir, "LFI reconnaissance"); err != nil {
|
||||
@@ -214,12 +214,7 @@ func LFI(targetURL string, timeout time.Duration, threads int, logdir string) (*
|
||||
parsedURL.Path,
|
||||
testParams.Encode())
|
||||
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, testURL, http.NoBody)
|
||||
if err != nil {
|
||||
charmlog.Debugf("Error creating request for %s: %v", testURL, err)
|
||||
continue
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
resp, err := client.Get(testURL)
|
||||
if err != nil {
|
||||
charmlog.Debugf("Error testing %s: %v", testURL, err)
|
||||
continue
|
||||
@@ -299,7 +294,7 @@ func LFI(targetURL string, timeout time.Duration, threads int, logdir string) (*
|
||||
} else {
|
||||
log.Info("No LFI vulnerabilities detected")
|
||||
log.Complete(0, "found")
|
||||
return nil, nil //nolint:nilnil // no LFI found is not an error
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return result, nil
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -15,6 +15,7 @@ package scan
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -36,7 +37,7 @@ func Nuclei(url string, timeout time.Duration, threads int, logdir string) ([]ou
|
||||
Prefix: "nuclei",
|
||||
}).With("url", url)
|
||||
|
||||
_ = templates.Install(nucleilog)
|
||||
templates.Install(nucleilog)
|
||||
pwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
spin.Stop()
|
||||
@@ -68,7 +69,7 @@ func Nuclei(url string, timeout time.Duration, threads int, logdir string) ([]ou
|
||||
}
|
||||
defer ne.Close()
|
||||
|
||||
sanitizedURL := stripScheme(url)
|
||||
sanitizedURL := strings.Split(url, "://")[1]
|
||||
ne.LoadTargets([]string{sanitizedURL}, false)
|
||||
|
||||
var results []output.ResultEvent
|
||||
|
||||
+8
-15
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -14,11 +14,11 @@ package scan
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -27,14 +27,13 @@ import (
|
||||
"github.com/dropalldatabases/sif/internal/output"
|
||||
)
|
||||
|
||||
// commonPorts is a var so integration tests can repoint it at a fixture.
|
||||
var commonPorts = "https://raw.githubusercontent.com/dropalldatabases/sif-runtime/main/ports/top-ports.txt"
|
||||
const commonPorts = "https://raw.githubusercontent.com/dropalldatabases/sif-runtime/main/ports/top-ports.txt"
|
||||
|
||||
func Ports(ctx context.Context, scope string, url string, timeout time.Duration, threads int, logdir string) ([]string, error) {
|
||||
func Ports(scope string, url string, timeout time.Duration, threads int, logdir string) ([]string, error) {
|
||||
log := output.Module("PORTS")
|
||||
log.Start()
|
||||
|
||||
sanitizedURL := stripScheme(url)
|
||||
sanitizedURL := strings.Split(url, "://")[1]
|
||||
if logdir != "" {
|
||||
if err := logger.WriteHeader(sanitizedURL, logdir, scope+" port scanning"); err != nil {
|
||||
log.Error("Error creating log file: %v", err)
|
||||
@@ -45,12 +44,7 @@ func Ports(ctx context.Context, scope string, url string, timeout time.Duration,
|
||||
var ports []int
|
||||
switch scope {
|
||||
case "common":
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, commonPorts, http.NoBody)
|
||||
if err != nil {
|
||||
log.Error("Error creating request: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
resp, err := http.Get(commonPorts)
|
||||
if err != nil {
|
||||
log.Error("Error downloading ports list: %s", err)
|
||||
return nil, err
|
||||
@@ -89,8 +83,7 @@ func Ports(ctx context.Context, scope string, url string, timeout time.Duration,
|
||||
progress.Increment(strconv.Itoa(port))
|
||||
|
||||
charmlog.Debugf("Looking up: %d", port)
|
||||
addr := fmt.Sprintf("%s:%d", sanitizedURL, port)
|
||||
tcp, err := (&net.Dialer{Timeout: timeout}).DialContext(ctx, "tcp", addr)
|
||||
tcp, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", sanitizedURL, port), timeout)
|
||||
if err != nil {
|
||||
charmlog.Debugf("Error %d: %v", port, err)
|
||||
} else {
|
||||
@@ -101,7 +94,7 @@ func Ports(ctx context.Context, scope string, url string, timeout time.Duration,
|
||||
mu.Lock()
|
||||
openPorts = append(openPorts, strconv.Itoa(port))
|
||||
mu.Unlock()
|
||||
_ = tcp.Close()
|
||||
tcp.Close()
|
||||
}
|
||||
}
|
||||
}(thread)
|
||||
|
||||
+6
-10
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -16,7 +16,6 @@ package scan
|
||||
// These provide better type safety and allow method implementations.
|
||||
type (
|
||||
HeaderResults []HeaderResult
|
||||
SecurityHeaderResults []SecurityHeaderResult
|
||||
DirectoryResults []DirectoryResult
|
||||
CloudStorageResults []CloudStorageResult
|
||||
DorkResults []DorkResult
|
||||
@@ -24,6 +23,7 @@ type (
|
||||
)
|
||||
|
||||
// ScanResult is the interface that all scan result types implement.
|
||||
// This enables type-safe handling of heterogeneous scan results.
|
||||
type ScanResult interface {
|
||||
// ResultType returns the unique identifier for this result type.
|
||||
ResultType() string
|
||||
@@ -31,16 +31,14 @@ type ScanResult interface {
|
||||
|
||||
// ResultType implementations for pointer result types.
|
||||
|
||||
func (r *ShodanResult) ResultType() string { return "shodan" }
|
||||
func (r *SQLResult) ResultType() string { return "sql" }
|
||||
func (r *LFIResult) ResultType() string { return "lfi" }
|
||||
func (r *CMSResult) ResultType() string { return "cms" }
|
||||
func (r *SecurityTrailsResult) ResultType() string { return "securitytrails" }
|
||||
func (r *ShodanResult) ResultType() string { return "shodan" }
|
||||
func (r *SQLResult) ResultType() string { return "sql" }
|
||||
func (r *LFIResult) ResultType() string { return "lfi" }
|
||||
func (r *CMSResult) ResultType() string { return "cms" }
|
||||
|
||||
// ResultType implementations for slice result types.
|
||||
|
||||
func (r HeaderResults) ResultType() string { return "headers" }
|
||||
func (r SecurityHeaderResults) ResultType() string { return "security_headers" }
|
||||
func (r DirectoryResults) ResultType() string { return "dirlist" }
|
||||
func (r CloudStorageResults) ResultType() string { return "cloudstorage" }
|
||||
func (r DorkResults) ResultType() string { return "dork" }
|
||||
@@ -52,9 +50,7 @@ var (
|
||||
_ ScanResult = (*SQLResult)(nil)
|
||||
_ ScanResult = (*LFIResult)(nil)
|
||||
_ ScanResult = (*CMSResult)(nil)
|
||||
_ ScanResult = (*SecurityTrailsResult)(nil)
|
||||
_ ScanResult = HeaderResults(nil)
|
||||
_ ScanResult = SecurityHeaderResults(nil)
|
||||
_ ScanResult = DirectoryResults(nil)
|
||||
_ ScanResult = CloudStorageResults(nil)
|
||||
_ ScanResult = DorkResults(nil)
|
||||
|
||||
+4
-24
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -19,7 +19,6 @@ package scan
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -31,22 +30,8 @@ import (
|
||||
"github.com/dropalldatabases/sif/internal/output"
|
||||
)
|
||||
|
||||
// stripScheme drops the scheme:// prefix from url, or returns it unchanged when
|
||||
// there's no scheme (so a bare host doesn't panic).
|
||||
func stripScheme(url string) string {
|
||||
if _, rest, ok := strings.Cut(url, "://"); ok {
|
||||
return rest
|
||||
}
|
||||
return url
|
||||
}
|
||||
|
||||
func fetchRobotsTXT(url string, client *http.Client) *http.Response {
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, url, http.NoBody)
|
||||
if err != nil {
|
||||
log.Debugf("Error creating request for robots.txt: %s", err)
|
||||
return nil
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
resp, err := client.Get(url)
|
||||
if err != nil {
|
||||
log.Debugf("Error fetching robots.txt: %s", err)
|
||||
return nil
|
||||
@@ -76,7 +61,7 @@ func fetchRobotsTXT(url string, client *http.Client) *http.Response {
|
||||
func Scan(url string, timeout time.Duration, threads int, logdir string) {
|
||||
output.ScanStart("base URL scanning")
|
||||
|
||||
sanitizedURL := stripScheme(url)
|
||||
sanitizedURL := strings.Split(url, "://")[1]
|
||||
|
||||
if logdir != "" {
|
||||
if err := logger.WriteHeader(sanitizedURL, logdir, "URL scanning"); err != nil {
|
||||
@@ -125,12 +110,7 @@ func Scan(url string, timeout time.Duration, threads int, logdir string) {
|
||||
|
||||
_, sanitizedRobot, _ := strings.Cut(robot, ": ")
|
||||
log.Debugf("%s", robot)
|
||||
robotReq, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, url+"/"+sanitizedRobot, http.NoBody)
|
||||
if err != nil {
|
||||
log.Debugf("Error creating request for %s: %s", sanitizedRobot, err)
|
||||
continue
|
||||
}
|
||||
resp, err := client.Do(robotReq)
|
||||
resp, err := client.Get(url + "/" + sanitizedRobot)
|
||||
if err != nil {
|
||||
log.Debugf("Error %s: %s", sanitizedRobot, err)
|
||||
continue
|
||||
|
||||
@@ -200,24 +200,3 @@ func TestHeaderResult(t *testing.T) {
|
||||
t.Errorf("expected value 'application/json', got '%s'", result.Value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStripScheme(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
url string
|
||||
want string
|
||||
}{
|
||||
{"https with path", "https://example.com/path", "example.com/path"},
|
||||
{"http", "http://example.com", "example.com"},
|
||||
{"no scheme stays put", "example.com", "example.com"},
|
||||
{"empty", "", ""},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := stripScheme(tt.url); got != tt.want {
|
||||
t.Errorf("stripScheme(%q) = %q, want %q", tt.url, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,162 +0,0 @@
|
||||
/*
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
: :
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
*/
|
||||
|
||||
package scan
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/dropalldatabases/sif/internal/logger"
|
||||
"github.com/dropalldatabases/sif/internal/output"
|
||||
)
|
||||
|
||||
type SecurityHeaderResult struct {
|
||||
Header string `json:"header"`
|
||||
Present bool `json:"present"`
|
||||
Value string `json:"value,omitempty"`
|
||||
Severity string `json:"severity"`
|
||||
Note string `json:"note"`
|
||||
}
|
||||
|
||||
type recommendedHeader struct {
|
||||
name string
|
||||
severity string
|
||||
}
|
||||
|
||||
var recommendedHeaders = []recommendedHeader{
|
||||
{"Strict-Transport-Security", "high"},
|
||||
{"Content-Security-Policy", "medium"},
|
||||
{"X-Frame-Options", "medium"},
|
||||
{"X-Content-Type-Options", "low"},
|
||||
{"Referrer-Policy", "low"},
|
||||
{"Permissions-Policy", "low"},
|
||||
{"Cross-Origin-Opener-Policy", "low"},
|
||||
}
|
||||
|
||||
// headers that leak server/framework details when present.
|
||||
var disclosureHeaders = []string{"Server", "X-Powered-By", "X-AspNet-Version", "X-AspNetMvc-Version"}
|
||||
|
||||
const hstsMinMaxAge = 31536000 // a year, in seconds
|
||||
|
||||
func SecurityHeaders(url string, timeout time.Duration, logdir string) (SecurityHeaderResults, error) {
|
||||
log := output.Module("SECHEADERS")
|
||||
log.Start()
|
||||
|
||||
sanitizedURL := stripScheme(url)
|
||||
|
||||
if logdir != "" {
|
||||
if err := logger.WriteHeader(sanitizedURL, logdir, "Security Header Analysis"); err != nil {
|
||||
log.Error("Error creating log file: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
client := &http.Client{
|
||||
Timeout: timeout,
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, url, http.NoBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
results := gradeSecurityHeaders(resp.Header, strings.HasPrefix(url, "https://"))
|
||||
|
||||
for _, r := range results {
|
||||
line := r.Header + " " + r.Note
|
||||
log.Warn("%s [%s]", line, r.Severity)
|
||||
if logdir != "" {
|
||||
_ = logger.Write(sanitizedURL, logdir, line+" ["+r.Severity+"]\n")
|
||||
}
|
||||
}
|
||||
|
||||
if len(results) == 0 {
|
||||
log.Success("all recommended security headers present")
|
||||
}
|
||||
|
||||
log.Complete(len(results), "issues")
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func gradeSecurityHeaders(header http.Header, https bool) SecurityHeaderResults {
|
||||
var results SecurityHeaderResults
|
||||
|
||||
for _, h := range recommendedHeaders {
|
||||
// hsts does nothing over plain http, so don't flag its absence there
|
||||
if h.name == "Strict-Transport-Security" && !https {
|
||||
continue
|
||||
}
|
||||
|
||||
value := header.Get(h.name)
|
||||
switch {
|
||||
case value == "":
|
||||
results = append(results, SecurityHeaderResult{
|
||||
Header: h.name,
|
||||
Severity: h.severity,
|
||||
Note: "missing",
|
||||
})
|
||||
case h.name == "Strict-Transport-Security" && hstsMaxAge(value) < hstsMinMaxAge:
|
||||
results = append(results, SecurityHeaderResult{
|
||||
Header: h.name,
|
||||
Present: true,
|
||||
Value: value,
|
||||
Severity: h.severity,
|
||||
Note: "max-age too short",
|
||||
})
|
||||
case h.name == "X-Content-Type-Options" && !strings.EqualFold(value, "nosniff"):
|
||||
results = append(results, SecurityHeaderResult{
|
||||
Header: h.name,
|
||||
Present: true,
|
||||
Value: value,
|
||||
Severity: "low",
|
||||
Note: "should be nosniff",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for _, name := range disclosureHeaders {
|
||||
if value := header.Get(name); value != "" {
|
||||
results = append(results, SecurityHeaderResult{
|
||||
Header: name,
|
||||
Present: true,
|
||||
Value: value,
|
||||
Severity: "low",
|
||||
Note: "discloses " + value,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
// hstsMaxAge returns the max-age seconds from an hsts value, or 0 if absent.
|
||||
func hstsMaxAge(value string) int {
|
||||
for _, part := range strings.Split(value, ";") {
|
||||
if age, ok := strings.CutPrefix(strings.ToLower(strings.TrimSpace(part)), "max-age="); ok {
|
||||
n, err := strconv.Atoi(strings.TrimSpace(age))
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return n
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
/*
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
: :
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
*/
|
||||
|
||||
package scan
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func buildHeader(kv map[string]string) http.Header {
|
||||
h := http.Header{}
|
||||
for k, v := range kv {
|
||||
h.Set(k, v)
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
func findFinding(results SecurityHeaderResults, name string) (SecurityHeaderResult, bool) {
|
||||
for _, r := range results {
|
||||
if r.Header == name {
|
||||
return r, true
|
||||
}
|
||||
}
|
||||
return SecurityHeaderResult{}, false
|
||||
}
|
||||
|
||||
func TestGradeSecurityHeaders_MissingOverHTTPS(t *testing.T) {
|
||||
results := gradeSecurityHeaders(http.Header{}, true)
|
||||
|
||||
for _, h := range recommendedHeaders {
|
||||
f, ok := findFinding(results, h.name)
|
||||
if !ok {
|
||||
t.Errorf("expected %s to be flagged", h.name)
|
||||
continue
|
||||
}
|
||||
if f.Present {
|
||||
t.Errorf("%s should not be marked present", h.name)
|
||||
}
|
||||
if f.Severity != h.severity {
|
||||
t.Errorf("%s severity = %q, want %q", h.name, f.Severity, h.severity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGradeSecurityHeaders_HSTSSkippedOverHTTP(t *testing.T) {
|
||||
results := gradeSecurityHeaders(http.Header{}, false)
|
||||
if _, ok := findFinding(results, "Strict-Transport-Security"); ok {
|
||||
t.Error("HSTS should only be graded for https targets")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGradeSecurityHeaders_AllPresent(t *testing.T) {
|
||||
h := buildHeader(map[string]string{
|
||||
"Strict-Transport-Security": "max-age=63072000; includeSubDomains",
|
||||
"Content-Security-Policy": "default-src 'self'",
|
||||
"X-Frame-Options": "DENY",
|
||||
"X-Content-Type-Options": "nosniff",
|
||||
"Referrer-Policy": "no-referrer",
|
||||
"Permissions-Policy": "geolocation=()",
|
||||
"Cross-Origin-Opener-Policy": "same-origin",
|
||||
})
|
||||
|
||||
if results := gradeSecurityHeaders(h, true); len(results) != 0 {
|
||||
t.Errorf("expected no findings, got %d: %+v", len(results), results)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGradeSecurityHeaders_ContentTypeNotNosniff(t *testing.T) {
|
||||
h := buildHeader(map[string]string{
|
||||
"Strict-Transport-Security": "max-age=63072000",
|
||||
"Content-Security-Policy": "default-src 'self'",
|
||||
"X-Frame-Options": "DENY",
|
||||
"X-Content-Type-Options": "sniff",
|
||||
"Referrer-Policy": "no-referrer",
|
||||
"Permissions-Policy": "geolocation=()",
|
||||
"Cross-Origin-Opener-Policy": "same-origin",
|
||||
})
|
||||
|
||||
f, ok := findFinding(gradeSecurityHeaders(h, true), "X-Content-Type-Options")
|
||||
if !ok {
|
||||
t.Fatal("expected X-Content-Type-Options to be flagged when not nosniff")
|
||||
}
|
||||
if !f.Present || f.Value != "sniff" {
|
||||
t.Errorf("finding = %+v, want present with value sniff", f)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGradeSecurityHeaders_WeakHSTS(t *testing.T) {
|
||||
// max-age=0 actively disables hsts, so a present header still has to be flagged
|
||||
h := buildHeader(map[string]string{"Strict-Transport-Security": "max-age=0"})
|
||||
|
||||
f, ok := findFinding(gradeSecurityHeaders(h, true), "Strict-Transport-Security")
|
||||
if !ok {
|
||||
t.Fatal("expected a short-lived hsts header to be flagged")
|
||||
}
|
||||
if !f.Present || f.Severity != "high" {
|
||||
t.Errorf("finding = %+v, want present high", f)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGradeSecurityHeaders_Disclosure(t *testing.T) {
|
||||
h := buildHeader(map[string]string{
|
||||
"Server": "Apache/2.4.1 (Ubuntu)",
|
||||
"X-Powered-By": "PHP/8.1.2",
|
||||
})
|
||||
|
||||
results := gradeSecurityHeaders(h, false)
|
||||
for _, name := range []string{"Server", "X-Powered-By"} {
|
||||
f, ok := findFinding(results, name)
|
||||
if !ok {
|
||||
t.Errorf("expected disclosure finding for %s", name)
|
||||
continue
|
||||
}
|
||||
if !f.Present || f.Severity != "low" {
|
||||
t.Errorf("%s finding = %+v, want present low", name, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSecurityHeaders_LiveResponse(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("X-Frame-Options", "SAMEORIGIN")
|
||||
w.Header().Set("Server", "nginx/1.25.3")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
results, err := SecurityHeaders(server.URL, 5*time.Second, "")
|
||||
if err != nil {
|
||||
t.Fatalf("SecurityHeaders returned error: %v", err)
|
||||
}
|
||||
|
||||
if _, ok := findFinding(results, "X-Frame-Options"); ok {
|
||||
t.Error("X-Frame-Options was set, should not be flagged")
|
||||
}
|
||||
if _, ok := findFinding(results, "Content-Security-Policy"); !ok {
|
||||
t.Error("expected missing Content-Security-Policy to be flagged")
|
||||
}
|
||||
if _, ok := findFinding(results, "Server"); !ok {
|
||||
t.Error("expected Server disclosure to be flagged")
|
||||
}
|
||||
}
|
||||
@@ -1,253 +0,0 @@
|
||||
/*
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
: :
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
*/
|
||||
|
||||
package scan
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/dropalldatabases/sif/internal/logger"
|
||||
"github.com/dropalldatabases/sif/internal/output"
|
||||
)
|
||||
|
||||
const securityTrailsBaseURL = "https://api.securitytrails.com/v1"
|
||||
|
||||
// SecurityTrailsResult holds discovered domains from SecurityTrails API
|
||||
type SecurityTrailsResult struct {
|
||||
Domain string `json:"domain"`
|
||||
Subdomains []string `json:"subdomains,omitempty"`
|
||||
AssociatedDomains []string `json:"associated_domains,omitempty"`
|
||||
}
|
||||
|
||||
// stSubdomainsResponse is the raw response from the subdomains endpoint -
|
||||
// returns prefix labels, not FQDNs
|
||||
type stSubdomainsResponse struct {
|
||||
Subdomains []string `json:"subdomains"`
|
||||
}
|
||||
|
||||
type stAssociatedResponse struct {
|
||||
Records []stAssociatedRecord `json:"records"`
|
||||
}
|
||||
|
||||
type stAssociatedRecord struct {
|
||||
Hostname string `json:"hostname"`
|
||||
}
|
||||
|
||||
// SecurityTrails queries the SecurityTrails API for subdomains and associated domains.
|
||||
// API key should be provided via the SECURITYTRAILS_API_KEY environment variable.
|
||||
func SecurityTrails(targetURL string, timeout time.Duration, logdir string) (*SecurityTrailsResult, error) {
|
||||
output.ScanStart("SecurityTrails lookup")
|
||||
|
||||
spin := output.NewSpinner("querying SecurityTrails API")
|
||||
spin.Start()
|
||||
|
||||
apiKey := os.Getenv("SECURITYTRAILS_API_KEY")
|
||||
if apiKey == "" {
|
||||
spin.Stop()
|
||||
output.Warn("SECURITYTRAILS_API_KEY environment variable not set, skipping SecurityTrails lookup")
|
||||
return nil, fmt.Errorf("SECURITYTRAILS_API_KEY environment variable not set")
|
||||
}
|
||||
|
||||
parsedURL, err := url.Parse(targetURL)
|
||||
if err != nil {
|
||||
spin.Stop()
|
||||
return nil, fmt.Errorf("failed to parse URL: %w", err)
|
||||
}
|
||||
hostname := parsedURL.Hostname()
|
||||
|
||||
client := &http.Client{Timeout: timeout}
|
||||
|
||||
result := &SecurityTrailsResult{
|
||||
Domain: hostname,
|
||||
}
|
||||
|
||||
// fetch subdomains
|
||||
spin.Update("fetching subdomains for " + hostname)
|
||||
subs, err := querySTSubdomains(client, hostname, apiKey)
|
||||
if err != nil {
|
||||
// non-fatal - still try associated domains
|
||||
output.Warn("SecurityTrails subdomains failed: %v", err)
|
||||
} else {
|
||||
result.Subdomains = subs
|
||||
}
|
||||
|
||||
// fetch associated domains
|
||||
spin.Update("fetching associated domains for " + hostname)
|
||||
assoc, err := querySTAssociated(client, hostname, apiKey)
|
||||
if err != nil {
|
||||
output.Warn("SecurityTrails associated domains failed: %v", err)
|
||||
} else {
|
||||
result.AssociatedDomains = assoc
|
||||
}
|
||||
|
||||
spin.Stop()
|
||||
|
||||
if logdir != "" {
|
||||
sanitizedURL := stripScheme(targetURL)
|
||||
if err := logger.WriteHeader(sanitizedURL, logdir, "SecurityTrails lookup"); err != nil {
|
||||
output.Error("error writing log header: %v", err)
|
||||
}
|
||||
logSecurityTrailsResults(sanitizedURL, logdir, result)
|
||||
}
|
||||
|
||||
printSecurityTrailsResults(result)
|
||||
|
||||
total := len(result.Subdomains) + len(result.AssociatedDomains)
|
||||
output.ScanComplete("SecurityTrails lookup", total, "domains discovered")
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// DiscoveredURLs returns all discovered domains as https:// URLs.
|
||||
// used by the orchestration layer for target expansion.
|
||||
func (r *SecurityTrailsResult) DiscoveredURLs() []string {
|
||||
seen := make(map[string]struct{})
|
||||
var urls []string
|
||||
|
||||
for _, sub := range r.Subdomains {
|
||||
fqdn := sub + "." + r.Domain
|
||||
if _, ok := seen[fqdn]; !ok {
|
||||
seen[fqdn] = struct{}{}
|
||||
urls = append(urls, "https://"+fqdn)
|
||||
}
|
||||
}
|
||||
|
||||
for _, assoc := range r.AssociatedDomains {
|
||||
if _, ok := seen[assoc]; !ok {
|
||||
seen[assoc] = struct{}{}
|
||||
urls = append(urls, "https://"+assoc)
|
||||
}
|
||||
}
|
||||
|
||||
return urls
|
||||
}
|
||||
|
||||
func querySTSubdomains(client *http.Client, hostname, apiKey string) ([]string, error) {
|
||||
reqURL := fmt.Sprintf("%s/domain/%s/subdomains", securityTrailsBaseURL, hostname)
|
||||
body, err := doSTRequest(client, reqURL, apiKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resp stSubdomainsResponse
|
||||
if err := json.Unmarshal(body, &resp); err != nil {
|
||||
return nil, fmt.Errorf("parse subdomains response: %w", err)
|
||||
}
|
||||
|
||||
return resp.Subdomains, nil
|
||||
}
|
||||
|
||||
func querySTAssociated(client *http.Client, hostname, apiKey string) ([]string, error) {
|
||||
reqURL := fmt.Sprintf("%s/domain/%s/associated", securityTrailsBaseURL, hostname)
|
||||
body, err := doSTRequest(client, reqURL, apiKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resp stAssociatedResponse
|
||||
if err := json.Unmarshal(body, &resp); err != nil {
|
||||
return nil, fmt.Errorf("parse associated response: %w", err)
|
||||
}
|
||||
|
||||
domains := make([]string, 0, len(resp.Records))
|
||||
for _, rec := range resp.Records {
|
||||
if rec.Hostname != "" {
|
||||
domains = append(domains, rec.Hostname)
|
||||
}
|
||||
}
|
||||
|
||||
return domains, nil
|
||||
}
|
||||
|
||||
// doSTRequest makes an authenticated GET to the SecurityTrails API
|
||||
func doSTRequest(client *http.Client, reqURL, apiKey string) ([]byte, error) {
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, reqURL, http.NoBody)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create request: %w", err)
|
||||
}
|
||||
req.Header.Set("APIKEY", apiKey)
|
||||
req.Header.Set("Accept", "application/json")
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("SecurityTrails request failed: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode == http.StatusForbidden || resp.StatusCode == http.StatusUnauthorized {
|
||||
return nil, fmt.Errorf("invalid SecurityTrails API key (status %d)", resp.StatusCode)
|
||||
}
|
||||
|
||||
if resp.StatusCode == http.StatusTooManyRequests {
|
||||
return nil, fmt.Errorf("SecurityTrails rate limit exceeded")
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
body, _ := io.ReadAll(io.LimitReader(resp.Body, 1024))
|
||||
return nil, fmt.Errorf("SecurityTrails API error (status %d): %s", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(io.LimitReader(resp.Body, 5*1024*1024))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read response: %w", err)
|
||||
}
|
||||
|
||||
return body, nil
|
||||
}
|
||||
|
||||
func printSecurityTrailsResults(result *SecurityTrailsResult) {
|
||||
output.Info("Domain: %s", output.Highlight.Render(result.Domain))
|
||||
|
||||
if len(result.Subdomains) > 0 {
|
||||
output.Info("Subdomains found: %d", len(result.Subdomains))
|
||||
for _, sub := range result.Subdomains {
|
||||
output.Success(" %s.%s", sub, result.Domain)
|
||||
}
|
||||
}
|
||||
|
||||
if len(result.AssociatedDomains) > 0 {
|
||||
output.Info("Associated domains found: %d", len(result.AssociatedDomains))
|
||||
for _, assoc := range result.AssociatedDomains {
|
||||
output.Success(" %s", assoc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func logSecurityTrailsResults(sanitizedURL, logdir string, result *SecurityTrailsResult) {
|
||||
var sb strings.Builder
|
||||
|
||||
sb.WriteString(fmt.Sprintf("Domain: %s\n", result.Domain))
|
||||
|
||||
if len(result.Subdomains) > 0 {
|
||||
sb.WriteString(fmt.Sprintf("\nSubdomains (%d):\n", len(result.Subdomains)))
|
||||
for _, sub := range result.Subdomains {
|
||||
sb.WriteString(fmt.Sprintf(" %s.%s\n", sub, result.Domain))
|
||||
}
|
||||
}
|
||||
|
||||
if len(result.AssociatedDomains) > 0 {
|
||||
sb.WriteString(fmt.Sprintf("\nAssociated Domains (%d):\n", len(result.AssociatedDomains)))
|
||||
for _, assoc := range result.AssociatedDomains {
|
||||
sb.WriteString(fmt.Sprintf(" %s\n", assoc))
|
||||
}
|
||||
}
|
||||
|
||||
logger.Write(sanitizedURL, logdir, sb.String())
|
||||
}
|
||||
@@ -1,208 +0,0 @@
|
||||
package scan
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestSecurityTrailsResult_DiscoveredURLs(t *testing.T) {
|
||||
result := &SecurityTrailsResult{
|
||||
Domain: "example.com",
|
||||
Subdomains: []string{"www", "api", "mail"},
|
||||
AssociatedDomains: []string{"example.org", "example.net"},
|
||||
}
|
||||
|
||||
urls := result.DiscoveredURLs()
|
||||
|
||||
if len(urls) != 5 {
|
||||
t.Errorf("expected 5 URLs, got %d: %v", len(urls), urls)
|
||||
}
|
||||
|
||||
expected := map[string]bool{
|
||||
"https://www.example.com": false,
|
||||
"https://api.example.com": false,
|
||||
"https://mail.example.com": false,
|
||||
"https://example.org": false,
|
||||
"https://example.net": false,
|
||||
}
|
||||
|
||||
for _, u := range urls {
|
||||
if _, ok := expected[u]; !ok {
|
||||
t.Errorf("unexpected URL: %s", u)
|
||||
}
|
||||
expected[u] = true
|
||||
}
|
||||
|
||||
for u, seen := range expected {
|
||||
if !seen {
|
||||
t.Errorf("missing expected URL: %s", u)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSecurityTrailsResult_DiscoveredURLs_Dedup(t *testing.T) {
|
||||
result := &SecurityTrailsResult{
|
||||
Domain: "example.com",
|
||||
Subdomains: []string{"www"},
|
||||
AssociatedDomains: []string{"www.example.com"},
|
||||
}
|
||||
|
||||
urls := result.DiscoveredURLs()
|
||||
if len(urls) != 1 {
|
||||
t.Errorf("expected 1 URL (deduped), got %d: %v", len(urls), urls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSecurityTrailsResult_DiscoveredURLs_Empty(t *testing.T) {
|
||||
result := &SecurityTrailsResult{
|
||||
Domain: "example.com",
|
||||
}
|
||||
|
||||
urls := result.DiscoveredURLs()
|
||||
if len(urls) != 0 {
|
||||
t.Errorf("expected 0 URLs, got %d: %v", len(urls), urls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDoSTRequest_Success(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Header.Get("APIKEY") != "test-key" {
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write([]byte(`{"test": true}`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
client := &http.Client{Timeout: 5 * time.Second}
|
||||
body, err := doSTRequest(client, server.URL, "test-key")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if len(body) == 0 {
|
||||
t.Error("expected non-empty body")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDoSTRequest_Unauthorized(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
client := &http.Client{Timeout: 5 * time.Second}
|
||||
_, err := doSTRequest(client, server.URL, "bad-key")
|
||||
if err == nil {
|
||||
t.Error("expected error for forbidden response")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDoSTRequest_RateLimit(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusTooManyRequests)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
client := &http.Client{Timeout: 5 * time.Second}
|
||||
_, err := doSTRequest(client, server.URL, "test-key")
|
||||
if err == nil {
|
||||
t.Error("expected error for rate limit response")
|
||||
}
|
||||
}
|
||||
|
||||
func TestQuerySTSubdomains(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Header.Get("APIKEY") != "test-key" {
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
resp := stSubdomainsResponse{
|
||||
Subdomains: []string{"www", "api", "mail", "dev"},
|
||||
}
|
||||
json.NewEncoder(w).Encode(resp)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
client := &http.Client{Timeout: 5 * time.Second}
|
||||
|
||||
// query the mock server directly via doSTRequest + unmarshal
|
||||
body, err := doSTRequest(client, server.URL, "test-key")
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
|
||||
var resp stSubdomainsResponse
|
||||
if err := json.Unmarshal(body, &resp); err != nil {
|
||||
t.Fatalf("unmarshal failed: %v", err)
|
||||
}
|
||||
|
||||
if len(resp.Subdomains) != 4 {
|
||||
t.Errorf("expected 4 subdomains, got %d", len(resp.Subdomains))
|
||||
}
|
||||
}
|
||||
|
||||
func TestQuerySTAssociated(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Header.Get("APIKEY") != "test-key" {
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
resp := stAssociatedResponse{
|
||||
Records: []stAssociatedRecord{
|
||||
{Hostname: "related.com"},
|
||||
{Hostname: "sibling.net"},
|
||||
{Hostname: ""},
|
||||
},
|
||||
}
|
||||
json.NewEncoder(w).Encode(resp)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
client := &http.Client{Timeout: 5 * time.Second}
|
||||
|
||||
body, err := doSTRequest(client, server.URL, "test-key")
|
||||
if err != nil {
|
||||
t.Fatalf("request failed: %v", err)
|
||||
}
|
||||
|
||||
var resp stAssociatedResponse
|
||||
if err := json.Unmarshal(body, &resp); err != nil {
|
||||
t.Fatalf("unmarshal failed: %v", err)
|
||||
}
|
||||
|
||||
// should have 3 records total (including empty one)
|
||||
if len(resp.Records) != 3 {
|
||||
t.Errorf("expected 3 records, got %d", len(resp.Records))
|
||||
}
|
||||
|
||||
// filter empty hostnames like the real code does
|
||||
var domains []string
|
||||
for _, rec := range resp.Records {
|
||||
if rec.Hostname != "" {
|
||||
domains = append(domains, rec.Hostname)
|
||||
}
|
||||
}
|
||||
if len(domains) != 2 {
|
||||
t.Errorf("expected 2 non-empty domains, got %d", len(domains))
|
||||
}
|
||||
}
|
||||
|
||||
func TestSecurityTrailsResult_ResultType(t *testing.T) {
|
||||
result := &SecurityTrailsResult{}
|
||||
if result.ResultType() != "securitytrails" {
|
||||
t.Errorf("expected ResultType 'securitytrails', got '%s'", result.ResultType())
|
||||
}
|
||||
}
|
||||
|
||||
func TestSecurityTrailsIntegration(t *testing.T) {
|
||||
t.Skip("integration test - requires valid SECURITYTRAILS_API_KEY")
|
||||
|
||||
_, err := SecurityTrails("https://example.com", 10*time.Second, "")
|
||||
if err != nil {
|
||||
t.Logf("SecurityTrails lookup failed: %v", err)
|
||||
}
|
||||
}
|
||||
+17
-21
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -13,7 +13,6 @@
|
||||
package scan
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -73,6 +72,7 @@ type shodanHostResponse struct {
|
||||
}
|
||||
|
||||
// shodanMetadata represents the _shodan field in Shodan API responses.
|
||||
// This provides type safety instead of using map[string]interface{}.
|
||||
type shodanMetadata struct {
|
||||
Module string `json:"module"`
|
||||
Crawler string `json:"crawler,omitempty"`
|
||||
@@ -134,7 +134,7 @@ func Shodan(targetURL string, timeout time.Duration, logdir string) (*ShodanResu
|
||||
|
||||
// log results
|
||||
if logdir != "" {
|
||||
sanitizedURL := stripScheme(targetURL)
|
||||
sanitizedURL := strings.Split(targetURL, "://")[1]
|
||||
if err := logger.WriteHeader(sanitizedURL, logdir, "Shodan lookup"); err != nil {
|
||||
output.Error("Error writing log header: %v", err)
|
||||
}
|
||||
@@ -159,20 +159,20 @@ func resolveHostname(hostname string) (string, error) {
|
||||
return hostname, nil
|
||||
}
|
||||
|
||||
addrs, err := net.DefaultResolver.LookupIPAddr(context.TODO(), hostname)
|
||||
ips, err := net.LookupIP(hostname)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// prefer IPv4
|
||||
for _, addr := range addrs {
|
||||
if addr.IP.To4() != nil {
|
||||
return addr.IP.String(), nil
|
||||
for _, ip := range ips {
|
||||
if ip.To4() != nil {
|
||||
return ip.String(), nil
|
||||
}
|
||||
}
|
||||
|
||||
if len(addrs) > 0 {
|
||||
return addrs[0].IP.String(), nil
|
||||
if len(ips) > 0 {
|
||||
return ips[0].String(), nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("no IP addresses found for %s", hostname)
|
||||
@@ -182,11 +182,7 @@ func queryShodanHost(ip string, apiKey string, timeout time.Duration) (*ShodanRe
|
||||
client := &http.Client{Timeout: timeout}
|
||||
|
||||
reqURL := fmt.Sprintf("%s/shodan/host/%s?key=%s", shodanBaseURL, ip, apiKey)
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, reqURL, http.NoBody)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create Shodan request: %w", err)
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
resp, err := client.Get(reqURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to query Shodan: %w", err)
|
||||
}
|
||||
@@ -236,14 +232,14 @@ func queryShodanHost(ip string, apiKey string, timeout time.Duration) (*ShodanRe
|
||||
Services: make([]ShodanService, 0, len(shodanResp.Data)),
|
||||
}
|
||||
|
||||
for i := range shodanResp.Data {
|
||||
for _, data := range shodanResp.Data {
|
||||
service := ShodanService{
|
||||
Port: shodanResp.Data[i].Port,
|
||||
Protocol: shodanResp.Data[i].Transport,
|
||||
Product: shodanResp.Data[i].Product,
|
||||
Version: shodanResp.Data[i].Version,
|
||||
Banner: truncateBanner(shodanResp.Data[i].Data, 200),
|
||||
Module: shodanResp.Data[i].Shodan.Module,
|
||||
Port: data.Port,
|
||||
Protocol: data.Transport,
|
||||
Product: data.Product,
|
||||
Version: data.Version,
|
||||
Banner: truncateBanner(data.Data, 200),
|
||||
Module: data.Shodan.Module,
|
||||
}
|
||||
result.Services = append(result.Services, service)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
|
||||
+5
-15
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -13,7 +13,6 @@
|
||||
package scan
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"regexp"
|
||||
@@ -121,7 +120,7 @@ func SQL(targetURL string, timeout time.Duration, threads int, logdir string) (*
|
||||
spin := output.NewSpinner("Scanning for SQL exposures")
|
||||
spin.Start()
|
||||
|
||||
sanitizedURL := stripScheme(targetURL)
|
||||
sanitizedURL := strings.Split(targetURL, "://")[1]
|
||||
|
||||
if logdir != "" {
|
||||
if err := logger.WriteHeader(sanitizedURL, logdir, "SQL reconnaissance"); err != nil {
|
||||
@@ -165,12 +164,7 @@ func SQL(targetURL string, timeout time.Duration, threads int, logdir string) (*
|
||||
adminPath := sqlAdminPaths[idx]
|
||||
checkURL := strings.TrimSuffix(targetURL, "/") + adminPath.path
|
||||
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, checkURL, http.NoBody)
|
||||
if err != nil {
|
||||
charmlog.Debugf("Error creating request for %s: %v", checkURL, err)
|
||||
continue
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
resp, err := client.Get(checkURL)
|
||||
if err != nil {
|
||||
charmlog.Debugf("Error checking %s: %v", checkURL, err)
|
||||
continue
|
||||
@@ -249,7 +243,7 @@ func SQL(targetURL string, timeout time.Duration, threads int, logdir string) (*
|
||||
if totalFindings == 0 {
|
||||
log.Info("No SQL exposures found")
|
||||
log.Complete(0, "found")
|
||||
return nil, nil //nolint:nilnil // no SQLi found is not an error
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
log.Complete(totalFindings, "found")
|
||||
@@ -291,11 +285,7 @@ func isAdminPanel(body string, panelType string) bool {
|
||||
}
|
||||
|
||||
func checkDatabaseErrors(client *http.Client, checkURL, sanitizedURL string, result *SQLResult, logdir string, mu *sync.Mutex, seen map[string]bool) {
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, checkURL, http.NoBody)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
resp, err := client.Get(checkURL)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -13,8 +13,10 @@
|
||||
package scan
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/charmbracelet/log"
|
||||
"github.com/dropalldatabases/sif/internal/logger"
|
||||
"github.com/dropalldatabases/sif/internal/styles"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -22,10 +24,6 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/charmbracelet/log"
|
||||
"github.com/dropalldatabases/sif/internal/logger"
|
||||
"github.com/dropalldatabases/sif/internal/styles"
|
||||
)
|
||||
|
||||
// SubdomainTakeoverResult represents the outcome of a subdomain takeover vulnerability check.
|
||||
@@ -36,12 +34,22 @@ type SubdomainTakeoverResult struct {
|
||||
Service string `json:"service,omitempty"`
|
||||
}
|
||||
|
||||
// SubdomainTakeover checks dnsResults for dangling subdomains pointing at
|
||||
// unclaimed third-party services.
|
||||
// SubdomainTakeover checks for potential subdomain takeover vulnerabilities.
|
||||
//
|
||||
// Parameters:
|
||||
// - url: the target URL to scan
|
||||
// - dnsResults: a slice of subdomains to check (typically from Dnslist function)
|
||||
// - timeout: maximum duration for each subdomain check
|
||||
// - threads: number of concurrent threads to use
|
||||
// - logdir: directory to store log files (empty string for no logging)
|
||||
//
|
||||
// Returns:
|
||||
// - []SubdomainTakeoverResult: a slice of results for each checked subdomain
|
||||
// - error: any error encountered during the scan
|
||||
func SubdomainTakeover(url string, dnsResults []string, timeout time.Duration, threads int, logdir string) ([]SubdomainTakeoverResult, error) {
|
||||
fmt.Println(styles.Separator.Render("Starting " + styles.Status.Render("Subdomain Takeover Vulnerability Check") + "..."))
|
||||
fmt.Println(styles.Separator.Render("🔍 Starting " + styles.Status.Render("Subdomain Takeover Vulnerability Check") + "..."))
|
||||
|
||||
sanitizedURL := stripScheme(url)
|
||||
sanitizedURL := strings.Split(url, "://")[1]
|
||||
|
||||
if logdir != "" {
|
||||
if err := logger.WriteHeader(sanitizedURL, logdir, "Subdomain Takeover Vulnerability Check"); err != nil {
|
||||
@@ -51,7 +59,7 @@ func SubdomainTakeover(url string, dnsResults []string, timeout time.Duration, t
|
||||
}
|
||||
|
||||
subdomainlog := log.NewWithOptions(os.Stderr, log.Options{
|
||||
Prefix: "Subdomain Takeover",
|
||||
Prefix: "Subdomain Takeover 🔍",
|
||||
})
|
||||
|
||||
client := &http.Client{
|
||||
@@ -106,15 +114,11 @@ func SubdomainTakeover(url string, dnsResults []string, timeout time.Duration, t
|
||||
}
|
||||
|
||||
func checkSubdomainTakeover(subdomain string, client *http.Client) (bool, string) {
|
||||
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, "http://"+subdomain, http.NoBody)
|
||||
if err != nil {
|
||||
return false, ""
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
resp, err := client.Get("http://" + subdomain)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "no such host") {
|
||||
// Check if CNAME exists
|
||||
cname, err := net.DefaultResolver.LookupCNAME(context.TODO(), subdomain)
|
||||
cname, err := net.LookupCNAME(subdomain)
|
||||
if err == nil && cname != "" {
|
||||
return true, "Dangling CNAME"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
@@ -13,6 +13,8 @@
|
||||
package scan
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/charmbracelet/log"
|
||||
"github.com/dropalldatabases/sif/internal/logger"
|
||||
"github.com/dropalldatabases/sif/internal/output"
|
||||
@@ -22,7 +24,7 @@ import (
|
||||
func Whois(url string, logdir string) {
|
||||
output.ScanStart("WHOIS lookup")
|
||||
|
||||
sanitizedURL := stripScheme(url)
|
||||
sanitizedURL := strings.Split(url, "://")[1]
|
||||
if logdir != "" {
|
||||
if err := logger.WriteHeader(sanitizedURL, logdir, " WHOIS scanning"); err != nil {
|
||||
output.Error("Error creating log file: %v", err)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
: :
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
*/
|
||||
|
||||
// Package version resolves sif's version from the build.
|
||||
package version
|
||||
|
||||
import (
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Resolve returns the best version available: the build-time ldflag if it was
|
||||
// stamped, else the go build info (module tag or vcs revision), else "dev". the
|
||||
// leading v is dropped so it matches the bare form the rest of sif uses.
|
||||
func Resolve(ldflag string) string {
|
||||
if ldflag != "" && ldflag != "dev" {
|
||||
return normalize(ldflag)
|
||||
}
|
||||
if v := fromBuildInfo(); v != "" {
|
||||
return normalize(v)
|
||||
}
|
||||
return "dev"
|
||||
}
|
||||
|
||||
func fromBuildInfo() string {
|
||||
info, ok := debug.ReadBuildInfo()
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
if v := info.Main.Version; v != "" && v != "(devel)" {
|
||||
return v
|
||||
}
|
||||
|
||||
// no module tag (a local build) - fall back to the commit it was built from
|
||||
var revision, modified string
|
||||
for _, s := range info.Settings {
|
||||
switch s.Key {
|
||||
case "vcs.revision":
|
||||
revision = s.Value
|
||||
case "vcs.modified":
|
||||
modified = s.Value
|
||||
}
|
||||
}
|
||||
if revision == "" {
|
||||
return ""
|
||||
}
|
||||
if len(revision) > 12 {
|
||||
revision = revision[:12]
|
||||
}
|
||||
if modified == "true" {
|
||||
revision += "-dirty"
|
||||
}
|
||||
return revision
|
||||
}
|
||||
|
||||
func normalize(v string) string {
|
||||
return strings.TrimPrefix(v, "v")
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
: :
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2026 vmfunc, xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
*/
|
||||
|
||||
package version
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestResolveLdflag(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
ldflag string
|
||||
want string
|
||||
}{
|
||||
{"tag with v", "v2026.6.7", "2026.6.7"},
|
||||
{"tag without v", "2026.6.7", "2026.6.7"},
|
||||
{"pseudo version", "2026.2.17-57-geb33321", "2026.2.17-57-geb33321"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := Resolve(tt.ldflag); got != tt.want {
|
||||
t.Errorf("Resolve(%q) = %q, want %q", tt.ldflag, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// with no ldflag, Resolve falls back to build info; in a test binary that's
|
||||
// non-deterministic, so just assert it never returns an empty string.
|
||||
func TestResolveFallbackNonEmpty(t *testing.T) {
|
||||
if Resolve("dev") == "" {
|
||||
t.Error("Resolve fallback should never be empty")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
: :
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
*/
|
||||
|
||||
// Package worker provides a generic worker pool for concurrent task processing.
|
||||
package worker
|
||||
|
||||
import "sync"
|
||||
|
||||
// Pool manages a pool of workers that process items concurrently.
|
||||
// It uses channel-based distribution for efficient load balancing.
|
||||
type Pool[T any, R any] struct {
|
||||
workers int
|
||||
fn func(T) R
|
||||
}
|
||||
|
||||
// New creates a new worker pool with the specified number of workers
|
||||
// and a processing function.
|
||||
func New[T any, R any](workers int, fn func(T) R) *Pool[T, R] {
|
||||
if workers < 1 {
|
||||
workers = 1
|
||||
}
|
||||
return &Pool[T, R]{
|
||||
workers: workers,
|
||||
fn: fn,
|
||||
}
|
||||
}
|
||||
|
||||
// Run processes all items concurrently and returns the results.
|
||||
// Items are distributed via a channel for optimal load balancing.
|
||||
func (p *Pool[T, R]) Run(items []T) []R {
|
||||
if len(items) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
input := make(chan T, len(items))
|
||||
output := make(chan R, len(items))
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(p.workers)
|
||||
|
||||
// Start workers
|
||||
for i := 0; i < p.workers; i++ {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for item := range input {
|
||||
output <- p.fn(item)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Feed items to workers
|
||||
for _, item := range items {
|
||||
input <- item
|
||||
}
|
||||
close(input)
|
||||
|
||||
// Wait for all workers to finish, then close output
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(output)
|
||||
}()
|
||||
|
||||
// Collect results
|
||||
results := make([]R, 0, len(items))
|
||||
for r := range output {
|
||||
results = append(results, r)
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
// RunWithFilter processes items concurrently and returns only non-zero results.
|
||||
// Useful when the processing function may return zero values for filtered items.
|
||||
func (p *Pool[T, R]) RunWithFilter(items []T, filter func(R) bool) []R {
|
||||
if len(items) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
input := make(chan T, len(items))
|
||||
output := make(chan R, len(items))
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(p.workers)
|
||||
|
||||
// Start workers
|
||||
for i := 0; i < p.workers; i++ {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for item := range input {
|
||||
result := p.fn(item)
|
||||
if filter(result) {
|
||||
output <- result
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Feed items to workers
|
||||
for _, item := range items {
|
||||
input <- item
|
||||
}
|
||||
close(input)
|
||||
|
||||
// Wait for all workers to finish, then close output
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(output)
|
||||
}()
|
||||
|
||||
// Collect results
|
||||
results := make([]R, 0, len(items)/2) // Estimate half will pass filter
|
||||
for r := range output {
|
||||
results = append(results, r)
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
// ForEach processes items concurrently without collecting results.
|
||||
// Useful for side-effect operations like logging or writing to external stores.
|
||||
func (p *Pool[T, R]) ForEach(items []T, callback func(R)) {
|
||||
if len(items) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
input := make(chan T, len(items))
|
||||
output := make(chan R, len(items))
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(p.workers)
|
||||
|
||||
// Start workers
|
||||
for i := 0; i < p.workers; i++ {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for item := range input {
|
||||
output <- p.fn(item)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Feed items to workers
|
||||
for _, item := range items {
|
||||
input <- item
|
||||
}
|
||||
close(input)
|
||||
|
||||
// Process results as they come in
|
||||
var outputWg sync.WaitGroup
|
||||
outputWg.Add(1)
|
||||
go func() {
|
||||
defer outputWg.Done()
|
||||
for r := range output {
|
||||
callback(r)
|
||||
}
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
close(output)
|
||||
outputWg.Wait()
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
: :
|
||||
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
||||
: ▄█ █ █▀ · BSD 3-Clause License :
|
||||
: :
|
||||
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
|
||||
: lunchcat alumni & contributors :
|
||||
: :
|
||||
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
||||
*/
|
||||
|
||||
package worker
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPoolRun(t *testing.T) {
|
||||
pool := New(4, func(x int) int {
|
||||
return x * 2
|
||||
})
|
||||
|
||||
items := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
|
||||
results := pool.Run(items)
|
||||
|
||||
if len(results) != len(items) {
|
||||
t.Errorf("Expected %d results, got %d", len(items), len(results))
|
||||
}
|
||||
|
||||
// Sort results since order is not guaranteed
|
||||
sort.Ints(results)
|
||||
expected := []int{2, 4, 6, 8, 10, 12, 14, 16, 18, 20}
|
||||
for i, v := range results {
|
||||
if v != expected[i] {
|
||||
t.Errorf("Expected results[%d] = %d, got %d", i, expected[i], v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPoolRunEmpty(t *testing.T) {
|
||||
pool := New(4, func(x int) int {
|
||||
return x * 2
|
||||
})
|
||||
|
||||
results := pool.Run(nil)
|
||||
if results != nil {
|
||||
t.Errorf("Expected nil for empty input, got %v", results)
|
||||
}
|
||||
|
||||
results = pool.Run([]int{})
|
||||
if results != nil {
|
||||
t.Errorf("Expected nil for empty slice, got %v", results)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPoolRunWithFilter(t *testing.T) {
|
||||
pool := New(4, func(x int) int {
|
||||
return x * 2
|
||||
})
|
||||
|
||||
items := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
|
||||
results := pool.RunWithFilter(items, func(r int) bool {
|
||||
return r > 10 // Only keep results > 10
|
||||
})
|
||||
|
||||
// Should have 5 results: 12, 14, 16, 18, 20
|
||||
if len(results) != 5 {
|
||||
t.Errorf("Expected 5 results, got %d", len(results))
|
||||
}
|
||||
|
||||
sort.Ints(results)
|
||||
expected := []int{12, 14, 16, 18, 20}
|
||||
for i, v := range results {
|
||||
if v != expected[i] {
|
||||
t.Errorf("Expected results[%d] = %d, got %d", i, expected[i], v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPoolForEach(t *testing.T) {
|
||||
var sum atomic.Int64
|
||||
|
||||
pool := New(4, func(x int) int {
|
||||
return x * 2
|
||||
})
|
||||
|
||||
items := []int{1, 2, 3, 4, 5}
|
||||
pool.ForEach(items, func(r int) {
|
||||
sum.Add(int64(r))
|
||||
})
|
||||
|
||||
// Sum should be 2+4+6+8+10 = 30
|
||||
if sum.Load() != 30 {
|
||||
t.Errorf("Expected sum = 30, got %d", sum.Load())
|
||||
}
|
||||
}
|
||||
|
||||
func TestPoolSingleWorker(t *testing.T) {
|
||||
pool := New(1, func(x int) int {
|
||||
return x + 1
|
||||
})
|
||||
|
||||
items := []int{1, 2, 3}
|
||||
results := pool.Run(items)
|
||||
|
||||
if len(results) != 3 {
|
||||
t.Errorf("Expected 3 results, got %d", len(results))
|
||||
}
|
||||
|
||||
sort.Ints(results)
|
||||
expected := []int{2, 3, 4}
|
||||
for i, v := range results {
|
||||
if v != expected[i] {
|
||||
t.Errorf("Expected results[%d] = %d, got %d", i, expected[i], v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPoolZeroWorkers(t *testing.T) {
|
||||
// Zero workers should default to 1
|
||||
pool := New(0, func(x int) int {
|
||||
return x
|
||||
})
|
||||
|
||||
if pool.workers != 1 {
|
||||
t.Errorf("Expected workers = 1, got %d", pool.workers)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPoolStringProcessing(t *testing.T) {
|
||||
pool := New(2, func(s string) int {
|
||||
return len(s)
|
||||
})
|
||||
|
||||
items := []string{"a", "bb", "ccc", "dddd"}
|
||||
results := pool.Run(items)
|
||||
|
||||
sort.Ints(results)
|
||||
expected := []int{1, 2, 3, 4}
|
||||
for i, v := range results {
|
||||
if v != expected[i] {
|
||||
t.Errorf("Expected results[%d] = %d, got %d", i, expected[i], v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPoolStructProcessing(t *testing.T) {
|
||||
type input struct {
|
||||
a int
|
||||
b int
|
||||
}
|
||||
type output struct {
|
||||
sum int
|
||||
prod int
|
||||
}
|
||||
|
||||
pool := New(3, func(in input) output {
|
||||
return output{sum: in.a + in.b, prod: in.a * in.b}
|
||||
})
|
||||
|
||||
items := []input{{1, 2}, {3, 4}, {5, 6}}
|
||||
results := pool.Run(items)
|
||||
|
||||
if len(results) != 3 {
|
||||
t.Errorf("Expected 3 results, got %d", len(results))
|
||||
}
|
||||
|
||||
// Verify all expected outputs are present
|
||||
found := make(map[output]bool)
|
||||
for _, r := range results {
|
||||
found[r] = true
|
||||
}
|
||||
|
||||
expectedOutputs := []output{{3, 2}, {7, 12}, {11, 30}}
|
||||
for _, exp := range expectedOutputs {
|
||||
if !found[exp] {
|
||||
t.Errorf("Expected output %v not found in results", exp)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,164 +0,0 @@
|
||||
.\" man page for sif - the blazing-fast pentesting suite
|
||||
.TH sif 1 "2026-06-08" "sif" "sif manual"
|
||||
.SH NAME
|
||||
sif \- blazing-fast pentesting suite
|
||||
.SH SYNOPSIS
|
||||
.B sif
|
||||
.B \-u
|
||||
.I url
|
||||
.RI [ scans ]
|
||||
.RI [ options ]
|
||||
.br
|
||||
.B sif
|
||||
.B \-f
|
||||
.I file
|
||||
.RI [ scans ]
|
||||
.RI [ options ]
|
||||
.br
|
||||
.B sif
|
||||
.RB { patchnote | version }
|
||||
.SH DESCRIPTION
|
||||
.B sif
|
||||
is a modular recon and exploitation suite. it runs multiple scan types
|
||||
concurrently against one or more targets, and can be extended with yaml
|
||||
modules. targets must include a
|
||||
.B http://
|
||||
or
|
||||
.B https://
|
||||
scheme.
|
||||
.SH TARGETS
|
||||
.TP
|
||||
.BR \-u ", " \-\-urls " \fIlist\fR"
|
||||
comma\-separated list of urls to scan.
|
||||
.TP
|
||||
.BR \-f ", " \-\-file " \fIpath\fR"
|
||||
file with one url per line.
|
||||
.SH SCANS
|
||||
.TP
|
||||
.BR \-dirlist " \fIsize\fR"
|
||||
directory and file fuzzing (small/medium/large).
|
||||
.TP
|
||||
.BR \-dnslist " \fIsize\fR"
|
||||
subdomain enumeration (small/medium/large).
|
||||
.TP
|
||||
.BR \-ports " \fIscope\fR"
|
||||
port scanning (common/full).
|
||||
.TP
|
||||
.B \-nuclei
|
||||
vulnerability scanning with nuclei templates.
|
||||
.TP
|
||||
.B \-dork
|
||||
automated google dorking.
|
||||
.TP
|
||||
.B \-js
|
||||
javascript analysis.
|
||||
.TP
|
||||
.B \-c3
|
||||
cloud storage misconfiguration scan.
|
||||
.TP
|
||||
.B \-headers
|
||||
dump the target's response headers.
|
||||
.TP
|
||||
.BR \-sh ", " \-\-security\-headers
|
||||
flag missing or weak security headers and headers that leak server internals.
|
||||
.TP
|
||||
.B \-st
|
||||
subdomain takeover detection (requires \fB\-dnslist\fR).
|
||||
.TP
|
||||
.B \-cms
|
||||
cms detection.
|
||||
.TP
|
||||
.B \-whois
|
||||
whois lookup.
|
||||
.TP
|
||||
.B \-git
|
||||
exposed git repository detection.
|
||||
.TP
|
||||
.B \-shodan
|
||||
shodan host lookup (requires \fBSHODAN_API_KEY\fR).
|
||||
.TP
|
||||
.B \-securitytrails
|
||||
domain discovery and target expansion (requires \fBSECURITYTRAILS_API_KEY\fR).
|
||||
.TP
|
||||
.B \-sql
|
||||
sql reconnaissance (admin panels, error disclosure).
|
||||
.TP
|
||||
.B \-lfi
|
||||
local file inclusion reconnaissance.
|
||||
.TP
|
||||
.B \-framework
|
||||
framework detection with cve lookup.
|
||||
.TP
|
||||
.B \-noscan
|
||||
skip the base url scan (robots.txt, etc).
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.BR \-d ", " \-\-debug
|
||||
enable debug logging.
|
||||
.TP
|
||||
.BR \-t ", " \-\-timeout " \fIduration\fR"
|
||||
per\-request timeout (default 10s).
|
||||
.TP
|
||||
.BR \-l ", " \-\-log " \fIdir\fR"
|
||||
directory to write logs to.
|
||||
.TP
|
||||
.BR \-\-threads " \fIn\fR"
|
||||
number of concurrent workers (default 10).
|
||||
.TP
|
||||
.BR \-\-template " \fIname\fR"
|
||||
sif runtime template to use.
|
||||
.TP
|
||||
.B \-api
|
||||
emit json results and suppress the interactive output.
|
||||
.SH MODULES
|
||||
.TP
|
||||
.BR \-m ", " \-\-modules " \fIids\fR"
|
||||
comma\-separated module ids to run.
|
||||
.TP
|
||||
.BR \-mt ", " \-\-module\-tags " \fItags\fR"
|
||||
run modules matching these tags.
|
||||
.TP
|
||||
.BR \-am ", " \-\-all\-modules
|
||||
run all loaded modules.
|
||||
.TP
|
||||
.BR \-lm ", " \-\-list\-modules
|
||||
list available modules and exit.
|
||||
.SH COMMANDS
|
||||
.TP
|
||||
.B sif patchnote
|
||||
fetch the latest github release and print its notes. also available as
|
||||
.BR \-pn .
|
||||
.TP
|
||||
.B sif version
|
||||
print the sif version and exit.
|
||||
.SH ENVIRONMENT
|
||||
.TP
|
||||
.B SHODAN_API_KEY
|
||||
api key used by \fB\-shodan\fR.
|
||||
.TP
|
||||
.B SECURITYTRAILS_API_KEY
|
||||
api key used by \fB\-securitytrails\fR.
|
||||
.TP
|
||||
.B SIF_NO_PATCHNOTES
|
||||
set to any value to suppress the once\-per\-version patch note shown at startup.
|
||||
.SH FILES
|
||||
.TP
|
||||
.I ~/.config/sif/modules/
|
||||
user\-defined yaml modules.
|
||||
.TP
|
||||
.I ~/.config/sif/seen_version
|
||||
records the last release whose notes were shown at startup.
|
||||
.SH EXAMPLES
|
||||
.TP
|
||||
run a few scans against a host:
|
||||
.B sif \-u https://example.com \-headers \-sh \-cms \-framework
|
||||
.TP
|
||||
fuzz directories and enumerate subdomains:
|
||||
.B sif \-u https://example.com \-dirlist medium \-dnslist medium
|
||||
.TP
|
||||
scan a list of targets and write logs:
|
||||
.B sif \-f targets.txt \-headers \-l ./logs
|
||||
.SH SEE ALSO
|
||||
project page: https://github.com/vmfunc/sif
|
||||
.SH AUTHORS
|
||||
vmfunc, xyzeva, and the lunchcat contributors.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user