Compare commits

..

123 Commits

Author SHA1 Message Date
vmfunc 495d2c5496 feat: add securitytrails integration for domain discovery + target expansion 2026-02-17 13:38:07 +01:00
dependabot[bot] 5ddfbc6204 chore(deps): bump github.com/likexian/whois from 1.15.1 to 1.15.7 (#67)
Bumps [github.com/likexian/whois](https://github.com/likexian/whois) from 1.15.1 to 1.15.7.
- [Release notes](https://github.com/likexian/whois/releases)
- [Commits](https://github.com/likexian/whois/compare/v1.15.1...v1.15.7)

---
updated-dependencies:
- dependency-name: github.com/likexian/whois
  dependency-version: 1.15.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-13 15:32:55 +01:00
dependabot[bot] b522aa3206 chore(deps): bump github.com/charmbracelet/log from 0.2.4 to 0.4.2 (#74)
Bumps [github.com/charmbracelet/log](https://github.com/charmbracelet/log) from 0.2.4 to 0.4.2.
- [Release notes](https://github.com/charmbracelet/log/releases)
- [Commits](https://github.com/charmbracelet/log/compare/v0.2.4...v0.4.2)

---
updated-dependencies:
- dependency-name: github.com/charmbracelet/log
  dependency-version: 0.4.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-13 15:11:38 +01:00
dependabot[bot] efd089a9b6 chore(deps): bump ossf/scorecard-action from 2.4.0 to 2.4.3 (#66)
Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.4.0 to 2.4.3.
- [Release notes](https://github.com/ossf/scorecard-action/releases)
- [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md)
- [Commits](https://github.com/ossf/scorecard-action/compare/v2.4.0...v2.4.3)

---
updated-dependencies:
- dependency-name: ossf/scorecard-action
  dependency-version: 2.4.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-13 15:11:30 +01:00
dependabot[bot] dd9db0dfd6 chore(deps): bump reviewdog/action-shellcheck from 1.27.0 to 1.32.0 (#70)
Bumps [reviewdog/action-shellcheck](https://github.com/reviewdog/action-shellcheck) from 1.27.0 to 1.32.0.
- [Release notes](https://github.com/reviewdog/action-shellcheck/releases)
- [Commits](https://github.com/reviewdog/action-shellcheck/compare/v1.27.0...v1.32.0)

---
updated-dependencies:
- dependency-name: reviewdog/action-shellcheck
  dependency-version: 1.32.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-13 15:11:26 +01:00
dependabot[bot] 1eab6143bb chore(deps): bump reviewdog/action-markdownlint from 0.24.0 to 0.26.2 (#73)
Bumps [reviewdog/action-markdownlint](https://github.com/reviewdog/action-markdownlint) from 0.24.0 to 0.26.2.
- [Release notes](https://github.com/reviewdog/action-markdownlint/releases)
- [Commits](https://github.com/reviewdog/action-markdownlint/compare/v0.24.0...v0.26.2)

---
updated-dependencies:
- dependency-name: reviewdog/action-markdownlint
  dependency-version: 0.26.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-13 15:11:23 +01:00
dependabot[bot] 418180a124 chore(deps): bump actions/github-script from 7 to 8 (#77)
Bumps [actions/github-script](https://github.com/actions/github-script) from 7 to 8.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v7...v8)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-13 15:05:54 +01:00
dependabot[bot] 6f4144efe1 chore(deps): bump actions/checkout from 4 to 6 (#68)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-13 14:47:32 +01:00
vmfunc a05d6ada56 ci: add pr bot for auto-labeling + rewrite release workflow for semver tags
pr-bot labels PRs by area (scan, nuclei, modules, ci, deps, etc) and size
(xs/s/m/l/xl), posts a summary comment with file stats breakdown.

release workflow now triggers on v* tags instead of every push to main -
extracts version from tag, injects via ldflags, auto-generates changelog
from commits since last release, includes install instructions in the
release body. prerelease detection for rc/beta tags.

Signed-off-by: vmfunc <celeste@linux.com>
2026-02-13 02:19:19 +01:00
vmfunc 75da3e3131 fix: resolve all golangci-lint issues across codebase
- noctx: use http.NewRequestWithContext instead of http.Get/client.Get
- bodyclose: close response bodies on all code paths
- httpNoBody: use http.NoBody instead of nil for GET request bodies
- ifElseChain: convert if/else chains to switch in sif.go
- sloppyReassign: use := in logger.go where possible
- nilnil: annotate intentional nil,nil returns in lfi.go, sql.go
- errcheck: handle template install error in nuclei.go
- govet copylock: pass mutex by pointer in executor.go
- log.Fatalf: replace with log.Errorf+continue in api mode
2026-02-13 02:11:17 +01:00
vmfunc f5251d0c44 chore: strengthen golangci-lint config - add gosec, errorlint, nilnil, wastedassign, usetesting linters
adds security and correctness linters, suppresses noisy checks
(fieldalignment, shadow, unusedwrite, nestingReduce), excludes
logger.Write from errcheck since log writes are best-effort
2026-02-13 02:11:03 +01:00
vmfunc e2198e932b ci: replace qodana with codeql - no external tokens needed
Signed-off-by: vmfunc <celeste@linux.com>
2026-02-13 02:08:32 +01:00
vmfunc bad5b598c9 test: add fuzz tests for LFI detection, SQL patterns, version parsing
fuzz targets: DetectLFIFromResponse, isAdminPanel, databaseErrorPatterns,
isValidVersionString, ExtractVersionOptimized - should bump the scorecard
fuzzing check.

Signed-off-by: vmfunc <celeste@linux.com>
2026-02-13 01:57:46 +01:00
vmfunc c85201b1ed ci: pin govulncheck to v1.1.4 - fixes scorecard pinned-dependencies
Signed-off-by: vmfunc <celeste@linux.com>
2026-02-13 01:57:36 +01:00
vmfunc 45a384bdc9 add SECURITY.md - fixes scorecard security-policy check
Signed-off-by: vmfunc <celeste@linux.com>
2026-02-13 01:57:31 +01:00
vmfunc fcf9291653 ci: add explicit permissions to all workflows - fixes scorecard token-permissions
Signed-off-by: vmfunc <celeste@linux.com>
2026-02-13 01:40:22 +01:00
vmfunc e94fda0acf deps: bump go-git to v5.16.5 - fixes CVE-2026-25934
Signed-off-by: vmfunc <celeste@linux.com>
2026-02-13 01:39:00 +01:00
vmfunc 03a9488b65 internal/scan: migrate nuclei integration to v3 SDK
replace ~100 lines of manual nuclei v2 plumbing (catalog, loader, core,
protocolstate, protocolinit, hosterrorscache, interactsh, reporting,
ratelimit, testutils) with the v3 lib SDK - NewNucleiEngineCtx +
functional options.

drops direct ratelimit dep, mholt/archiver and nwaples/rardecode
(resolves dependabot CVE alerts for path traversal + DoS).

Signed-off-by: vmfunc <celeste@linux.com>
2026-02-13 01:22:25 +01:00
vmfunc 83702e9a41 ci: overhaul workflows - lint, security scanning, release hardening
- add golangci-lint job to go.yml (parallel with build+test)
- add Go 1.23/1.24 version matrix, coverage only on 1.24
- upgrade setup-go@v4 to v5, codecov@v4 to v5 across all workflows
- fix check-large-files bug (find|while never exits 1), exclude .git/
- add concurrency groups to push+PR workflows (no duplicate runs)
- lowercase all workflow names to match project voice
- add gosec, errorlint, gocognit, nilnil, wastedassign, usetesting linters
- remove deprecated exportloopref (Go 1.22 fixed loop var capture)
- new: govulncheck.yml - Go vuln scanner with call-graph analysis
- new: scorecard.yml - OpenSSF supply chain scorecard
- new: dependabot.yml - auto-update Go deps + Actions versions
- release: SHA256 checksums + SBOM generation for all artifacts
- add CODEOWNERS
2026-02-13 01:09:57 +01:00
vmfunc 426a301182 deps: bump projectdiscovery/utils to v0.9.0
Signed-off-by: vmfunc <celeste@linux.com>
2026-02-13 01:03:47 +01:00
vmfunc 953ef299c9 deps: bump goflags to v0.1.74
Signed-off-by: vmfunc <celeste@linux.com>
2026-02-13 01:03:46 +01:00
vmfunc 548c2110d4 update funding.yml with proper sponsor info 2026-02-13 00:26:04 +01:00
vmfunc 4f42c52964 add nixpkgs install instructions and badge to readme 2026-02-13 00:12:28 +01:00
vmfunc 5a557eb20a Merge pull request #62 from 0x4bs3nt/feat/builtin-shodan
feat(modules): builtin shodan scan as module
2026-02-08 21:31:07 +01:00
vmfunc f50f1b933a Merge branch 'main' into feat/builtin-shodan 2026-02-08 19:22:32 +01:00
vmfunc 6f460425be Merge pull request #63 from 0x4bs3nt/feat/builtin-whois
feat(modules): builtin whois scan as module
2026-02-08 14:12:27 +01:00
vmfunc 261dbea356 Merge pull request #64 from 0x4bs3nt/feat/builtin-frameworks
feat(modules): builtin framework detection as module
2026-02-08 14:11:56 +01:00
vmfunc 16ea9047f0 Merge branch 'main' into feat/builtin-frameworks 2026-01-12 11:22:56 +01:00
vmfunc 39bd115d3c Merge branch 'main' into feat/builtin-shodan 2026-01-12 11:22:36 +01:00
vmfunc ccf093b7e9 fix: rename to snakecase 2026-01-12 11:19:54 +01:00
vmfunc b5398ec687 fix: renamed whois module file
Renamed whois scan module file to differentiate from legacy whois scan
file.
2026-01-12 11:19:54 +01:00
vmfunc b298e2ec2c fix(conflicts): fix PR conflicts on 2026-01-12 11:19:48 +01:00
vmfunc 812d0b3e53 Merge pull request #61 from 0x4bs3nt/feat/builtin-nuclei
feat(modules): builtin nuclei scan as module
2026-01-11 16:39:18 -08:00
vmfunc 95cebab47f fix: rename to snakecase 2026-01-07 22:39:56 +01:00
vmfunc 579f5aff4b fix: rename to snakecase 2026-01-07 22:39:35 +01:00
vmfunc 6df46b635a fix: rename to snakecase 2026-01-07 22:39:19 +01:00
vmfunc 4a6364aba9 fix: shodan module file rename
Renamed shodan module file to differentiate from legacy shodan lookup
files.
2026-01-07 22:35:51 +01:00
vmfunc e7db0777c2 fix: frameworks module file rename
Renamed frameworks module file to differentiate from legacy framework
scans.
2026-01-07 22:34:53 +01:00
vmfunc 9767a6b189 fix: renamed nuclei module file
Renamed the nuclei module file to differentiate from the nuclei legacy
scan file.
2026-01-07 22:33:49 +01:00
vmfunc abb992aefd fix: colorizer exception
Fixed Nuclei giving off exception for missing Colorizer on the executor
options.
2026-01-07 19:06:51 +01:00
vmfunc 3c160de165 fix(nuclei): logdir, headless option and hosterrorscache
Set the HostErrorsCache executor option, cache is created but not passed
as option.
Headless initialization is required even without browser templates.
Nuclei expects project file to be set
2026-01-07 17:01:22 +01:00
vmfunc 66a752d604 fix: nuclei scan nil pointer dereference
Fixed nil pointer dereference issues in the nuclei scan running as a
module
2026-01-07 15:09:49 +01:00
vmfunc 45f341c97f feat(modules): legacy nuclei scan
Converted nuclei scan to be able to run as module.
2026-01-07 13:07:35 +01:00
vmfunc 0383c49bbd feat(modules): legacy shodan scan
Converted legacy Go shodan scan to be able to run as module.
2026-01-07 13:05:08 +01:00
vmfunc e5e831541f feat(modules): legacy framework scan
Converted legacy framework scan to be able to run as module.
2026-01-07 13:02:40 +01:00
vmfunc f309198f69 feat(modules): infra for builtin modules
Infrastructure preparation for builtin complex Go module registration.
2026-01-07 12:56:17 +01:00
vmfunc 689d575282 Merge pull request #56 from 0x4bs3nt/feat/astro-framework-detection
feat(frameworks): add Astro framework detection
2026-01-06 12:10:34 -08:00
vmfunc 75014e244b fix: adjust generator meta weight
Adjusted generator meta weight to remain consistent with other meta-framework detectors.

Co-authored-by: vmfunc <celeste@router.sex>
2026-01-06 14:45:03 +01:00
vmfunc 9c5220ec57 Merge pull request #55 from 0x4bs3nt/docs/contributing-update
docs: update CONTRIBUTING.md
2026-01-05 23:50:02 -08:00
vmfunc 0297bf3975 fix: discord invite
Fixed discord invite to official server invite url.
2026-01-06 06:35:32 +01:00
vmfunc 8eb7e84090 fix: use dynamic versioning for debian packages 2026-01-05 20:55:30 -08:00
vmfunc 4e0c45fa58 docs: update CONTRIBUTING.md
Update CONTRIBUTING.md docs with up to date data:
 - Discord invite to new sif server
 - Update URL-s to new vmfunc/sif repository
 - Update guidelines on contributing framework detection patterns
2026-01-06 05:30:34 +01:00
vmfunc 6467a2ca58 docs: add apt/cloudsmith installation instructions and badge 2026-01-05 20:28:30 -08:00
vmfunc 844affaed4 ci: push debian packages to cloudsmith 2026-01-05 20:28:07 -08:00
vmfunc 56895899ff ci: add debian package builds to releases 2026-01-05 20:13:18 -08:00
vmfunc 2e99e5072f docs: add 0xatrilla to contributors for AUR packaging 2026-01-05 19:51:50 -08:00
vmfunc 37925c6c99 docs: add AUR and Homebrew badges to readme 2026-01-05 19:48:51 -08:00
vmfunc d3216ca4a6 Merge pull request #53 from 0xatrilla/add-aur-install-instructions
docs: add AUR installation instructions
2026-01-05 19:44:43 -08:00
vmfunc 277f516ce9 chore: revise arch linux installation section in README
Updated Arch Linux installation instructions in README.md.
2026-01-05 19:44:15 -08:00
vmfunc ee1f9d7f31 feat(frameworks): add Astro framework detection
Add detection support for the Astro meta framework.

Includes signature detection, version extraction and tests with full
signature coverage.
2026-01-06 04:40:15 +01:00
acxtrilla 9705d95067 docs: add AUR installation instructions
Added Arch Linux (AUR) installation section to README with instructions
for installing via AUR helpers (yay/paru) or manually with makepkg.

Package available at: https://aur.archlinux.org/packages/sif
2026-01-06 01:56:40 +00:00
vmfunc 8c60e255dc docs: add homebrew installation instructions 2026-01-05 16:53:26 -08:00
vmfunc 7438dfb2ca chore: readme inconsistency 2026-01-03 06:14:40 -08:00
vmfunc 60c38e29cf ci: upgrade to go 1.24 in all workflows 2026-01-03 06:04:33 -08:00
vmfunc 7268374333 chore: add license headers to missing files 2026-01-03 06:01:00 -08:00
vmfunc 00a66adf27 feat(output): add styled console output with module loggers
- Add output package with colored prefixes and module loggers
- Each module gets unique background color based on name hash
- Add spinner for indeterminate operations
- Add progress bar for known-count operations
- Update all scan files to use ModuleLogger pattern
- Add clean PrintSummary for scan completion
2026-01-03 05:57:10 -08:00
vmfunc ab17191c31 docs: add comprehensive documentation and fix github actions
- add docs/ with installation, usage, modules, scans, and api docs
- add docs link to main readme
- fix release.yml to bundle modules directory with releases
- add module system tests to runtest.yml
- standardize go version to 1.23 across workflows
2026-01-03 05:57:10 -08:00
vmfunc cd1a56bd14 docs: update readme and add module documentation 2026-01-03 05:57:10 -08:00
vmfunc 36a0e473e3 feat: show module loading and execution logs by default 2026-01-03 05:57:10 -08:00
vmfunc 29b1b804af feat: add debug logging for module execution 2026-01-03 05:57:10 -08:00
vmfunc d2537dae1b refactor: move pkg/scan to internal/scan 2026-01-03 05:57:10 -08:00
vmfunc 6d8319dfa8 fix: add io.LimitReader and proper error handling to shodan.go
Add io.LimitReader with 5MB limit to prevent memory exhaustion and
fix ignored error in queryShodanHost. The error from io.ReadAll was
previously being discarded with _, which could mask read failures.
2026-01-03 05:57:10 -08:00
vmfunc 7ec8c6fb70 fix: add io.LimitReader to prevent memory exhaustion
Add io.LimitReader with 5MB limit to all HTTP response body reads
to prevent potential memory exhaustion from maliciously large responses.

Affected files:
- pkg/scan/cms.go
- pkg/scan/subdomaintakeover.go
- pkg/scan/js/scan.go
- pkg/scan/js/supabase.go
2026-01-03 05:57:10 -08:00
vmfunc 3e4fd67588 fix: regex compilation performance
Move regex compilation from inside functions to package level to avoid
recompiling on every function call. This improves performance by
compiling the regex patterns once at package initialization.

- Move jwtRegex to package level in supabase.go
- Move nextPagesRegex to package level in next.go
- Use strings.Builder instead of string concatenation in next.go
2026-01-03 05:57:10 -08:00
vmfunc 2d306fcf1d feat: implement loadYAML in module loader 2026-01-03 05:57:10 -08:00
vmfunc 82c8667e63 feat: integrate module system into sif.go
Add module system integration allowing users to run YAML-defined security
modules via CLI flags. Implements --list-modules to display available modules,
and supports running modules by ID, tags, or all at once.
2026-01-03 05:57:10 -08:00
vmfunc dc537a02f2 feat: add module cli flags 2026-01-03 05:57:10 -08:00
vmfunc a5ea29b88d feat: add built-in yaml modules for security scanning 2026-01-03 05:57:10 -08:00
vmfunc 01a10c6a2f feat: add yaml module parser and http executor 2026-01-03 05:57:10 -08:00
vmfunc 9154f8e77a feat: add module system infrastructure 2026-01-03 05:57:10 -08:00
vmfunc 539122ac4e refactor: move config to internal 2026-01-03 05:57:10 -08:00
vmfunc 28588fe37c refactor: move logger to internal 2026-01-03 05:57:10 -08:00
vmfunc a6abadd0d4 refactor: rewrite framework detection with modular detector architecture
- create detector interface and registry for extensibility
- extract detectors to separate files: backend.go, frontend.go, cms.go, meta.go
- reduce detect.go from 785 lines to 178 lines (pure orchestrator)
- export VersionMatch and ExtractVersionOptimized for detector use
- create result.go with NewFrameworkResult and WithVulnerabilities helpers
- add url validation to New() for early error detection
- add sif_test.go with main package tests
- update detect_test.go to use external test package pattern
2026-01-03 05:57:09 -08:00
vmfunc 1b27250b05 feat: add generic types and type-safe result handling
introduce ScanResult interface and generic NewModuleResult constructor
for compile-time type safety when creating module results.

- add pkg/scan/result.go with ScanResult interface and named slice types
- add typed shodanMetadata struct to replace map[string]interface{}
- refactor supabase.go with typed response structs and json.RawMessage
- add ResultType() methods to all scan result types
- update sif.go to use NewModuleResult generic constructor

this provides type safety without breaking JSON serialization.
2026-01-03 05:57:09 -08:00
vmfunc 2002509ab5 refactor: extract cve database to separate file
move CVEEntry struct and knownCVEs map to cve.go for better
organization. this reduces detect.go by another 170 lines and makes
the CVE database easier to maintain and extend.
2026-01-03 05:57:09 -08:00
vmfunc 7223a2eb66 perf: precompile framework version regex patterns
move version extraction patterns to version.go and compile them at init
time instead of recompiling on every check. this significantly improves
framework detection performance.

- add version.go with pre-compiled regex patterns for all frameworks
- update detect.go to use extractVersionOptimized
- remove duplicate extractVersionWithConfidence and isValidVersion functions
- add io.LimitReader to prevent memory exhaustion on large responses
- update tests to use the optimized version extraction
2026-01-03 05:57:09 -08:00
vmfunc 314783dba3 fix: response body leaks in cms.go and sql.go
close response bodies immediately after reading instead of deferring
inside loops, which delays closure until function exit
2026-01-03 05:57:09 -08:00
vmfunc bad1af5fc6 fix: response body leak in scan.go robots processing
move resp.body.close() inside the loop after use instead of deferring,
which would only run when the outer function exits
2026-01-03 05:57:09 -08:00
vmfunc 7ab5cfc18c feat: add generic worker pool for concurrent task processing
implement channel-based work distribution with generics for type-safe
concurrent processing, includes run, runwithfilter, and foreach methods
with comprehensive test coverage
2026-01-03 05:57:09 -08:00
vmfunc aba8c410a6 perf: optimize deduplication with map-based o(1) lookups in lfi and sql
replace o(n) slice iteration with map lookups for checking duplicates,
preallocate result slices, reduce lock hold time by separating map check
from result append
2026-01-03 05:57:09 -08:00
vmfunc 582baf2d33 fix: data races and slice preallocation in dirlist and dnslist
add mutex protection for concurrent slice appends, preallocate result
slices with reasonable capacity, use logger instead of direct file i/o
2026-01-03 05:57:09 -08:00
vmfunc ecb0124688 fix: error patterns and string building in sif.go and js/scan.go
replace errors.new(fmt.sprintf()) with fmt.errorf, use strings.builder
instead of string concatenation in loop, fix defer in loop issue,
preallocate slices where size is estimable
2026-01-03 05:57:09 -08:00
vmfunc 088a5bebeb test: add logger tests for buffered write functionality
covers initialization, write, flush, close, concurrent writes, and
file creation with proper cleanup verification
2026-01-03 05:57:09 -08:00
vmfunc 17d8e664d6 refactor: logger to use buffered file handles
replace per-write file open/close with cached file handles and buffered
writers for significantly reduced i/o overhead. adds flush and close
methods for proper cleanup at program exit.
2026-01-03 05:57:09 -08:00
vmfunc 86539cd06e chore: remove unused utils package
the returnApiOutput function was never used and contained only
hardcoded test data
2026-01-03 05:57:09 -08:00
vmfunc 046a5bc7d7 ci: add test coverage reporting to workflow
run tests with race detector and coverage profiling, upload results
to codecov for visibility into test coverage metrics
2026-01-03 05:57:09 -08:00
vmfunc 295d684054 ci: enhance golangci-lint with additional linters
add gocritic, revive, unconvert, prealloc, bodyclose, noctx, and
exportloopref for better code quality detection
2026-01-03 05:57:09 -08:00
vmfunc 8cb4a85a99 Merge pull request #51 from andrewgazelka/chore/modernize-nix-flake
chore(nix): modernize flake to use buildGoModule
2026-01-03 00:38:59 -08:00
Andrew Gazelka f2c8cc71b2 chore(nix): modernize flake to use buildGoModule
- Remove flake-utils dependency (use local forAllSystems helper)
- Remove gomod2nix dependency (use native buildGoModule)
- Add overlay export for easy consumption
- Update nixpkgs to latest unstable
- Disable tests in nix build (require network access)
2026-01-03 00:25:37 -08:00
vmfunc 01fa28555b docs: update contributor name and add vxfemboy 2026-01-02 19:56:44 -08:00
vmfunc 29478f087a chore: fix contributorrc 2026-01-02 19:55:31 -08:00
vmfunc 7b3f4a4f2f chore: fix contributorrc 2026-01-02 19:51:03 -08:00
vmfunc 563f3817ce Merge pull request #40 from vmfunc/feat/framework-detection
feat: framework detection module
2026-01-02 19:15:07 -08:00
vmfunc 20ea60cd70 fix: adjust sif logo alignment 2026-01-02 19:12:28 -08:00
vmfunc 5eac60f696 fix: improve version detection and add documentation
- fix version detection to validate reasonable version numbers (major < 100)
- remove overly permissive patterns that caused false positives
- add comprehensive framework contribution documentation to CONTRIBUTING.md
- document signature patterns, version detection, and CVE data format
- add configuration documentation for flags and env vars
- outline future enhancements for community contributions
2026-01-02 19:04:37 -08:00
vmfunc e02e1554ea docs: add framework detection to readme 2026-01-02 18:54:24 -08:00
vmfunc 816b89328c feat: expand framework detection with cvs, version confidence, concurrency
- add 20+ new framework signatures (vue, angular, react, svelte, sveltekit,
  remix, gatsby, joomla, magento, shopify, ghost, ember, backbone, meteor,
  strapi, adonisjs, cakephp, codeigniter, asp.net core, spring boot)
- add version confidence scoring with multiple detection sources
- add concurrent framework scanning for better performance
- expand cve database with 15+ known vulnerabilities (spring4shell, etc.)
- add risk level assessment based on cve severity
- add comprehensive security recommendations
- add new tests for all features
2026-01-02 18:52:15 -08:00
vmfunc af9d05f6b2 chore: add license header to detect.go 2026-01-02 18:52:15 -08:00
vmfunc 138bdf35aa feat: improve framework detection with more signatures and tests
- use math.Exp instead of custom exp implementation
- add more framework signatures: next.js, nuxt.js, wordpress, drupal,
  symfony, fastapi, gin, phoenix
- fix header detection to check both header names and values
- simplify version detection (remove unnecessary padding)
- add comprehensive test suite for framework detection
- fix formatting in dork.go
2026-01-02 18:52:15 -08:00
vmfunc 494a84e338 chore(actions): add framework to CI 2026-01-02 18:52:15 -08:00
vmfunc 3bc7a2463d feat(framework-detection): weighted bayesian detection algorithm
- weighted signature matching for more accurate framework detection
- sigmoid normalization for confidence scores
- version detection with semantic versioning support
- header-only pattern
2026-01-02 18:52:15 -08:00
vmfunc a08239bb1c feat: framework detection module 2026-01-02 18:52:15 -08:00
vmfunc ecf71be01f fix: use static discord badge instead of server id 2026-01-02 18:45:07 -08:00
vmfunc 29709103be docs: update readme with new modules and discord link 2026-01-02 18:42:45 -08:00
vmfunc db24c59498 feat: add lfi reconnaissance module (#49)
adds a new --lfi flag for local file inclusion vulnerability scanning:
- tests common lfi parameters with directory traversal payloads
- detects /etc/passwd, /etc/shadow, windows system files
- identifies php wrappers and encoded content
- supports various bypass techniques (null bytes, encoding)

closes #4
2026-01-02 18:41:30 -08:00
vmfunc 4392e33179 feat: add sql reconnaissance module (#48)
adds a new --sql flag that performs sql reconnaissance on target urls:
- detects common database admin panels (phpmyadmin, adminer, pgadmin, etc.)
- identifies database error disclosure (mysql, postgresql, mssql, oracle, sqlite)
- scans common paths for sql injection indicators

closes #3
2026-01-02 18:40:06 -08:00
vmfunc 080ab10f56 fix: remove duplicate subdomain takeover call and add config tests (#46)
- remove duplicate SubdomainTakeover call that ran twice when both
  dns scan and --st flag were enabled
- add comprehensive tests for config settings defaults and behavior
- fix formatting in dork.go

closes #1
2026-01-02 18:38:47 -08:00
vmfunc 4a77307acf Merge pull request #47 from vmfunc/feat/shodan-integration
feat: add shodan integration for host reconnaissance
2026-01-02 18:35:56 -08:00
vmfunc d44dbb7f48 feat: add shodan integration for host reconnaissance
adds a new --shodan flag that queries the shodan api for information
about the target host. requires SHODAN_API_KEY environment variable.

features:
- resolves hostnames to ip addresses
- queries shodan host api for reconnaissance data
- displays organization, isp, location, ports, services, and vulns
- logs results to file when logdir is specified

closes #2
2026-01-02 18:24:37 -08:00
vmfunc 1bf927b895 fix: update dependencies to address security vulnerabilities
- golang.org/x/crypto v0.26.0 -> v0.46.0 (critical: ssh auth bypass)
- golang.org/x/net v0.28.0 -> v0.48.0 (medium: xss vulnerability)
- golang.org/x/oauth2 v0.11.0 -> v0.34.0 (high: input validation)
- quic-go v0.48.2 -> v0.58.0 (high: panic on undecryptable packets)
- golang-jwt/jwt v4.5.1 -> v4.5.2 (high: memory allocation)
- cloudflare/circl v1.3.7 -> v1.6.2 (low: validation issues)
- refraction-networking/utls v1.5.4 -> v1.8.1 (medium: tls downgrade)
- ulikunitz/xz v0.5.11 -> v0.5.15 (medium: memory leak)
- klauspost/compress v1.16.7 -> v1.17.4

also fixes go vet warnings for non-constant format strings
2026-01-02 18:03:27 -08:00
vmfunc 0e3e43a1f3 fix: update readme badges and use banner image
- update badges to point to vmfunc/sif
- replace ascii art with banner image
- fix header check action to check first 5 lines
- remove obsolete LICENSE.md
2026-01-02 17:54:17 -08:00
vmfunc 8230edf30b chore: delete old license 2026-01-02 17:45:14 -08:00
vmfunc d30c7f56a3 license: switch to bsd 3-clause, update headers and readme
- replace proprietary license with bsd 3-clause
- update all go file headers with new retro terminal style
- add header-check github action to enforce license headers
- completely rewrite readme to be modern, sleek, and lowercase
- fix broken badges
2026-01-02 17:41:18 -08:00
89 changed files with 3243 additions and 762 deletions
+1
View File
@@ -0,0 +1 @@
* @vmfunc
+15
View File
@@ -0,0 +1,15 @@
# These are supported funding model platforms
github: vmfunc
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
thanks_dev: # Replace with a single thanks.dev username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
+17
View File
@@ -0,0 +1,17 @@
version: 2
updates:
- package-ecosystem: gomod
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 5
labels:
- deps
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 5
labels:
- deps
+44
View File
@@ -0,0 +1,44 @@
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"
+8 -3
View File
@@ -1,7 +1,12 @@
name: Automatic Rebase
name: automatic rebase
on:
issue_comment:
types: [created]
permissions:
contents: write
pull-requests: write
jobs:
rebase:
name: Rebase
@@ -9,10 +14,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the latest code
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Automatic Rebase
- name: automatic rebase
uses: cirrus-actions/rebase@1.8
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+18 -7
View File
@@ -1,18 +1,29 @@
name: Check Large Files
name: check large files
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
check-large-files:
name: Check for large files
name: check for large files
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check for large files
- uses: actions/checkout@v6
- name: check for large files
run: |
find . -type f -size +5M | while read file; do
echo "::error file=${file}::File ${file} is larger than 5MB"
done
large_files=$(find . -path ./.git -prune -o -type f -size +5M -print)
if [ -n "$large_files" ]; then
echo "$large_files" | while read -r file; do
echo "::error file=${file}::File ${file} is larger than 5MB"
done
exit 1
fi
+27 -12
View File
@@ -1,24 +1,39 @@
name: Qodana
name: code quality
on:
workflow_dispatch:
pull_request:
push:
branches:
- main
schedule:
- cron: "0 6 * * 1" # monday 06:00 UTC
permissions: {}
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
qodana:
codeql:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
checks: write
security-events: write
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: set up go
uses: actions/setup-go@v5
with:
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 }}
go-version: "1.24"
- name: initialize codeql
uses: github/codeql-action/init@v3
with:
languages: go
- name: build
run: go build ./...
- name: perform codeql analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:go"
+9 -5
View File
@@ -1,4 +1,4 @@
name: "Dependency Review"
name: dependency review
on:
pull_request:
push:
@@ -7,16 +7,20 @@ on:
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- name: "Checkout Repository"
uses: actions/checkout@v4
- name: "Dependency Review"
- name: checkout repository
uses: actions/checkout@v6
- name: dependency review
uses: actions/dependency-review-action@v4
continue-on-error: ${{ github.event_name == 'push' }}
- name: "Check Dependency Review Outcome"
- name: check dependency review outcome
if: github.event_name == 'push' && failure()
run: |
echo "::warning::Dependency review failed. Please check the dependencies for potential issues."
+35 -9
View File
@@ -1,24 +1,50 @@
name: Go
name: go
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v4
- uses: actions/checkout@v6
- name: set up go
uses: actions/setup-go@v5
with:
go-version: "1.24"
- name: Build
- name: golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: latest
build:
runs-on: ubuntu-latest
strategy:
matrix:
go-version: ["1.23", "1.24"]
steps:
- uses: actions/checkout@v6
- name: set up go
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
- name: build
run: make
- name: Run tests with coverage
- name: run tests with coverage
run: go test -race -coverprofile=coverage.out -covermode=atomic ./...
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
- name: upload coverage to codecov
if: matrix.go-version == '1.24'
uses: codecov/codecov-action@v5
with:
files: ./coverage.out
fail_ci_if_error: false
+27
View File
@@ -0,0 +1,27 @@
name: govulncheck
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: "0 6 * * 1" # monday 06:00 UTC
permissions:
contents: read
jobs:
govulncheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: set up go
uses: actions/setup-go@v5
with:
go-version: "1.24"
- name: install govulncheck
run: go install golang.org/x/vuln/cmd/govulncheck@v1.1.4
- name: run govulncheck
run: govulncheck ./...
continue-on-error: true
+5 -2
View File
@@ -8,11 +8,14 @@ on:
paths:
- '**.go'
permissions:
contents: read
jobs:
check-headers:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: check license headers
run: |
@@ -41,7 +44,7 @@ jobs:
echo ': █▀ █ █▀▀ · Blazing-fast pentesting suite :'
echo ': ▄█ █ █▀ · BSD 3-Clause License :'
echo ': :'
echo ': (c) 2022-2025 vmfunc (vmfunc), xyzeva, :'
echo ': (c) 2022-2025 vmfunc, xyzeva, :'
echo ': lunchcat alumni & contributors :'
echo ': :'
echo '·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·'
+8 -2
View File
@@ -1,4 +1,4 @@
name: Mind your language
name: mind your language
on:
issues:
types:
@@ -12,13 +12,19 @@ on:
types:
- created
- edited
permissions:
contents: read
issues: write
pull-requests: write
jobs:
echo_issue_comment:
runs-on: ubuntu-latest
name: profanity check
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Profanity check step
uses: tailaiw/mind-your-language-action@v1.0.3
env:
+7 -3
View File
@@ -1,18 +1,22 @@
name: Markdown Lint
name: markdown lint
on:
pull_request:
paths:
- "**/*.md"
permissions:
contents: read
pull-requests: write
jobs:
markdownlint:
name: runner / markdownlint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: markdownlint
uses: reviewdog/action-markdownlint@v0.24.0
uses: reviewdog/action-markdownlint@v0.26.2
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
reporter: github-pr-review
+10 -2
View File
@@ -1,16 +1,24 @@
name: Misspell Check
name: misspell check
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
pull-requests: write
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
misspell:
name: runner / misspell
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: misspell
uses: reviewdog/action-misspell@v1.26.0
with:
+139
View File
@@ -0,0 +1,139 @@
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@v5
with:
configuration-path: .github/labeler.yml
size:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: label pr size
uses: actions/github-script@v8
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@v8
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,
});
}
+102 -50
View File
@@ -1,8 +1,9 @@
name: Release
name: release
on:
push:
branches: [main]
tags:
- "v*"
permissions:
contents: write
@@ -18,29 +19,32 @@ jobs:
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v4
- uses: actions/checkout@v6
- name: set up go
uses: actions/setup-go@v5
with:
go-version: "1.24"
- name: Build for Windows
run: |
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: extract version
run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV
- name: Build for macOS
- name: build for windows
run: |
GOOS=darwin GOARCH=amd64 go build -o sif-macos-amd64 ./cmd/sif
GOOS=darwin GOARCH=arm64 go build -o sif-macos-arm64 ./cmd/sif
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
- name: Build for Linux
- name: build for macOS
run: |
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
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
- name: Package releases with modules
- 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
- name: package releases with modules
run: |
for binary in sif-linux-amd64 sif-linux-386 sif-linux-arm64 sif-macos-amd64 sif-macos-arm64; do
mkdir -p "dist/${binary}"
@@ -55,10 +59,8 @@ jobs:
cd dist && zip -r "../${binary}.zip" "${binary}" && cd ..
done
- name: Build Debian packages
- 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"
@@ -67,7 +69,7 @@ jobs:
for binary in sif-linux-amd64 sif-linux-386 sif-linux-arm64; do
arch="${arch_map[$binary]}"
pkg_dir="sif_${VERSION}_${arch}"
pkg_dir="sif_${{ env.VERSION }}_${arch}"
mkdir -p "${pkg_dir}/DEBIAN"
mkdir -p "${pkg_dir}/usr/bin"
@@ -79,11 +81,11 @@ jobs:
cat > "${pkg_dir}/DEBIAN/control" << EOF
Package: sif
Version: ${VERSION}
Version: ${{ env.VERSION }}
Section: security
Priority: optional
Architecture: ${arch}
Maintainer: vmfunc <celeste@router.sex>
Maintainer: vmfunc <celeste@linux.com>
Homepage: https://github.com/vmfunc/sif
Description: Modular pentesting toolkit
sif is a fast, concurrent, and extensible pentesting toolkit written in Go.
@@ -94,43 +96,90 @@ jobs:
dpkg-deb --build "${pkg_dir}"
done
- name: Set release version
run: echo "RELEASE_VERSION=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
- name: generate checksums
run: |
sha256sum \
sif-windows-amd64.zip \
sif-windows-386.zip \
sif-macos-amd64.tar.gz \
sif-macos-arm64.tar.gz \
sif-linux-amd64.tar.gz \
sif-linux-386.tar.gz \
sif-linux-arm64.tar.gz \
sif_*.deb \
> checksums-sha256.txt
- name: Create Release and Upload Assets
- name: generate SBOM
uses: anchore/sbom-action@v0
with:
artifact-name: sbom.spdx.json
output-file: sbom.spdx.json
- name: generate changelog
id: changelog
uses: actions/github-script@v8
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@v2
with:
tag_name: automated-release-${{ env.RELEASE_VERSION }}
name: Release ${{ env.RELEASE_VERSION }}
name: sif v${{ env.VERSION }}
body: |
Automated release v${{ env.RELEASE_VERSION }}
## what's changed
## Assets
${{ steps.changelog.outputs.result }}
Each archive contains the sif binary and built-in modules.
- 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`
## Installation
## install
**homebrew / linuxbrew**
```bash
tar -xzf sif-linux-amd64.tar.gz
cd sif-linux-amd64
./sif -h
# coming soon
```
For more details, check the [commit history](https://github.com/${{ github.repository }}/commits/main).
**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
```bash
sha256sum -c checksums-sha256.txt
```
draft: false
prerelease: false
prerelease: ${{ contains(github.ref_name, '-') }}
files: |
sif-windows-amd64.zip
sif-windows-386.zip
@@ -142,10 +191,13 @@ jobs:
sif_*_amd64.deb
sif_*_i386.deb
sif_*_arm64.deb
checksums-sha256.txt
sbom.spdx.json
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Push to Cloudsmith
- name: push to cloudsmith
if: ${{ !contains(github.ref_name, '-') }}
env:
CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }}
run: |
+10 -3
View File
@@ -1,4 +1,4 @@
name: Update Report Card
name: update report card
on:
push:
@@ -7,10 +7,17 @@ on:
branches: [main]
workflow_call:
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
update-report-card:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Update Go Report Card
- uses: actions/checkout@v6
- name: update go report card
uses: creekorful/goreportcard-action@v1.0
+10 -7
View File
@@ -1,4 +1,4 @@
name: Functional Test
name: functional test
on:
push:
@@ -7,18 +7,21 @@ on:
branches: [main]
workflow_call:
permissions:
contents: read
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v4
- uses: actions/checkout@v6
- name: set up go
uses: actions/setup-go@v5
with:
go-version: "1.24"
- name: Build Sif
- name: build sif
run: make
- name: Run Sif with features
- name: run sif with features
run: |
./sif -u https://example.com -dnslist small -dirlist small -dork -git -whois -cms -framework
if [ $? -eq 0 ]; then
@@ -28,7 +31,7 @@ jobs:
exit 1
fi
- name: Test module system
- name: test module system
run: |
echo "Listing modules..."
./sif -lm
+30
View File
@@ -0,0 +1,30 @@
name: scorecard
on:
push:
branches: [main]
schedule:
- cron: "0 6 * * 1" # monday 06:00 UTC
permissions: read-all
jobs:
analysis:
runs-on: ubuntu-latest
permissions:
security-events: write
id-token: write
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- name: run scorecard
uses: ossf/scorecard-action@v2.4.3
with:
results_file: results.sarif
results_format: sarif
publish_results: true
- name: upload sarif results
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
+7 -3
View File
@@ -1,18 +1,22 @@
name: Shell Check
name: shell check
on:
pull_request:
paths:
- "**/*.sh"
permissions:
contents: read
pull-requests: write
jobs:
shellcheck:
name: runner / shellcheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: shellcheck
uses: reviewdog/action-shellcheck@v1.27.0
uses: reviewdog/action-shellcheck@v1.32.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
reporter: github-pr-review
+6 -2
View File
@@ -1,4 +1,4 @@
name: YAML Lint
name: yaml lint
on:
pull_request:
@@ -6,12 +6,16 @@ on:
- "**/*.yml"
- "**/*.yaml"
permissions:
contents: read
pull-requests: write
jobs:
yamllint:
name: runner / yamllint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: yamllint
uses: reviewdog/action-yamllint@v1.19.0
with:
+31 -4
View File
@@ -10,25 +10,46 @@ linters:
- 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
- exportloopref # loop variable capture
- gosec # security issues
- errorlint # error wrapping and comparison
- nilnil # return nil, nil
- wastedassign # assignments to variables never read
- usetesting # os.Setenv in tests instead of t.Setenv, etc.
linters-settings:
govet:
enable-all: true
disable:
- fieldalignment # too many structs to reorder, risks breaking serialization
- shadow # common Go pattern, too noisy
- unusedwrite # false positives on test data structs
errcheck:
check-blank: false
exclude-functions:
- github.com/dropalldatabases/sif/internal/logger.Write # log writes are best-effort
revive:
rules:
- name: exported
arguments: [checkPrivateReceivers]
disabled: true # stuttering names (scan.ScanResult) require breaking API changes
gocritic:
enabled-tags:
- diagnostic
- style
- performance
disabled-checks:
- commentedOutCode # too opinionated for a project with TODO comments
- paramTypeCombine # style-only, not worth churn
- unnamedResult # style-only
- unnecessaryDefer # common pattern in tests
- nestingReduce # inverting conditions in scan logic hurts readability
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
run:
timeout: 5m
@@ -36,4 +57,10 @@ run:
issues:
max-issues-per-linter: 50
max-same-issues: 3
max-same-issues: 50
exclude-rules:
# test files get some slack
- path: _test\.go
linters:
- errcheck
- noctx
+1 -1
View File
@@ -1,6 +1,6 @@
BSD 3-Clause License
Copyright (c) 2022-2025 vmfunc (vmfunc), xyzeva, lunchcat alumni,
Copyright (c) 2022-2025 vmfunc, xyzeva, lunchcat alumni,
and other sif contributors.
Redistribution and use in source and binary forms, with or without
+25
View File
@@ -8,6 +8,7 @@
[![build](https://img.shields.io/github/actions/workflow/status/vmfunc/sif/go.yml?style=flat-square)](https://github.com/vmfunc/sif/actions)
[![license](https://img.shields.io/badge/license-BSD--3--Clause-blue?style=flat-square)](LICENSE)
[![aur](https://img.shields.io/aur/version/sif?style=flat-square&logo=archlinux&logoColor=white&color=1793D1)](https://aur.archlinux.org/packages/sif)
[![nixpkgs](https://img.shields.io/badge/nixpkgs-sif-5277C3?style=flat-square&logo=nixos&logoColor=white)](https://search.nixos.org/packages?query=sif)
[![homebrew](https://img.shields.io/badge/homebrew-tap-FBB040?style=flat-square&logo=homebrew&logoColor=white)](https://github.com/vmfunc/homebrew-sif)
[![apt](https://img.shields.io/badge/apt-cloudsmith-2A5ADF?style=flat-square&logo=debian&logoColor=white)](https://cloudsmith.io/~sif/repos/deb/packages/)
[![discord](https://img.shields.io/badge/discord-join-5865F2?style=flat-square&logo=discord&logoColor=white)](https://discord.gg/sifcli)
@@ -45,6 +46,25 @@ yay -S sif
paru -S sif
```
### nix
```bash
# nixpkgs (declarative — add to configuration.nix or home-manager)
environment.systemPackages = [ pkgs.sif ];
# or imperatively
nix profile install nixpkgs#sif
# or just run it without installing
nix run nixpkgs#sif -- -u https://example.com -all
```
the repo also ships a flake if you want to build from source:
```bash
nix run github:vmfunc/sif
```
### debian/ubuntu (apt)
```bash
@@ -95,6 +115,10 @@ 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
@@ -128,6 +152,7 @@ sif has a modular architecture. modules are defined in yaml and can be extended
| `-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 |
+15
View File
@@ -0,0 +1,15 @@
# security policy
## reporting a vulnerability
if you find a security issue in sif, email celeste@linux.com directly.
don't open a public issue.
expect a response within 48 hours. if it's confirmed, i'll push a fix
and credit you in the release notes (unless you'd rather stay anonymous).
## scope
sif is a pentesting tool — "it can scan things" is not a vulnerability.
actual bugs: command injection in user input handling, path traversal in
template extraction, credential leaks, that kind of thing.
+1 -1
View File
@@ -4,7 +4,7 @@
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
: ▄█ █ █▀ · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
+293 -124
View File
@@ -1,223 +1,392 @@
module github.com/dropalldatabases/sif
go 1.24.0
go 1.24.2
require (
github.com/antchfx/htmlquery v1.3.0
github.com/charmbracelet/lipgloss v0.8.0
github.com/charmbracelet/log v0.2.4
github.com/likexian/whois v1.15.1
github.com/projectdiscovery/goflags v0.1.54
github.com/projectdiscovery/nuclei/v2 v2.9.14
github.com/projectdiscovery/ratelimit v0.0.9
github.com/projectdiscovery/utils v0.1.1
github.com/antchfx/htmlquery v1.3.5
github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834
github.com/charmbracelet/log v0.4.2
github.com/likexian/whois v1.15.7
github.com/projectdiscovery/goflags v0.1.74
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.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.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.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.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
github.com/PuerkitoBio/goquery v1.8.1 // indirect
github.com/Mzack9999/go-rsync v0.0.0-20250821180103-81ffa574ef4d // indirect
github.com/Mzack9999/goja v0.0.0-20250507184235-e46100e9c697 // indirect
github.com/Mzack9999/goja_nodejs v0.0.0-20250507184139-66bcbf65c883 // indirect
github.com/ProtonMail/go-crypto v1.1.6 // indirect
github.com/PuerkitoBio/goquery v1.11.0 // indirect
github.com/STARRY-S/zip v0.2.3 // indirect
github.com/VividCortex/ewma v1.2.0 // indirect
github.com/akrylysov/pogreb v0.10.1 // indirect
github.com/akrylysov/pogreb v0.10.2 // indirect
github.com/alecthomas/chroma v0.10.0 // indirect
github.com/alecthomas/jsonschema v0.0.0-20211022214203-8b29eab41725 // 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/andybalholm/brotli v1.0.6 // indirect
github.com/andybalholm/cascadia v1.3.2 // indirect
github.com/andygrunwald/go-jira v1.16.0 // indirect
github.com/antchfx/xmlquery v1.3.15 // indirect
github.com/antchfx/xpath v1.2.4 // indirect
github.com/alexsnet/go-vnc v0.1.0 // indirect
github.com/alitto/pond v1.9.2 // indirect
github.com/andybalholm/brotli v1.2.0 // indirect
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.5 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/aws/aws-sdk-go-v2 v1.19.0 // indirect
github.com/aws/aws-sdk-go-v2/config v1.18.28 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.13.27 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.36 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.29 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.12.13 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.13 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.19.3 // indirect
github.com/aws/smithy-go v1.13.5 // 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.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.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.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.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.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/charmbracelet/glamour v0.6.0 // indirect
github.com/cheggaaa/pb/v3 v3.1.4 // 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.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-20250327172914-2fdc97757edf // indirect
github.com/charmbracelet/x/term v0.2.1 // 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/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 // indirect
github.com/corpix/uarand v0.2.0 // 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.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
github.com/dlclark/regexp2 v1.8.1 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/ditashi/jsbeautifier-go v0.0.0-20141206144643-2520a8026a9c // indirect
github.com/djherbis/times v1.6.0 // indirect
github.com/dlclark/regexp2 v1.11.5 // indirect
github.com/docker/docker v28.3.3+incompatible // indirect
github.com/docker/go-connections v0.6.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 // indirect
github.com/dustin/go-humanize v1.0.1 // 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
github.com/fatih/structs v1.1.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/felixge/fgprof v0.9.5 // indirect
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.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
github.com/gin-gonic/gin v1.9.1 // indirect
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.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.0 // indirect
github.com/go-ole/go-ole v1.2.6 // 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-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
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.14.1 // indirect
github.com/go-rod/rod v0.114.0 // indirect
github.com/go-playground/validator/v10 v10.26.0 // indirect
github.com/go-rod/rod v0.116.2 // indirect
github.com/go-sourcemap/sourcemap v2.1.4+incompatible // indirect
github.com/go-sql-driver/mysql v1.9.3 // indirect
github.com/goburrow/cache v0.1.4 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect
github.com/gobwas/ws v1.2.1 // indirect
github.com/gobwas/ws v1.4.0 // indirect
github.com/goccy/go-json v0.10.5 // indirect
github.com/gocolly/colly/v2 v2.1.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
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 v0.0.4 // indirect
github.com/google/certificate-transparency-go v1.1.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
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/gorilla/css v1.0.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/css v1.0.1 // indirect
github.com/gosimple/slug v1.15.0 // indirect
github.com/gosimple/unidecode v1.0.1 // indirect
github.com/h2non/filetype v1.1.3 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
github.com/hashicorp/go-version v1.6.0 // 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.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
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect
github.com/itchyny/gojq v0.12.13 // indirect
github.com/itchyny/timefmt-go v0.1.5 // indirect
github.com/iangcarroll/cookiemonster v1.6.0 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/invopop/jsonschema v0.13.0 // indirect
github.com/invopop/yaml v0.3.1 // indirect
github.com/itchyny/gojq v0.12.17 // indirect
github.com/itchyny/timefmt-go v0.1.6 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jcmturner/aescts/v2 v2.0.0 // indirect
github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect
github.com/jcmturner/gofork v1.7.6 // indirect
github.com/jcmturner/gokrb5/v8 v8.4.4 // indirect
github.com/jcmturner/rpc/v2 v2.0.3 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/julienschmidt/httprouter v1.3.0 // indirect
github.com/kataras/jwt v0.1.8 // indirect
github.com/k14s/starlark-go v0.0.0-20200720175618-3a5c849cc368 // indirect
github.com/kaiakz/ubuffer v0.0.0-20200803053910-dd1083087166 // indirect
github.com/kataras/jwt v0.1.10 // indirect
github.com/kennygrant/sanitize v1.2.4 // indirect
github.com/klauspost/compress v1.17.4 // indirect
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.2.5 // indirect
github.com/klauspost/pgzip v1.2.5 // indirect
github.com/leodido/go-urn v1.2.4 // 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.10.9 // indirect
github.com/libdns/libdns v0.2.1 // indirect
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // 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-20250821153705-5981dea3221d // indirect
github.com/mackerelio/go-osstat v0.2.4 // indirect
github.com/mattn/go-colorable v0.1.13 // 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.14 // 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 v1.2.0 // indirect
github.com/mholt/archiver v3.1.1+incompatible // indirect
github.com/mholt/archiver/v3 v3.5.1 // indirect
github.com/microcosm-cc/bluemonday v1.0.25 // indirect
github.com/miekg/dns v1.1.56 // 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
github.com/miekg/dns v1.1.68 // indirect
github.com/mikelolasagasti/xz v1.0.1 // indirect
github.com/minio/minlz v1.0.1 // indirect
github.com/minio/selfupdate v0.6.1-0.20230907112617-f11e74f84ca7 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/sys/atomicwriter v0.1.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/montanaflynn/stats v0.7.1 // indirect
github.com/muesli/reflow v0.3.0 // indirect
github.com/muesli/termenv v0.15.2 // indirect
github.com/nwaples/rardecode v1.1.3 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
github.com/pierrec/lz4/v4 v4.1.2 // indirect
github.com/muesli/termenv v0.16.0 // indirect
github.com/nwaples/rardecode/v2 v2.2.2 // indirect
github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect
github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect
github.com/olekukonko/errors v1.1.0 // indirect
github.com/olekukonko/ll v0.0.9 // indirect
github.com/olekukonko/tablewriter v1.0.8 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
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.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-20210106213030-5aafc221ea8c // indirect
github.com/projectdiscovery/asnmap v1.1.0 // 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.0.9 // indirect
github.com/projectdiscovery/clistats v0.0.19 // indirect
github.com/projectdiscovery/dsl v0.0.20 // indirect
github.com/projectdiscovery/fastdialer v0.1.1 // indirect
github.com/projectdiscovery/cdncheck v1.2.20 // indirect
github.com/projectdiscovery/clistats v0.1.1 // 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.5 // indirect
github.com/projectdiscovery/gologger v1.1.12 // indirect
github.com/projectdiscovery/gostruct v0.0.1 // indirect
github.com/projectdiscovery/hmap v0.0.45 // indirect
github.com/projectdiscovery/httpx v1.3.4 // indirect
github.com/projectdiscovery/interactsh v1.2.0 // 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.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.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-20240226150047-2e2c51e35983 // indirect
github.com/projectdiscovery/mapcidr v1.1.34 // indirect
github.com/projectdiscovery/networkpolicy v0.0.8 // indirect
github.com/projectdiscovery/rawhttp v0.1.18 // 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.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.62 // indirect
github.com/projectdiscovery/retryablehttp-go v1.0.63 // 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.1.4 // indirect
github.com/projectdiscovery/yamldoc-go v1.0.4 // 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.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.1 // indirect
github.com/remeh/sizedwaitgroup v1.0.0 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
github.com/rs/xid v1.5.0 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/rs/xid v1.6.0 // indirect
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect
github.com/sashabaranov/go-openai v1.14.2 // indirect
github.com/sashabaranov/go-openai v1.37.0 // indirect
github.com/segmentio/ksuid v1.0.4 // indirect
github.com/shirou/gopsutil/v3 v3.23.7 // 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/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
github.com/skeema/knownhosts v1.3.1 // indirect
github.com/sorairolake/lzip-go v0.3.8 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/cast v1.5.1 // indirect
github.com/stretchr/testify v1.11.1 // indirect
github.com/spf13/afero v1.15.0 // indirect
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.6.0 // indirect
github.com/tidwall/buntdb v1.3.0 // indirect
github.com/tidwall/gjson v1.14.4 // 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.1.1 // indirect
github.com/tidwall/match v1.2.0 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tidwall/rtred v0.1.2 // indirect
github.com/tidwall/tinyqueue v0.1.1 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/tim-ywliu/nested-logrus-formatter v1.3.2 // 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
github.com/ugorji/go/codec v1.2.11 // indirect
github.com/ulikunitz/xz v0.5.15 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/weppos/publicsuffix-go v0.30.1-0.20230422193905-8fecedd899db // indirect
github.com/xanzy/go-gitlab v0.84.0 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
github.com/yl2chen/cidranger v1.0.2 // indirect
github.com/vmihailenco/bufpool v0.1.11 // indirect
github.com/vmihailenco/msgpack/v5 v5.3.4 // indirect
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-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
github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
github.com/yassinebenaid/godump v0.11.1 // indirect
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
github.com/ysmood/fetchup v0.2.3 // indirect
github.com/ysmood/goob v0.4.0 // indirect
github.com/ysmood/got v0.34.1 // indirect
github.com/ysmood/got v0.40.0 // indirect
github.com/ysmood/gson v0.7.3 // indirect
github.com/ysmood/leakless v0.8.0 // indirect
github.com/yuin/goldmark v1.5.4 // indirect
github.com/yuin/goldmark-emoji v1.0.1 // indirect
github.com/ysmood/leakless v0.9.0 // indirect
github.com/yuin/goldmark v1.7.13 // indirect
github.com/yuin/goldmark-emoji v1.0.5 // indirect
github.com/yusufpapurcu/wmi v1.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-20230422215203-9a665e1e9968 // indirect
go.etcd.io/bbolt v1.3.7 // 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.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.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.25.0 // indirect
go.uber.org/zap v1.27.0 // indirect
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
goftp.io/server/v2 v2.0.1 // indirect
golang.org/x/crypto v0.46.0 // indirect
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
golang.org/x/mod v0.30.0 // indirect
golang.org/x/net v0.48.0 // indirect
golang.org/x/arch v0.3.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.19.0 // indirect
golang.org/x/sys v0.39.0 // indirect
golang.org/x/term v0.38.0 // indirect
golang.org/x/text v0.32.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.39.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.40.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.33.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect
gopkg.in/corvus-ch/zbase32.v1 v1.0.0 // indirect
gopkg.in/djherbis/times.v1 v1.3.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
mellium.im/sasl v0.3.2 // indirect
moul.io/http2curl v1.0.0 // indirect
)
+1154 -280
View File
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -42,6 +42,7 @@ type Settings struct {
CloudStorage bool
SubdomainTakeover bool
Shodan bool
SecurityTrails bool
SQL bool
LFI bool
Framework bool
@@ -92,6 +93,7 @@ func Parse() *Settings {
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"),
+1 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
+3 -3
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 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, 0755); err != nil {
if err := os.Mkdir(dir, 0o755); 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, 0666)
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o666)
if err != nil {
return nil, err
}
+1 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
+6 -7
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 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 _, m := range matchers {
matched := checkMatcher(m, resp, body)
if m.Negative {
for i := range matchers {
matched := checkMatcher(&matchers[i], resp, body)
if matchers[i].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,8 +352,7 @@ func runExtractors(extractors []Extractor, resp *http.Response, body string) map
for _, e := range extractors {
part := getPart(e.Part, resp, body)
switch e.Type {
case "regex":
if e.Type == "regex" {
for _, pattern := range e.Regex {
re, err := regexp.Compile(pattern)
if err != nil {
+1 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
+1 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
+1 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
+2 -2
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -16,7 +16,7 @@
: SIF - Blazing-fast pentesting suite :
: Blaze - BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
-------------------------------------------------------------------------------------------------
+3 -5
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -13,10 +13,8 @@
package format
import (
"fmt"
"github.com/dropalldatabases/sif/internal/styles"
"github.com/projectdiscovery/nuclei/v2/pkg/output"
"github.com/projectdiscovery/nuclei/v3/pkg/output"
)
func FormatLine(event *output.ResultEvent) string {
@@ -29,7 +27,7 @@ func FormatLine(event *output.ResultEvent) string {
}
output += " [" + event.Type + "]"
output += " [" + formatSeverity(fmt.Sprintf("%s", event.Info.SeverityHolder.Severity)) + "]"
output += " [" + formatSeverity(event.Info.SeverityHolder.Severity.String()) + "]"
return output
}
+11 -5
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -15,6 +15,7 @@ package templates
import (
"archive/tar"
"compress/gzip"
"context"
"errors"
"fmt"
"io"
@@ -37,7 +38,12 @@ func Install(logger *log.Logger) error {
logger.Infof("nuclei-templates directory not found. Installing...")
resp, err := http.Get(fmt.Sprintf(archive, ref))
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)
if err != nil {
return err
}
@@ -53,7 +59,7 @@ func Install(logger *log.Logger) error {
for {
header, err := data.Next()
if errors.Is(io.EOF, err) {
if errors.Is(err, io.EOF) {
break
}
if err != nil {
@@ -62,7 +68,7 @@ func Install(logger *log.Logger) error {
switch header.Typeflag {
case tar.TypeDir:
if err := os.Mkdir(header.Name, 0755); err != nil {
if err := os.Mkdir(header.Name, 0o755); err != nil {
return err
}
case tar.TypeReg:
@@ -77,7 +83,7 @@ func Install(logger *log.Logger) error {
}
}
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
}
+1 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
+5 -4
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -138,11 +138,12 @@ func (p *Progress) render() {
bar := ""
for i := 0; i < progressWidth; i++ {
if i < filled {
switch {
case i < filled:
bar += progressFilled
} else if i == filled && current < total {
case i == filled && current < total:
bar += progressCurrent
} else {
default:
bar += progressEmpty
}
}
+1 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
+1 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
+1 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
+3 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -17,7 +17,9 @@ import "github.com/dropalldatabases/sif/internal/modules"
// Register registers all Go-based built-in scans as modules.
// Allows complex Go scans to participate in the module system
func Register() {
modules.Register(&ShodanModule{})
modules.Register(&FrameworksModule{})
modules.Register(&NucleiModule{})
modules.Register(&WhoisModule{})
modules.Register(&SecurityTrailsModule{})
}
@@ -0,0 +1,79 @@
/*
··
: :
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 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
}
+157
View File
@@ -0,0 +1,157 @@
/*
··
: :
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
*/
package builtin
import (
"context"
"fmt"
"github.com/dropalldatabases/sif/internal/modules"
"github.com/dropalldatabases/sif/internal/scan"
"strings"
)
type ShodanModule struct{}
func (m *ShodanModule) Info() modules.Info {
return modules.Info{
ID: "shodan-lookup",
Name: "Shodan Host Intelligence",
Author: "sif",
Severity: "info",
Description: "Queries Shodan API for host information, open ports, and vulnerabilities (requires SHODAN_API_KEY)",
Tags: []string{"recon", "osint", "shodan", "vulns"},
}
}
func (m *ShodanModule) Type() modules.ModuleType {
return modules.TypeScript
}
func (m *ShodanModule) Execute(ctx context.Context, target string, opts modules.Options) (*modules.Result, error) {
// Call existing legacy scan.Shodan function
shodanResult, err := scan.Shodan(target, opts.Timeout, opts.LogDir)
if err != nil {
return nil, err
}
result := &modules.Result{
ModuleID: m.Info().ID,
Target: target,
Findings: []modules.Finding{},
}
// If nothing returned, return empty result
if shodanResult == nil || shodanResult.IP == "" {
return result, nil
}
// Create main finding
evidence := fmt.Sprintf("Shodan data found for %s", shodanResult.IP)
severity := "info"
if len(shodanResult.Vulns) > 0 {
severity = "high"
evidence = fmt.Sprintf("Host %s has %d known vulnerabilities", shodanResult.IP, len(shodanResult.Vulns))
}
finding := modules.Finding{
URL: target,
Severity: severity,
Evidence: evidence,
Extracted: map[string]string{
"ip": shodanResult.IP,
},
}
// Add hostnames
if len(shodanResult.Hostnames) > 0 {
finding.Extracted["hostnames"] = strings.Join(shodanResult.Hostnames, ", ")
}
// Add organization info
if shodanResult.Organization != "" {
finding.Extracted["organization"] = shodanResult.Organization
}
// Add ISP info
if shodanResult.ISP != "" {
finding.Extracted["isp"] = shodanResult.ISP
}
// Add ASN
if shodanResult.ASN != "" {
finding.Extracted["asn"] = shodanResult.ASN
}
// Add location
if shodanResult.Country != "" {
location := shodanResult.Country
if shodanResult.City != "" {
location = shodanResult.City + ", " + shodanResult.Country
}
finding.Extracted["location"] = location
}
// Add OS
if shodanResult.OS != "" {
finding.Extracted["os"] = shodanResult.OS
}
// Add open ports
if len(shodanResult.Ports) > 0 {
portStrs := make([]string, len(shodanResult.Ports))
for i, port := range shodanResult.Ports {
portStrs[i] = fmt.Sprintf("%d", port)
}
finding.Extracted["open_ports"] = strings.Join(portStrs, ", ")
finding.Extracted["port_count"] = fmt.Sprintf("%d", len(shodanResult.Ports))
}
// Add vulnerabilities
if len(shodanResult.Vulns) > 0 {
finding.Extracted["vulnerabilities"] = strings.Join(shodanResult.Vulns, ", ")
finding.Extracted["vuln_count"] = fmt.Sprintf("%d", len(shodanResult.Vulns))
}
// Add last update
if shodanResult.LastUpdate != "" {
finding.Extracted["last_update"] = shodanResult.LastUpdate
}
// Add service count
if len(shodanResult.Services) > 0 {
finding.Extracted["service_count"] = fmt.Sprintf("%d", len(shodanResult.Services))
// Add service details
serviceDetails := make([]string, 0, len(shodanResult.Services))
for _, service := range shodanResult.Services {
detail := fmt.Sprintf("%d/%s", service.Port, service.Protocol)
if service.Product != "" {
detail += " " + service.Product
if service.Version != "" {
detail += " " + service.Version
}
}
serviceDetails = append(serviceDetails, detail)
}
finding.Extracted["services"] = strings.Join(serviceDetails, "; ")
}
result.Findings = append(result.Findings, finding)
return result, nil
}
+1 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
+12 -10
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -13,6 +13,7 @@
package scan
import (
"context"
"fmt"
"net/http"
"os"
@@ -54,7 +55,7 @@ func CloudStorage(url string, timeout time.Duration, logdir string) ([]CloudStor
var results []CloudStorageResult
for _, bucket := range potentialBuckets {
isPublic, err := checkS3Bucket(bucket, client)
isPublic, err := checkS3Bucket(context.TODO(), bucket, client)
if err != nil {
cloudlog.Errorf("Error checking S3 bucket %s: %v", bucket, err)
continue
@@ -69,7 +70,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)
@@ -85,22 +86,23 @@ func extractPotentialBuckets(url string) []string {
parts := strings.Split(url, ".")
var buckets []string
for i, part := range parts {
buckets = append(buckets, part)
buckets = append(buckets, part+"-s3")
buckets = append(buckets, "s3-"+part)
buckets = append(buckets, part, part+"-s3", "s3-"+part)
if i < len(parts)-1 {
domainExtension := part + "-" + parts[i+1]
buckets = append(buckets, domainExtension)
buckets = append(buckets, parts[i+1]+"-"+part)
buckets = append(buckets, domainExtension, parts[i+1]+"-"+part)
}
}
return buckets
}
func checkS3Bucket(bucket string, client *http.Client) (bool, error) {
func checkS3Bucket(ctx context.Context, bucket string, client *http.Client) (bool, error) {
url := fmt.Sprintf("https://%s.s3.amazonaws.com", bucket)
resp, err := client.Get(url)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, http.NoBody)
if err != nil {
return false, err
}
resp, err := client.Do(req)
if err != nil {
return false, err
}
+15 -4
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -13,6 +13,7 @@
package scan
import (
"context"
"io"
"net/http"
"strings"
@@ -48,7 +49,13 @@ func CMS(url string, timeout time.Duration, logdir string) (*CMSResult, error) {
Timeout: timeout,
}
resp, err := client.Get(url)
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, url, http.NoBody)
if err != nil {
spin.Stop()
return nil, err
}
resp, err := client.Do(req)
if err != nil {
spin.Stop()
return nil, err
@@ -92,7 +99,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
return nil, nil //nolint:nilnil // no CMS found is not an error
}
func detectWordPress(url string, client *http.Client, bodyString string) bool {
@@ -118,7 +125,11 @@ func detectWordPress(url string, client *http.Client, bodyString string) bool {
}
for _, file := range wpFiles {
resp, err := client.Get(url + file)
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, url+file, http.NoBody)
if err != nil {
continue
}
resp, err := client.Do(req)
if err == nil {
found := resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusFound
resp.Body.Close()
+16 -4
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -14,6 +14,7 @@ package scan
import (
"bufio"
"context"
"fmt"
"net/http"
"strconv"
@@ -62,7 +63,12 @@ func Dirlist(size string, url string, timeout time.Duration, threads int, logdir
list = directoryURL + bigFile
}
resp, err := http.Get(list)
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)
if err != nil {
log.Error("Error downloading directory list: %s", err)
return nil, err
@@ -99,7 +105,12 @@ func Dirlist(size string, url string, timeout time.Duration, threads int, logdir
progress.Increment(directory)
charmlog.Debugf("%s", directory)
resp, err := client.Get(url + "/" + 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)
if err != nil {
charmlog.Debugf("Error %s: %s", directory, err)
continue
@@ -111,7 +122,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{
@@ -122,6 +133,7 @@ func Dirlist(size string, url string, timeout time.Duration, threads int, logdir
results = append(results, result)
mu.Unlock()
}
resp.Body.Close()
}
}(thread)
}
+23 -5
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -14,6 +14,7 @@ package scan
import (
"bufio"
"context"
"fmt"
"net/http"
"strings"
@@ -47,7 +48,12 @@ func Dnslist(size string, url string, timeout time.Duration, threads int, logdir
list = dnsURL + dnsBigFile
}
resp, err := http.Get(list)
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)
if err != nil {
log.Error("Error downloading DNS list: %s", err)
return nil, err
@@ -95,13 +101,19 @@ func Dnslist(size string, url string, timeout time.Duration, threads int, logdir
charmlog.Debugf("Looking up: %s", domain)
// Check HTTP
resp, err := client.Get("http://" + domain + "." + sanitizedURL)
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)
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)
@@ -113,20 +125,26 @@ func Dnslist(size string, url string, timeout time.Duration, threads int, logdir
}
// Check HTTPS
resp, err = client.Get("https://" + domain + "." + sanitizedURL)
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)
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))
}
}
}
+12 -4
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -17,6 +17,7 @@ package scan
import (
"bufio"
"context"
"fmt"
"net/http"
"strconv"
@@ -69,7 +70,14 @@ func Dork(url string, timeout time.Duration, threads int, logdir string) ([]Dork
}
}
resp, err := http.Get(dorkURL + dorkFile)
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)
if err != nil {
spin.Stop()
output.Error("Error downloading dork list: %s", err)
@@ -98,7 +106,7 @@ func Dork(url string, timeout time.Duration, threads int, logdir string) ([]Dork
continue
}
results, err := googlesearch.Search(nil, fmt.Sprintf("%s %s", dork, sanitizedURL))
results, err := googlesearch.Search(context.TODO(), fmt.Sprintf("%s %s", dork, sanitizedURL))
if err != nil {
log.Debugf("error searching for dork %s: %v", dork, err)
continue
@@ -108,7 +116,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{
+1 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
+11 -5
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -13,6 +13,7 @@
package frameworks
import (
"context"
"fmt"
"io"
"net/http"
@@ -47,7 +48,12 @@ func DetectFramework(url string, timeout time.Duration, logdir string) (*Framewo
client := &http.Client{Timeout: timeout}
resp, err := client.Get(url)
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
if err != nil {
spin.Stop()
return nil, err
@@ -66,7 +72,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
return nil, nil //nolint:nilnil // no detectors registered is not an error
}
// Run all detectors concurrently
@@ -105,7 +111,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
return nil, nil //nolint:nilnil // no framework detected is not an error
}
// Get version match details
@@ -124,7 +130,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)",
+1 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
+1 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
+1 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
+1 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
+46
View File
@@ -0,0 +1,46 @@
/*
··
: :
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
*/
package frameworks
import "testing"
func FuzzIsValidVersionString(f *testing.F) {
f.Add("1.0")
f.Add("1.0.0")
f.Add("10.2.3.4")
f.Add("999.999.999")
f.Add("")
f.Add("abc")
f.Add("1.")
f.Add(".1")
f.Add("1.2.3.4.5")
f.Add("aaaaaaaaaaaaaaaaaaaaaaaaa")
f.Fuzz(func(t *testing.T, v string) {
// should never panic
isValidVersionString(v)
})
}
func FuzzExtractVersionOptimized(f *testing.F) {
f.Add("<meta name=\"generator\" content=\"WordPress 6.4.2\">", "WordPress")
f.Add("Laravel v10.0.1", "Laravel")
f.Add("<html>nothing</html>", "Django")
f.Add("", "unknown")
f.Add("X-Powered-By: Express/4.18.2", "Express")
f.Fuzz(func(t *testing.T, body string, framework string) {
// should never panic
ExtractVersionOptimized(body, framework)
})
}
+1 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
+2 -2
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 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 len(v) == 0 || len(v) > 20 {
if v == "" || len(v) > 20 {
return false
}
+63
View File
@@ -0,0 +1,63 @@
/*
··
: :
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
*/
package scan
import "testing"
func FuzzDetectLFIFromResponse(f *testing.F) {
f.Add("root:x:0:0:root:/root:/bin/bash")
f.Add("<html><body>Hello World</body></html>")
f.Add("[boot loader]\ntimeout=30")
f.Add("DOCUMENT_ROOT=/var/www/html")
f.Add("<?php echo 'hello'; ?>")
f.Add("127.0.0.1 localhost")
f.Add("")
f.Add("PD9waHAgZWNobyAnaGVsbG8nOyA/Pg==")
f.Fuzz(func(t *testing.T, body string) {
// should never panic
DetectLFIFromResponse(body)
})
}
func FuzzIsAdminPanel(f *testing.F) {
f.Add("<html>phpMyAdmin</html>", "phpMyAdmin")
f.Add("<html>adminer</html>", "Adminer")
f.Add("<html>pgadmin</html>", "pgAdmin")
f.Add("<html>nothing here</html>", "phpMyAdmin")
f.Add("", "unknown")
f.Add("<html>database query mysql</html>", "generic")
f.Fuzz(func(t *testing.T, body string, panelType string) {
// should never panic
isAdminPanel(body, panelType)
})
}
func FuzzDatabaseErrorPatterns(f *testing.F) {
f.Add("you have an error in your sql syntax")
f.Add("Warning: mysql_fetch_array()")
f.Add("postgresql error at character 42")
f.Add("ORA-12345: some oracle error")
f.Add("sqlite3_prepare_v2 failed")
f.Add("document bson error in mongodb")
f.Add("<html>normal page</html>")
f.Add("")
f.Fuzz(func(t *testing.T, body string) {
// should never panic on any input
for _, pattern := range databaseErrorPatterns {
pattern.pattern.MatchString(body)
}
})
}
+17 -3
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -14,6 +14,7 @@ package scan
import (
"bufio"
"context"
"net/http"
"strconv"
"strings"
@@ -47,7 +48,13 @@ func Git(url string, timeout time.Duration, threads int, logdir string) ([]strin
}
}
resp, err := http.Get(gitURL + gitFile)
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)
if err != nil {
spin.Stop()
log.Error("Error downloading git list: %s", err)
@@ -80,9 +87,15 @@ func Git(url string, timeout time.Duration, threads int, logdir string) ([]strin
}
charmlog.Debugf("%s", repourl)
resp, err := client.Get(url + "/" + 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)
if err != nil {
charmlog.Debugf("Error %s: %s", repourl, err)
continue
}
if resp.StatusCode == 200 && !strings.HasPrefix(resp.Header.Get("Content-Type"), "text/html") {
@@ -95,6 +108,7 @@ func Git(url string, timeout time.Duration, threads int, logdir string) ([]strin
foundUrls = append(foundUrls, resp.Request.URL.String())
}
resp.Body.Close()
}
}(thread)
}
+7 -2
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -13,6 +13,7 @@
package scan
import (
"context"
"net/http"
"strings"
"time"
@@ -43,7 +44,11 @@ func Headers(url string, timeout time.Duration, logdir string) ([]HeaderResult,
Timeout: timeout,
}
resp, err := client.Get(url)
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
}
+9 -2
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -24,6 +24,7 @@ package frameworks
import (
"bufio"
"context"
"fmt"
"net/http"
"regexp"
@@ -41,7 +42,13 @@ func GetPagesRouterScripts(scriptUrl string) ([]string, error) {
return nil, err
}
resp, err := http.Get(scriptUrl)
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)
if err != nil {
fmt.Println(err)
return nil, err
+14 -3
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -14,6 +14,7 @@ package js
import (
"bufio"
"context"
"io"
"net/http"
"slices"
@@ -47,7 +48,12 @@ func JavascriptScan(url string, timeout time.Duration, threads int, logdir strin
spin.Stop()
return nil, err
}
resp, err := http.Get(url)
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)
if err != nil {
spin.Stop()
return nil, err
@@ -109,7 +115,12 @@ 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)
resp, err := http.Get(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)
if err != nil {
charmlog.Warnf("Failed to fetch script: %s", err)
continue
+7 -6
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -16,6 +16,7 @@ package js
import (
"bytes"
"context"
"encoding/base64"
"encoding/json"
"errors"
@@ -70,7 +71,7 @@ type supabaseOpenAPIResponse struct {
// getSupabaseArrayResponse fetches a Supabase endpoint that returns an array.
func getSupabaseArrayResponse(projectId, path, apikey string, auth *string) (*supabaseArrayResponse, error) {
body, resp, err := doSupabaseRequest(projectId, path, apikey, auth)
body, resp, err := doSupabaseRequest(projectId, path, apikey, auth) //nolint:bodyclose // closed in doSupabaseRequest
if err != nil {
return nil, err
}
@@ -95,7 +96,7 @@ func getSupabaseArrayResponse(projectId, path, apikey string, auth *string) (*su
// getSupabaseOpenAPI fetches the OpenAPI spec from Supabase.
func getSupabaseOpenAPI(projectId, apikey string, auth *string) (*supabaseOpenAPIResponse, error) {
body, _, err := doSupabaseRequest(projectId, "/rest/v1/", apikey, auth)
body, _, err := doSupabaseRequest(projectId, "/rest/v1/", apikey, auth) //nolint:bodyclose // closed in doSupabaseRequest
if err != nil {
return nil, err
}
@@ -111,7 +112,7 @@ func getSupabaseOpenAPI(projectId, apikey string, auth *string) (*supabaseOpenAP
func doSupabaseRequest(projectId, path, apikey string, auth *string) ([]byte, *http.Response, error) {
client := http.Client{}
req, err := http.NewRequest("GET", "https://"+projectId+".supabase.co"+path, nil)
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, "https://"+projectId+".supabase.co"+path, http.NoBody)
if err != nil {
return nil, nil, err
}
@@ -170,7 +171,7 @@ func ScanSupabase(jsContent string, jsUrl string) ([]supabaseScanResult, error)
supabaselog.Debugf("JWT body: %s", decoded)
var supabaseJwt *supabaseJwtBody
err = json.Unmarshal([]byte(decoded), &supabaseJwt)
err = json.Unmarshal(decoded, &supabaseJwt)
if err != nil {
supabaselog.Debugf("Failed to json parse JWT %s: %s", jwt, err)
continue
@@ -183,7 +184,7 @@ func ScanSupabase(jsContent string, jsUrl string) ([]supabaseScanResult, error)
supabaselog.Infof("Found valid supabase project %s with role %s", *supabaseJwt.ProjectId, *supabaseJwt.Role)
client := http.Client{}
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"}`))
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"}`))
if err != nil {
supabaselog.Errorf("Error while creating HTTP req for creating user: %s", err)
continue
+9 -3
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -13,6 +13,7 @@
package scan
import (
"context"
"fmt"
"io"
"net/http"
@@ -214,7 +215,12 @@ func LFI(targetURL string, timeout time.Duration, threads int, logdir string) (*
parsedURL.Path,
testParams.Encode())
resp, err := client.Get(testURL)
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)
if err != nil {
charmlog.Debugf("Error testing %s: %v", testURL, err)
continue
@@ -294,7 +300,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
return nil, nil //nolint:nilnil // no LFI found is not an error
}
return result, nil
+1 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
+43 -99
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -14,33 +14,17 @@ package scan
import (
"context"
"fmt"
"os"
"strings"
"sync"
"time"
"github.com/charmbracelet/log"
"github.com/dropalldatabases/sif/internal/nuclei/format"
"github.com/dropalldatabases/sif/internal/nuclei/templates"
sifoutput "github.com/dropalldatabases/sif/internal/output"
"github.com/logrusorgru/aurora"
"github.com/projectdiscovery/nuclei/v2/pkg/catalog/config"
"github.com/projectdiscovery/nuclei/v2/pkg/catalog/disk"
"github.com/projectdiscovery/nuclei/v2/pkg/catalog/loader"
"github.com/projectdiscovery/nuclei/v2/pkg/core"
"github.com/projectdiscovery/nuclei/v2/pkg/core/inputs"
"github.com/projectdiscovery/nuclei/v2/pkg/output"
"github.com/projectdiscovery/nuclei/v2/pkg/parsers"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/contextargs"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/hosterrorscache"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/interactsh"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolinit"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolstate"
"github.com/projectdiscovery/nuclei/v2/pkg/reporting"
"github.com/projectdiscovery/nuclei/v2/pkg/testutils"
"github.com/projectdiscovery/nuclei/v2/pkg/types"
"github.com/projectdiscovery/ratelimit"
nuclei "github.com/projectdiscovery/nuclei/v3/lib"
"github.com/projectdiscovery/nuclei/v3/pkg/output"
)
func Nuclei(url string, timeout time.Duration, threads int, logdir string) ([]output.ResultEvent, error) {
@@ -49,99 +33,59 @@ func Nuclei(url string, timeout time.Duration, threads int, logdir string) ([]ou
spin := sifoutput.NewSpinner("Running nuclei templates")
spin.Start()
sanitizedURL := strings.Split(url, "://")[1]
nucleilog := log.NewWithOptions(os.Stderr, log.Options{
Prefix: "nuclei",
}).With("url", url)
// Apply threads, timeout, log settings
options := types.DefaultOptions()
options.TemplateThreads = threads
options.Timeout = int(timeout.Seconds())
if logdir != "" {
options.ProjectPath = logdir
}
options.Headless = false
// Get templates
templates.Install(nucleilog)
_ = templates.Install(nucleilog)
pwd, err := os.Getwd()
if err != nil {
return nil, fmt.Errorf("failed to get working directory: %w", err)
spin.Stop()
return nil, err
}
config.DefaultConfig.SetTemplatesDir(pwd)
catalog := disk.NewCatalog(pwd)
results := []output.ResultEvent{}
// Custom output
outputWriter := testutils.NewMockOutputWriter()
outputWriter.WriteCallback = func(event *output.ResultEvent) {
ctx := context.Background()
ne, err := nuclei.NewNucleiEngineCtx(ctx,
nuclei.WithTemplatesOrWorkflows(nuclei.TemplateSources{
Templates: []string{pwd + "/nuclei-templates"},
}),
nuclei.WithConcurrency(nuclei.Concurrency{
TemplateConcurrency: threads,
HostConcurrency: 1,
HeadlessHostConcurrency: 1,
HeadlessTemplateConcurrency: 1,
JavascriptTemplateConcurrency: 1,
TemplatePayloadConcurrency: 25,
ProbeConcurrency: 50,
}),
nuclei.WithNetworkConfig(nuclei.NetworkConfig{
Timeout: int(timeout.Seconds()),
}),
nuclei.DisableUpdateCheck(),
)
if err != nil {
spin.Stop()
return nil, err
}
defer ne.Close()
sanitizedURL := strings.Split(url, "://")[1]
ne.LoadTargets([]string{sanitizedURL}, false)
var results []output.ResultEvent
var mu sync.Mutex
err = ne.ExecuteCallbackWithCtx(ctx, func(event *output.ResultEvent) {
if event.Matched != "" {
nucleilog.Infof("%s", format.FormatLine(event))
mu.Lock()
results = append(results, *event)
// TODO: metasploit
mu.Unlock()
}
}
cache := hosterrorscache.New(30, hosterrorscache.DefaultMaxHostsCount, nil)
defer cache.Close()
progressClient := &testutils.MockProgressClient{}
reportingClient, err := reporting.New(&reporting.Options{}, "")
if err != nil {
return nil, fmt.Errorf("failed to create reporting client: %w", err)
}
defer reportingClient.Close()
interactOpts := interactsh.DefaultOptions(outputWriter, reportingClient, progressClient)
interactClient, err := interactsh.New(interactOpts)
if err != nil {
return nil, err
}
defer interactClient.Close()
protocolstate.Init(options)
protocolinit.Init(options)
executorOpts := protocols.ExecutorOptions{
Colorizer: aurora.NewAurora(false),
Output: outputWriter,
Progress: progressClient,
Catalog: catalog,
Options: options,
IssuesClient: reportingClient,
RateLimiter: ratelimit.New(context.Background(), 150, time.Second),
Interactsh: interactClient,
HostErrorsCache: cache,
ResumeCfg: types.NewResumeCfg(),
}
engine := core.New(options)
engine.SetExecuterOptions(executorOpts)
workflowLoader, err := parsers.NewLoader(&executorOpts)
if err != nil {
return nil, err
}
executorOpts.WorkflowLoader = workflowLoader
store, err := loader.New(loader.NewConfig(options, catalog, executorOpts))
if err != nil {
return nil, err
}
store.Load()
inputArgs := []*contextargs.MetaInput{{Input: sanitizedURL}}
input := &inputs.SimpleInputProvider{Inputs: inputArgs}
_ = engine.Execute(store.Templates(), input)
engine.WorkPool().Wait()
})
spin.Stop()
sifoutput.ScanComplete("nuclei template scanning", len(results), "found")
return results, nil
return results, err
}
+8 -2
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -14,6 +14,7 @@ package scan
import (
"bufio"
"context"
"fmt"
"net"
"net/http"
@@ -44,7 +45,12 @@ func Ports(scope string, url string, timeout time.Duration, threads int, logdir
var ports []int
switch scope {
case "common":
resp, err := http.Get(commonPorts)
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)
if err != nil {
log.Error("Error downloading ports list: %s", err)
return nil, err
+7 -5
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -31,10 +31,11 @@ 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 *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" }
// ResultType implementations for slice result types.
@@ -50,6 +51,7 @@ var (
_ ScanResult = (*SQLResult)(nil)
_ ScanResult = (*LFIResult)(nil)
_ ScanResult = (*CMSResult)(nil)
_ ScanResult = (*SecurityTrailsResult)(nil)
_ ScanResult = HeaderResults(nil)
_ ScanResult = DirectoryResults(nil)
_ ScanResult = CloudStorageResults(nil)
+14 -3
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -19,6 +19,7 @@ package scan
import (
"bufio"
"context"
"net/http"
"strconv"
"strings"
@@ -31,7 +32,12 @@ import (
)
func fetchRobotsTXT(url string, client *http.Client) *http.Response {
resp, err := client.Get(url)
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)
if err != nil {
log.Debugf("Error fetching robots.txt: %s", err)
return nil
@@ -110,7 +116,12 @@ func Scan(url string, timeout time.Duration, threads int, logdir string) {
_, sanitizedRobot, _ := strings.Cut(robot, ": ")
log.Debugf("%s", robot)
resp, err := client.Get(url + "/" + sanitizedRobot)
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)
if err != nil {
log.Debugf("Error %s: %s", sanitizedRobot, err)
continue
+253
View File
@@ -0,0 +1,253 @@
/*
··
: :
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 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 := strings.Split(targetURL, "://")[1]
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())
}
+208
View File
@@ -0,0 +1,208 @@
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)
}
}
+14 -9
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -13,6 +13,7 @@
package scan
import (
"context"
"encoding/json"
"fmt"
"io"
@@ -182,7 +183,11 @@ 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)
resp, err := client.Get(reqURL)
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)
if err != nil {
return nil, fmt.Errorf("failed to query Shodan: %w", err)
}
@@ -232,14 +237,14 @@ func queryShodanHost(ip string, apiKey string, timeout time.Duration) (*ShodanRe
Services: make([]ShodanService, 0, len(shodanResp.Data)),
}
for _, data := range shodanResp.Data {
for i := range shodanResp.Data {
service := ShodanService{
Port: data.Port,
Protocol: data.Transport,
Product: data.Product,
Version: data.Version,
Banner: truncateBanner(data.Data, 200),
Module: data.Shodan.Module,
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,
}
result.Services = append(result.Services, service)
}
+1 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
+14 -4
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -13,6 +13,7 @@
package scan
import (
"context"
"io"
"net/http"
"regexp"
@@ -164,7 +165,12 @@ func SQL(targetURL string, timeout time.Duration, threads int, logdir string) (*
adminPath := sqlAdminPaths[idx]
checkURL := strings.TrimSuffix(targetURL, "/") + adminPath.path
resp, err := client.Get(checkURL)
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)
if err != nil {
charmlog.Debugf("Error checking %s: %v", checkURL, err)
continue
@@ -243,7 +249,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
return nil, nil //nolint:nilnil // no SQLi found is not an error
}
log.Complete(totalFindings, "found")
@@ -285,7 +291,11 @@ 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) {
resp, err := client.Get(checkURL)
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, checkURL, http.NoBody)
if err != nil {
return
}
resp, err := client.Do(req)
if err != nil {
return
}
+1 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
+11 -5
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -13,10 +13,8 @@
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"
@@ -24,6 +22,10 @@ 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.
@@ -114,7 +116,11 @@ func SubdomainTakeover(url string, dnsResults []string, timeout time.Duration, t
}
func checkSubdomainTakeover(subdomain string, client *http.Client) (bool, string) {
resp, err := client.Get("http://" + subdomain)
req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, "http://"+subdomain, http.NoBody)
if err != nil {
return false, ""
}
resp, err := client.Do(req)
if err != nil {
if strings.Contains(err.Error(), "no such host") {
// Check if CNAME exists
+1 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
+1 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
+1 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
+1 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
+55 -8
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··
@@ -86,9 +86,10 @@ func New(settings *config.Settings) (*App, error) {
return app, nil
}
if len(settings.URLs) > 0 {
switch {
case len(settings.URLs) > 0:
app.targets = settings.URLs
} else if settings.File != "" {
case settings.File != "":
if _, err := os.Stat(settings.File); err != nil {
return nil, err
}
@@ -104,7 +105,7 @@ func New(settings *config.Settings) (*App, error) {
for scanner.Scan() {
app.targets = append(app.targets, scanner.Text())
}
} else {
default:
return nil, fmt.Errorf("target(s) must be supplied with -u or -f\n\nSee 'sif -h' for more information")
}
@@ -168,6 +169,15 @@ func (app *App) Run() error {
defer logger.Close()
}
// target expansion - securitytrails discovers new domains before scanning
if app.settings.SecurityTrails {
expanded := app.expandTargets()
if len(expanded) > 0 {
output.Info("SecurityTrails discovered %d additional targets", len(expanded))
app.targets = append(app.targets, expanded...)
}
}
scansRun := make([]string, 0, 16)
for _, url := range app.targets {
@@ -362,13 +372,14 @@ func (app *App) Run() error {
// Determine which modules to run
var toRun []modules.Module
if app.settings.AllModules {
switch {
case app.settings.AllModules:
toRun = modules.All()
} else if app.settings.ModuleTags != "" {
case app.settings.ModuleTags != "":
for _, tag := range strings.Split(app.settings.ModuleTags, ",") {
toRun = append(toRun, modules.ByTag(strings.TrimSpace(tag))...)
}
} else if app.settings.Modules != "" {
case app.settings.Modules != "":
for _, id := range strings.Split(app.settings.Modules, ",") {
if m, ok := modules.Get(strings.TrimSpace(id)); ok {
toRun = append(toRun, m)
@@ -411,7 +422,8 @@ func (app *App) Run() error {
marshalled, err := json.Marshal(result)
if err != nil {
log.Fatalf("failed to marshal result: %s", err)
log.Errorf("failed to marshal result: %s", err)
continue
}
fmt.Println(string(marshalled))
}
@@ -423,3 +435,38 @@ func (app *App) Run() error {
return nil
}
// expandTargets queries SecurityTrails for each original target and returns
// newly discovered domains (subdomains + associated) for target expansion
func (app *App) expandTargets() []string {
seen := make(map[string]struct{})
for _, t := range app.targets {
seen[t] = struct{}{}
}
// snapshot original targets - don't expand discovered ones
originals := make([]string, len(app.targets))
copy(originals, app.targets)
var expanded []string
for _, url := range originals {
result, err := scan.SecurityTrails(url, app.settings.Timeout, app.settings.LogDir)
if err != nil {
log.Errorf("SecurityTrails error for %s: %v", url, err)
continue
}
if result == nil {
continue
}
for _, d := range result.DiscoveredURLs() {
if _, exists := seen[d]; !exists {
seen[d] = struct{}{}
expanded = append(expanded, d)
}
}
}
return expanded
}
+1 -1
View File
@@ -4,7 +4,7 @@
: · Blazing-fast pentesting suite :
: · BSD 3-Clause License :
: :
: (c) 2022-2025 vmfunc (vmfunc), xyzeva, :
: (c) 2022-2025 vmfunc, xyzeva, :
: lunchcat alumni & contributors :
: :
··