package modules_test import ( "context" "net/http" "net/http/httptest" "testing" "time" "github.com/vmfunc/sif/internal/modules" ) func runDebugModule(t *testing.T, file string, status int, body string) *modules.Result { t.Helper() def, err := modules.ParseYAMLModule(file) if err != nil { t.Fatalf("parse %s: %v", file, err) } srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(status) _, _ = w.Write([]byte(body)) })) defer srv.Close() res, err := modules.ExecuteHTTPModule(context.Background(), srv.URL, def, modules.Options{ Timeout: 5 * time.Second, Threads: 2, }) if err != nil { t.Fatalf("execute %s: %v", file, err) } return res } func debugExtract(res *modules.Result, key string) string { for _, f := range res.Findings { if v := f.Extracted[key]; v != "" { return v } } return "" } func TestDebugExposureModules(t *testing.T) { const ignition = "../../modules/recon/laravel-ignition-exposure.yaml" const profiler = "../../modules/recon/symfony-profiler-exposure.yaml" const heapdump = "../../modules/recon/spring-heapdump-exposure.yaml" t.Run("ignition health check exposes command execution", func(t *testing.T) { res := runDebugModule(t, ignition, 200, `{"can_execute_commands":true,"config":{}}`) if len(res.Findings) == 0 { t.Fatal("expected an ignition finding") } if v := debugExtract(res, "can_execute_commands"); v != "true" { t.Errorf("can_execute_commands=%q, want true", v) } }) t.Run("ignition exposed with debug off still flags and extracts false", func(t *testing.T) { res := runDebugModule(t, ignition, 200, `{"can_execute_commands":false}`) if len(res.Findings) == 0 { t.Fatal("expected an ignition finding even when command execution is off") } if v := debugExtract(res, "can_execute_commands"); v != "false" { t.Errorf("can_execute_commands=%q, want false", v) } }) t.Run("symfony profiler exposes a request token", func(t *testing.T) { body := `