mirror of
https://github.com/lunchcat/sif.git
synced 2026-07-28 22:40:54 -07:00
* refactor(cli): extract per-target scan into scanTarget pull the target loop body into scanTarget, which returns a targetScan holding that target's findings, report rows, scan labels and log files instead of appending onto run-wide slices. the run loop merges those in target order and finishRun handles the post-loop notify/silent/report/ summary steps. behavior is identical for the sequential run today; the isolation is the seam a bounded worker pool needs next. * feat(cli): scan targets in parallel with -concurrency add -concurrency N (default 1) to run the per-target scan pool over several targets at once. scanTarget already returns isolated accumulators, so workers share only the console: output.SetConcurrent serializes sink writes and de-animates spinners/progress so parallel lines stay whole. results merge in input order, and concurrency 1 keeps the sequential path unchanged.
79 lines
3.0 KiB
Go
79 lines
3.0 KiB
Go
/*
|
|
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
|
: :
|
|
: █▀ █ █▀▀ · Blazing-fast pentesting suite :
|
|
: ▄█ █ █▀ · BSD 3-Clause License :
|
|
: :
|
|
: (c) 2022-2026 vmfunc, xyzeva, :
|
|
: lunchcat alumni & contributors :
|
|
: :
|
|
·━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━·
|
|
*/
|
|
|
|
package sif
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/vmfunc/sif/internal/config"
|
|
)
|
|
|
|
// headersOnlyApp builds an App that runs only the HTTP headers scan against
|
|
// live servers, with every network-touching scanner gated off. it isolates the
|
|
// scanTarget path to a single deterministic scan.
|
|
func headersOnlyApp() *App {
|
|
return &App{settings: &config.Settings{
|
|
Headers: true,
|
|
NoScan: true,
|
|
Dirlist: "none",
|
|
Dnslist: "none",
|
|
Ports: "none",
|
|
Timeout: 5 * time.Second,
|
|
}}
|
|
}
|
|
|
|
func okServer() *httptest.Server {
|
|
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
|
w.Header().Set("X-Sif-Test", "1")
|
|
w.WriteHeader(http.StatusOK)
|
|
}))
|
|
}
|
|
|
|
// TestScanTargetIsolatesPerTargetState is the accumulator seam the worker pool
|
|
// depends on: each scanTarget call must own its scansRun rather than share a
|
|
// run-wide slice. two sequential scans of different targets must each report a
|
|
// single scan, not a growing total; a shared accumulator would make the second
|
|
// call report two.
|
|
func TestScanTargetIsolatesPerTargetState(t *testing.T) {
|
|
srvA := okServer()
|
|
defer srvA.Close()
|
|
srvB := okServer()
|
|
defer srvB.Close()
|
|
|
|
app := headersOnlyApp()
|
|
|
|
tsA, err := app.scanTarget(srvA.URL, "", false)
|
|
if err != nil {
|
|
t.Fatalf("scanTarget(A): %v", err)
|
|
}
|
|
if len(tsA.scansRun) != 1 || tsA.scansRun[0] != "HTTP Headers" {
|
|
t.Fatalf("target A scansRun = %v, want exactly [HTTP Headers]", tsA.scansRun)
|
|
}
|
|
|
|
tsB, err := app.scanTarget(srvB.URL, "", false)
|
|
if err != nil {
|
|
t.Fatalf("scanTarget(B): %v", err)
|
|
}
|
|
if len(tsB.scansRun) != 1 || tsB.scansRun[0] != "HTTP Headers" {
|
|
t.Fatalf("target B scansRun = %v, want exactly [HTTP Headers] (accumulator leaked across targets)", tsB.scansRun)
|
|
}
|
|
|
|
// no log dir configured, so no per-target log file should be recorded.
|
|
if len(tsA.logFiles) != 0 || len(tsB.logFiles) != 0 {
|
|
t.Errorf("logFiles should be empty without a log dir, got A=%v B=%v", tsA.logFiles, tsB.logFiles)
|
|
}
|
|
}
|