From 34419afbadd1f4dbf8453bd3b8bd6d17420b0b0a Mon Sep 17 00:00:00 2001 From: Emmanuel Gautier Date: Tue, 27 Feb 2024 20:17:48 +0100 Subject: [PATCH] refactor: make the structure easier to understand --- cmd/scan/root_test.go | 18 +++ internal/auth/bearer_test.go | 84 ++++++++++ internal/auth/scheme_test.go | 43 +++++ internal/auth/security_scheme.go | 48 ++++++ internal/auth/security_scheme_test.go | 45 ++++++ internal/{rest_api => openapi}/loader.go | 2 +- .../{auth/auth.go => request/operation.go} | 23 +-- internal/request/operation_test.go | 39 +++++ internal/request/request.go | 45 +++--- internal/request/request_test.go | 150 ------------------ internal/request/scan_url.go | 31 ++++ internal/rest_api/request.go | 36 ----- report/report.go | 22 +-- report/report_test.go | 61 +++++++ report/reporter.go | 8 +- report/vuln.go | 2 +- report/vuln_test.go | 34 ++++ scan/best_practices/http_headers.go | 13 +- scan/best_practices/http_headers_test.go | 21 +-- scan/best_practices/http_trace_method.go | 9 +- scan/best_practices/http_trace_method_test.go | 5 +- scan/jwt/alg_none.go | 13 +- scan/jwt/not_verified.go | 18 ++- scan/jwt/null_signature.go | 9 +- scan/jwt/weak_secret.go | 17 +- scan/openapi.go | 9 +- scan/openapi_test.go | 3 +- scan/scan.go | 30 ++-- scan/scan_test.go | 7 +- scan/url.go | 3 +- scan/url_test.go | 13 +- 31 files changed, 551 insertions(+), 310 deletions(-) create mode 100644 cmd/scan/root_test.go create mode 100644 internal/auth/bearer_test.go create mode 100644 internal/auth/scheme_test.go create mode 100644 internal/auth/security_scheme.go create mode 100644 internal/auth/security_scheme_test.go rename internal/{rest_api => openapi}/loader.go (98%) rename internal/{auth/auth.go => request/operation.go} (64%) create mode 100644 internal/request/operation_test.go delete mode 100644 internal/request/request_test.go create mode 100644 internal/request/scan_url.go delete mode 100644 internal/rest_api/request.go create mode 100644 report/report_test.go create mode 100644 report/vuln_test.go diff --git a/cmd/scan/root_test.go b/cmd/scan/root_test.go new file mode 100644 index 0000000..117c3d5 --- /dev/null +++ b/cmd/scan/root_test.go @@ -0,0 +1,18 @@ +package scan_test + +import ( + "testing" + + "github.com/cerberauth/vulnapi/cmd/scan" + "github.com/stretchr/testify/assert" +) + +func TestNewScanCmd(t *testing.T) { + scanCmd := scan.NewScanCmd() + + assert.NotNil(t, scanCmd) + + // Assert that NewCURLScanCmd and NewOpenAPIScanCmd commands are added + assert.NotNil(t, scanCmd.Commands()) + assert.Len(t, scanCmd.Commands(), 2) +} diff --git a/internal/auth/bearer_test.go b/internal/auth/bearer_test.go new file mode 100644 index 0000000..6b27162 --- /dev/null +++ b/internal/auth/bearer_test.go @@ -0,0 +1,84 @@ +package auth_test + +import ( + "net/http" + "testing" + + "github.com/cerberauth/vulnapi/internal/auth" + "github.com/stretchr/testify/assert" +) + +func TestNewAuthorizationBearerSecurityScheme(t *testing.T) { + name := "token" + value := "abc123" + + ss := auth.NewAuthorizationBearerSecurityScheme(name, &value) + + assert.Equal(t, auth.HttpType, ss.Type) + assert.Equal(t, auth.BearerScheme, ss.Scheme) + assert.Equal(t, auth.InHeader, ss.In) + assert.Equal(t, name, ss.Name) + assert.Equal(t, &value, ss.ValidValue) + assert.Equal(t, "", ss.AttackValue) +} + +func TestBearerSecurityScheme_GetHeaders(t *testing.T) { + name := "token" + value := "abc123" + + ss := auth.NewAuthorizationBearerSecurityScheme(name, &value) + + headers := ss.GetHeaders() + + assert.Equal(t, http.Header{ + "Authorization": []string{"Bearer abc123"}, + }, headers) +} + +func TestBearerSecurityScheme_GetCookies(t *testing.T) { + name := "token" + value := "abc123" + + ss := auth.NewAuthorizationBearerSecurityScheme(name, &value) + + cookies := ss.GetCookies() + + assert.Empty(t, cookies) +} + +func TestBearerSecurityScheme_GetValidValue(t *testing.T) { + name := "token" + value := "abc123" + + ss := auth.NewAuthorizationBearerSecurityScheme(name, &value) + + validValue := ss.GetValidValue() + + assert.Equal(t, value, validValue) +} + +func TestBearerSecurityScheme_SetAttackValue(t *testing.T) { + name := "token" + value := "abc123" + + ss := auth.NewAuthorizationBearerSecurityScheme(name, &value) + + attackValue := "xyz789" + ss.SetAttackValue(attackValue) + + assert.Equal(t, attackValue, ss.AttackValue) +} + +func TestBearerSecurityScheme_GetAttackValue(t *testing.T) { + name := "token" + value := "abc123" + + ss := auth.NewAuthorizationBearerSecurityScheme(name, &value) + + attackValue := "xyz789" + ss.SetAttackValue(attackValue) + + result := ss.GetAttackValue() + + assert.Equal(t, attackValue, result) +} diff --git a/internal/auth/scheme_test.go b/internal/auth/scheme_test.go new file mode 100644 index 0000000..7229cc8 --- /dev/null +++ b/internal/auth/scheme_test.go @@ -0,0 +1,43 @@ +package auth_test + +import ( + "testing" + + "github.com/cerberauth/vulnapi/internal/auth" + "github.com/stretchr/testify/assert" +) + +func TestSchemeName_String(t *testing.T) { + scheme := auth.BasicScheme + assert.Equal(t, "basic", scheme.String()) +} + +func TestSchemeName_Set_Valid(t *testing.T) { + scheme := auth.SchemeName("") + err := scheme.Set("bearer") + assert.NoError(t, err) + assert.Equal(t, auth.BearerScheme, scheme) +} + +func TestSchemeName_Set_Invalid(t *testing.T) { + scheme := auth.SchemeName("") + err := scheme.Set("invalid") + assert.Error(t, err) + assert.EqualError(t, err, `must be one of "basic", "bearer", "digest", "oauth", "privateToken"`) + assert.Equal(t, auth.SchemeName(""), scheme) +} + +func TestSchemeName_Type(t *testing.T) { + scheme := auth.BasicScheme + assert.Equal(t, "scheme", scheme.Type()) +} + +func TestSchemeIn(t *testing.T) { + schemeIn := auth.InHeader + assert.Equal(t, "header", string(schemeIn)) +} + +func TestSchemeIn_String(t *testing.T) { + schemeIn := auth.InHeader + assert.Equal(t, "header", string(schemeIn)) +} diff --git a/internal/auth/security_scheme.go b/internal/auth/security_scheme.go new file mode 100644 index 0000000..a47d62c --- /dev/null +++ b/internal/auth/security_scheme.go @@ -0,0 +1,48 @@ +package auth + +import ( + "net/http" +) + +type Type string + +const ( + HttpType Type = "http" + OAuth2 Type = "oauth2" + OpenIdConnect Type = "openIdConnect" + ApiKey Type = "apiKey" +) + +type SecurityScheme interface { + GetHeaders() http.Header + GetCookies() []*http.Cookie + GetValidValue() interface{} + SetAttackValue(v interface{}) + GetAttackValue() interface{} +} + +type NoAuthSecurityScheme struct{} + +var _ SecurityScheme = (*NoAuthSecurityScheme)(nil) + +func NewNoAuthSecurityScheme() *NoAuthSecurityScheme { + return &NoAuthSecurityScheme{} +} + +func (ss *NoAuthSecurityScheme) GetHeaders() http.Header { + return http.Header{} +} + +func (ss *NoAuthSecurityScheme) GetCookies() []*http.Cookie { + return []*http.Cookie{} +} + +func (ss *NoAuthSecurityScheme) GetValidValue() interface{} { + return nil +} + +func (ss *NoAuthSecurityScheme) SetAttackValue(v interface{}) {} + +func (ss *NoAuthSecurityScheme) GetAttackValue() interface{} { + return nil +} diff --git a/internal/auth/security_scheme_test.go b/internal/auth/security_scheme_test.go new file mode 100644 index 0000000..7253209 --- /dev/null +++ b/internal/auth/security_scheme_test.go @@ -0,0 +1,45 @@ +package auth_test + +import ( + "testing" + + "github.com/cerberauth/vulnapi/internal/auth" + "github.com/stretchr/testify/assert" +) + +func TestNewNoAuthSecurityScheme(t *testing.T) { + ss := auth.NewNoAuthSecurityScheme() + assert.NotNil(t, ss) +} + +func TestNoAuthSecurityScheme_GetHeaders(t *testing.T) { + ss := &auth.NoAuthSecurityScheme{} + headers := ss.GetHeaders() + assert.NotNil(t, headers) + assert.Empty(t, headers) +} + +func TestNoAuthSecurityScheme_GetCookies(t *testing.T) { + ss := &auth.NoAuthSecurityScheme{} + cookies := ss.GetCookies() + assert.NotNil(t, cookies) + assert.Empty(t, cookies) +} + +func TestNoAuthSecurityScheme_GetValidValue(t *testing.T) { + ss := &auth.NoAuthSecurityScheme{} + validValue := ss.GetValidValue() + assert.Nil(t, validValue) +} + +func TestNoAuthSecurityScheme_SetAttackValue(t *testing.T) { + ss := &auth.NoAuthSecurityScheme{} + ss.SetAttackValue("attack value") + // No assertion as this method does not return anything +} + +func TestNoAuthSecurityScheme_GetAttackValue(t *testing.T) { + ss := &auth.NoAuthSecurityScheme{} + attackValue := ss.GetAttackValue() + assert.Nil(t, attackValue) +} diff --git a/internal/rest_api/loader.go b/internal/openapi/loader.go similarity index 98% rename from internal/rest_api/loader.go rename to internal/openapi/loader.go index 19ee2c7..83b600a 100644 --- a/internal/rest_api/loader.go +++ b/internal/openapi/loader.go @@ -1,4 +1,4 @@ -package restapi +package openapi import ( "errors" diff --git a/internal/auth/auth.go b/internal/request/operation.go similarity index 64% rename from internal/auth/auth.go rename to internal/request/operation.go index dda7101..a9e770a 100644 --- a/internal/auth/auth.go +++ b/internal/request/operation.go @@ -1,24 +1,11 @@ -package auth +package request -import "net/http" +import ( + "net/http" -type Type string - -const ( - HttpType Type = "http" - OAuth2 Type = "oauth2" - OpenIdConnect Type = "openIdConnect" - ApiKey Type = "apiKey" + "github.com/cerberauth/vulnapi/internal/auth" ) -type SecurityScheme interface { - GetHeaders() http.Header - GetCookies() []*http.Cookie - GetValidValue() interface{} - SetAttackValue(v interface{}) - GetAttackValue() interface{} -} - type Operations []Operation func (o Operations) Len() int { return len(o) } @@ -37,7 +24,7 @@ type Operation struct { Headers *http.Header Cookies []http.Cookie - SecuritySchemes []SecurityScheme + SecuritySchemes []auth.SecurityScheme } func (o Operation) Clone() Operation { diff --git a/internal/request/operation_test.go b/internal/request/operation_test.go new file mode 100644 index 0000000..58386df --- /dev/null +++ b/internal/request/operation_test.go @@ -0,0 +1,39 @@ +package request_test + +import ( + "net/http" + "testing" + + "github.com/cerberauth/vulnapi/internal/request" + "github.com/stretchr/testify/assert" +) + +func TestOperation_Clone(t *testing.T) { + headers := http.Header{} + headers.Add("Content-Type", "application/json") + + cookies := []http.Cookie{ + { + Name: "cookie1", + Value: "value1", + }, + { + Name: "cookie2", + Value: "value2", + }, + } + + operation := request.Operation{ + Url: "http://example.com", + Method: "GET", + Headers: &headers, + Cookies: cookies, + } + + clonedOperation := operation.Clone() + + assert.Equal(t, operation.Url, clonedOperation.Url) + assert.Equal(t, operation.Method, clonedOperation.Method) + assert.Equal(t, operation.Headers, clonedOperation.Headers) + assert.Equal(t, operation.Cookies, clonedOperation.Cookies) +} diff --git a/internal/request/request.go b/internal/request/request.go index b3cd7de..47d4bc4 100644 --- a/internal/request/request.go +++ b/internal/request/request.go @@ -1,38 +1,47 @@ package request import ( + "io" "net/http" + "time" "github.com/cerberauth/vulnapi/internal/auth" ) -func NewRequest(method string, url string) (*http.Request, error) { - req, err := http.NewRequest(method, url, nil) +var SharedClient = &http.Client{ + Timeout: time.Second * 10, +} + +type Request struct { + *http.Request + SecurityScheme *auth.SecurityScheme +} + +func NewRequest(method string, url string, body io.Reader) (*Request, error) { + req, err := http.NewRequest(method, url, body) if err != nil { return nil, err } + return &Request{req, nil}, nil +} - req.Header.Set("User-Agent", "vulnapi/0.1") - - return req, nil +func (r *Request) WithSecurityScheme(ss *auth.SecurityScheme) *Request { + r.SecurityScheme = ss + return r } -func DoRequest(client *http.Client, req *http.Request, ss auth.SecurityScheme) (*http.Request, *http.Response, error) { - if ss != nil { - for _, c := range ss.GetCookies() { - req.AddCookie(c) - } +func (r *Request) Do() (*http.Response, error) { + r.Header.Set("User-Agent", "MyProject") - for n, h := range ss.GetHeaders() { - req.Header.Add(n, h[0]) + if securityScheme := *r.SecurityScheme; securityScheme != nil { + for _, c := range securityScheme.GetCookies() { + r.AddCookie(c) } - } - res, err := client.Do(req) - if err != nil { - return req, res, err + for n, h := range securityScheme.GetHeaders() { + r.Header.Add(n, h[0]) + } } - defer res.Body.Close() - return req, res, nil + return SharedClient.Do(r.Request) } diff --git a/internal/request/request_test.go b/internal/request/request_test.go deleted file mode 100644 index 32ee094..0000000 --- a/internal/request/request_test.go +++ /dev/null @@ -1,150 +0,0 @@ -package request - -import ( - "net/http" - "net/url" - "testing" - - "github.com/jarcoal/httpmock" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -type SecuritySchemeMock struct { - Cookies []*http.Cookie - Headers http.Header - ValidValue interface{} - AttackValue interface{} -} - -func NewSecuritySchemeMock() *SecuritySchemeMock { - return &SecuritySchemeMock{ - Cookies: []*http.Cookie{}, - Headers: http.Header{}, - ValidValue: nil, - AttackValue: nil, - } -} - -func (ss *SecuritySchemeMock) GetCookies() []*http.Cookie { - return ss.Cookies -} - -func (ss *SecuritySchemeMock) GetHeaders() http.Header { - return ss.Headers -} - -func (ss *SecuritySchemeMock) GetValidValue() interface{} { - return ss.ValidValue -} - -func (ss *SecuritySchemeMock) SetAttackValue(v interface{}) { - ss.AttackValue = v -} - -func (ss *SecuritySchemeMock) GetAttackValue() interface{} { - return ss.AttackValue -} - -var reqMethod = "GET" -var reqUrl = "http://localhost:8080" - -func setupSuite(tb testing.TB) func(tb testing.TB) { - httpmock.Activate() - httpmock.RegisterResponder(reqMethod, reqUrl, httpmock.NewBytesResponder(204, nil)) - - return func(tb testing.TB) { - defer httpmock.DeactivateAndReset() - } -} - -func TestNewRequestUserMethodAndUrl(t *testing.T) { - teardownSuite := setupSuite(t) - defer teardownSuite(t) - - req, err := NewRequest(reqMethod, reqUrl) - require.NoError(t, err) - assert.Equal(t, reqMethod, req.Method) - assert.Equal(t, &url.URL{Scheme: "http", Host: "localhost:8080"}, req.URL) - - reqMethod2 := "PUT" - - req2, err2 := NewRequest(reqMethod2, reqUrl) - require.NoError(t, err2) - assert.Equal(t, reqMethod2, req2.Method) - assert.Equal(t, &url.URL{Scheme: "http", Host: "localhost:8080"}, req2.URL) -} - -func TestNewRequestAddUserAgent(t *testing.T) { - teardownSuite := setupSuite(t) - defer teardownSuite(t) - - req, err := NewRequest(reqMethod, reqUrl) - require.NoError(t, err) - assert.Equal(t, "vulnapi/0.1", req.UserAgent()) -} - -func TestNewRequestWithWrongUrl(t *testing.T) { - teardownSuite := setupSuite(t) - defer teardownSuite(t) - - _, err := NewRequest(reqMethod, "://localhost:8080") - require.Error(t, err) -} - -func TestDoRequestWithoutSecurityScheme(t *testing.T) { - teardownSuite := setupSuite(t) - defer teardownSuite(t) - - client := &http.Client{} - req, _ := NewRequest(reqMethod, reqUrl) - - req, res, err := DoRequest(client, req, nil) - require.NoError(t, err) - assert.Equal(t, 0, len(req.Cookies())) - assert.Equal(t, req, req) - assert.NotNil(t, res) - - assert.Equal(t, 1, httpmock.GetTotalCallCount()) -} - -func TestDoRequestWithSecuritySchemeAndCookies(t *testing.T) { - teardownSuite := setupSuite(t) - defer teardownSuite(t) - - ss := NewSecuritySchemeMock() - ss.Cookies = append(ss.Cookies, &http.Cookie{ - Name: "cookie", - Value: "cookie value", - }) - client := &http.Client{} - req, _ := NewRequest(reqMethod, reqUrl) - - req, res, err := DoRequest(client, req, ss) - require.NoError(t, err) - assert.Equal(t, 1, len(req.Cookies())) - assert.Equal(t, ss.Cookies[0].Name, req.Cookies()[0].Name) - assert.Equal(t, ss.Cookies[0].Value, req.Cookies()[0].Value) - assert.NotNil(t, res) - - assert.Equal(t, 1, httpmock.GetTotalCallCount()) -} - -func TestDoRequestWithSecuritySchemeAndHeaders(t *testing.T) { - teardownSuite := setupSuite(t) - defer teardownSuite(t) - - ss := NewSecuritySchemeMock() - ss.Headers = http.Header{} - ss.Headers.Add("header1", "value1") - client := &http.Client{} - req, _ := NewRequest(reqMethod, reqUrl) - - req, res, err := DoRequest(client, req, ss) - require.NoError(t, err) - assert.Equal(t, 0, len(req.Cookies())) - assert.Equal(t, "value1", req.Header.Get("header1")) - assert.NotNil(t, res) - - assert.Equal(t, 1, httpmock.GetTotalCallCount()) -} diff --git a/internal/request/scan_url.go b/internal/request/scan_url.go new file mode 100644 index 0000000..3f802e3 --- /dev/null +++ b/internal/request/scan_url.go @@ -0,0 +1,31 @@ +package request + +import ( + "fmt" + + "github.com/cerberauth/vulnapi/internal/auth" + "github.com/cerberauth/vulnapi/report" +) + +func ScanURL(operation *Operation, securityScheme *auth.SecurityScheme) (*report.VulnerabilityScanAttempt, error) { + req, err := NewRequest(operation.Method, operation.Url, nil) + if err != nil { + return nil, fmt.Errorf("request with url %s has an unexpected error", err) + } else { + req = req.WithSecurityScheme(securityScheme) + } + + resp, err := req.Do() + if err != nil { + err = fmt.Errorf("request with url %s has an unexpected error", err) + } else if resp.StatusCode < 200 && resp.StatusCode >= 300 { + err = fmt.Errorf("unexpected status code %d during test request", resp.StatusCode) + } + defer resp.Body.Close() + + return &report.VulnerabilityScanAttempt{ + Request: req.Request, + Response: resp, + Err: err, + }, nil +} diff --git a/internal/rest_api/request.go b/internal/rest_api/request.go deleted file mode 100644 index 19c3546..0000000 --- a/internal/rest_api/request.go +++ /dev/null @@ -1,36 +0,0 @@ -package restapi - -import ( - "fmt" - "net/http" - - "github.com/cerberauth/vulnapi/internal/auth" - "github.com/cerberauth/vulnapi/internal/request" - "github.com/cerberauth/vulnapi/report" -) - -func ScanRestAPI(o *auth.Operation, ss auth.SecurityScheme) *report.VulnerabilityScanAttempt { - var req *http.Request - var res *http.Response - var err error = nil - - client := &http.Client{} - req, err = request.NewRequest(o.Method, o.Url) - if err != nil { - err = fmt.Errorf("request with url %s has an unexpected error", err) - } else { - req, res, err = request.DoRequest(client, req, ss) - } - - if err != nil { - err = fmt.Errorf("request with url %s has an unexpected error", err) - } else if res.StatusCode < 200 && res.StatusCode >= 300 { - err = fmt.Errorf("unexpected status code %d during test request", res.StatusCode) - } - - return &report.VulnerabilityScanAttempt{ - Request: req, - Response: res, - Err: err, - } -} diff --git a/report/report.go b/report/report.go index bce3186..25b7b69 100644 --- a/report/report.go +++ b/report/report.go @@ -13,45 +13,45 @@ type VulnerabilityScanAttempt struct { } type ScanReport struct { - scans []*VulnerabilityScanAttempt - vulns []*VulnerabilityReport + Scans []*VulnerabilityScanAttempt `json:"scans"` + Vulns []*VulnerabilityReport `json:"vulnerabilities"` - startTime time.Time - endTime time.Time + StartTime time.Time `json:"start_time"` + EndTime time.Time `json:"end_time"` } func NewScanReport() *ScanReport { return &ScanReport{ - startTime: time.Now(), + StartTime: time.Now(), } } func (sc *ScanReport) Start() *ScanReport { - sc.startTime = time.Now() + sc.StartTime = time.Now() return sc } func (sc *ScanReport) End() *ScanReport { - sc.endTime = time.Now() + sc.EndTime = time.Now() return sc } func (sc *ScanReport) AddScanAttempt(a *VulnerabilityScanAttempt) *ScanReport { - sc.scans = append(sc.scans, a) + sc.Scans = append(sc.Scans, a) return sc } func (sc *ScanReport) GetScanAttempts() []*VulnerabilityScanAttempt { - return sc.scans + return sc.Scans } func (sc *ScanReport) AddVulnerabilityReport(vr *VulnerabilityReport) *ScanReport { - sc.vulns = append(sc.vulns, vr) + sc.Vulns = append(sc.Vulns, vr) return sc } func (sc *ScanReport) GetVulnerabilityReports() []*VulnerabilityReport { - return sc.vulns + return sc.Vulns } func (sc *ScanReport) HasVulnerabilityReport() bool { diff --git a/report/report_test.go b/report/report_test.go new file mode 100644 index 0000000..194c5e7 --- /dev/null +++ b/report/report_test.go @@ -0,0 +1,61 @@ +package report_test + +import ( + "net/http" + "testing" + "time" + + "github.com/cerberauth/vulnapi/report" + "github.com/stretchr/testify/assert" +) + +func TestNewScanReport(t *testing.T) { + sr := report.NewScanReport() + assert.NotNil(t, sr) + assert.NotZero(t, sr.StartTime) +} + +func TestScanReport_Start(t *testing.T) { + sr := report.NewScanReport() + startTime := sr.StartTime + time.Sleep(1 * time.Second) + sr.Start() + assert.NotEqual(t, startTime, sr.StartTime) +} + +func TestScanReport_End(t *testing.T) { + sr := report.NewScanReport() + endTime := sr.EndTime + time.Sleep(1 * time.Second) + sr.End() + assert.NotEqual(t, endTime, sr.EndTime) +} + +func TestScanReport_AddScanAttempt(t *testing.T) { + sr := report.NewScanReport() + scanAttempt := &report.VulnerabilityScanAttempt{ + Request: &http.Request{}, + Response: &http.Response{}, + Err: nil, + } + sr.AddScanAttempt(scanAttempt) + assert.Equal(t, 1, len(sr.GetScanAttempts())) + assert.Equal(t, scanAttempt, sr.GetScanAttempts()[0]) +} + +func TestScanReport_AddVulnerabilityReport(t *testing.T) { + sr := report.NewScanReport() + vulnerabilityReport := &report.VulnerabilityReport{} + sr.AddVulnerabilityReport(vulnerabilityReport) + assert.Equal(t, 1, len(sr.GetVulnerabilityReports())) + assert.Equal(t, vulnerabilityReport, sr.GetVulnerabilityReports()[0]) +} + +func TestScanReport_HasVulnerabilityReport(t *testing.T) { + sr := report.NewScanReport() + assert.False(t, sr.HasVulnerabilityReport()) + + vulnerabilityReport := &report.VulnerabilityReport{} + sr.AddVulnerabilityReport(vulnerabilityReport) + assert.True(t, sr.HasVulnerabilityReport()) +} diff --git a/report/reporter.go b/report/reporter.go index c92efed..9804215 100644 --- a/report/reporter.go +++ b/report/reporter.go @@ -1,21 +1,21 @@ package report type Reporter struct { - reports []*ScanReport + Reports []*ScanReport `json:"reports"` } func NewReporter() *Reporter { return &Reporter{ - reports: []*ScanReport{}, + Reports: []*ScanReport{}, } } func (rr *Reporter) AddReport(r *ScanReport) { - rr.reports = append(rr.reports, r) + rr.Reports = append(rr.Reports, r) } func (rr *Reporter) GetReports() []*ScanReport { - return rr.reports + return rr.Reports } func (rr *Reporter) HasVulnerability() bool { diff --git a/report/vuln.go b/report/vuln.go index 369f7d7..d9b047a 100644 --- a/report/vuln.go +++ b/report/vuln.go @@ -29,7 +29,7 @@ func severyLevelString(severityLevel float64) string { if severityLevel >= 9 { return "critical" } else if severityLevel < 9 && severityLevel >= 7 { - return "hight" + return "high" } else if severityLevel < 7 && severityLevel >= 4 { return "medium" } else if severityLevel < 4 && severityLevel >= 0.1 { diff --git a/report/vuln_test.go b/report/vuln_test.go new file mode 100644 index 0000000..8443b25 --- /dev/null +++ b/report/vuln_test.go @@ -0,0 +1,34 @@ +package report_test + +import ( + "testing" + + "github.com/cerberauth/vulnapi/report" + "github.com/stretchr/testify/assert" +) + +func TestVulnerabilityReport_IsLowRiskSeverity(t *testing.T) { + vr := &report.VulnerabilityReport{SeverityLevel: 3.5} + assert.True(t, vr.IsLowRiskSeverity()) +} + +func TestVulnerabilityReport_IsMediumRiskSeverity(t *testing.T) { + vr := &report.VulnerabilityReport{SeverityLevel: 5.5} + assert.True(t, vr.IsMediumRiskSeverity()) +} + +func TestVulnerabilityReport_IsHighRiskSeverity(t *testing.T) { + vr := &report.VulnerabilityReport{SeverityLevel: 9.5} + assert.True(t, vr.IsHighRiskSeverity()) +} + +func TestVulnerabilityReport_String(t *testing.T) { + vr := &report.VulnerabilityReport{ + SeverityLevel: 7.5, + Name: "Test Vulnerability", + Description: "This is a test vulnerability", + Url: "https://example.com/vulnerability", + } + expected := "[high][Test Vulnerability] https://example.com/vulnerability: This is a test vulnerability" + assert.Equal(t, expected, vr.String()) +} diff --git a/scan/best_practices/http_headers.go b/scan/best_practices/http_headers.go index 658cc97..dcd4403 100644 --- a/scan/best_practices/http_headers.go +++ b/scan/best_practices/http_headers.go @@ -5,7 +5,7 @@ import ( "strings" "github.com/cerberauth/vulnapi/internal/auth" - restapi "github.com/cerberauth/vulnapi/internal/rest_api" + "github.com/cerberauth/vulnapi/internal/request" "github.com/cerberauth/vulnapi/report" ) @@ -43,7 +43,7 @@ const ( XFrameOptionsHTTPHeaderIsNotSetVulnerabilityDescription = "No X-Frame-Options Header has been detected in HTTP Response." ) -func checkCSPHeader(o *auth.Operation, headers http.Header, r *report.ScanReport) bool { +func checkCSPHeader(o *request.Operation, headers http.Header, r *report.ScanReport) bool { cspHeader := headers.Get(CSPHTTPHeader) if cspHeader == "" { r.AddVulnerabilityReport(&report.VulnerabilityReport{ @@ -77,7 +77,7 @@ func checkCSPHeader(o *auth.Operation, headers http.Header, r *report.ScanReport return false } -func CheckCORSAllowOrigin(o *auth.Operation, headers http.Header, r *report.ScanReport) bool { +func CheckCORSAllowOrigin(o *request.Operation, headers http.Header, r *report.ScanReport) bool { allowOrigin := headers.Get(CORSOriginHTTPHeader) if allowOrigin == "" { r.AddVulnerabilityReport(&report.VulnerabilityReport{ @@ -105,13 +105,16 @@ func CheckCORSAllowOrigin(o *auth.Operation, headers http.Header, r *report.Scan return false } -func HTTPHeadersBestPracticesScanHandler(o *auth.Operation, ss auth.SecurityScheme) (*report.ScanReport, error) { +func HTTPHeadersBestPracticesScanHandler(o *request.Operation, ss auth.SecurityScheme) (*report.ScanReport, error) { r := report.NewScanReport() token := ss.GetValidValue().(string) ss.SetAttackValue(token) - vsa := restapi.ScanRestAPI(o, ss) + vsa, err := request.ScanURL(o, &ss) r.AddScanAttempt(vsa).End() + if err != nil { + return r, err + } if vsa.Err != nil { return r, vsa.Err diff --git a/scan/best_practices/http_headers_test.go b/scan/best_practices/http_headers_test.go index 3025d91..9d4651a 100644 --- a/scan/best_practices/http_headers_test.go +++ b/scan/best_practices/http_headers_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/cerberauth/vulnapi/internal/auth" + "github.com/cerberauth/vulnapi/internal/request" "github.com/cerberauth/vulnapi/report" bestpractices "github.com/cerberauth/vulnapi/scan/best_practices" "github.com/jarcoal/httpmock" @@ -12,7 +13,7 @@ import ( "github.com/stretchr/testify/require" ) -func getValidHTTPHeaders(o *auth.Operation) *http.Header { +func getValidHTTPHeaders(o *request.Operation) *http.Header { header := http.Header{} header.Add(bestpractices.CSPHTTPHeader, "frame-ancestors 'none'") header.Add(bestpractices.CORSOriginHTTPHeader, "http://localhost:8080") @@ -29,7 +30,7 @@ func TestHTTPHeadersBestPracticesScanHandler(t *testing.T) { token := "token" securityScheme := auth.NewAuthorizationBearerSecurityScheme("default", &token) - o := auth.Operation{ + o := request.Operation{ Method: "GET", Url: "http://localhost:8080/", } @@ -50,7 +51,7 @@ func TestHTTPHeadersBestPracticesWithoutCSPScanHandler(t *testing.T) { token := "token" securityScheme := auth.NewAuthorizationBearerSecurityScheme("default", &token) - o := auth.Operation{ + o := request.Operation{ Method: "GET", Url: "http://localhost:8080/", } @@ -79,7 +80,7 @@ func TestHTTPHeadersBestPracticesWithoutFrameAncestorsCSPDirectiveScanHandler(t token := "token" securityScheme := auth.NewAuthorizationBearerSecurityScheme("default", &token) - o := auth.Operation{ + o := request.Operation{ Method: "GET", Url: "http://localhost:8080/", } @@ -108,7 +109,7 @@ func TestHTTPHeadersBestPracticesWithNotNoneFrameAncestorsCSPDirectiveScanHandle token := "token" securityScheme := auth.NewAuthorizationBearerSecurityScheme("default", &token) - o := auth.Operation{ + o := request.Operation{ Method: "GET", Url: "http://localhost:8080/", } @@ -137,7 +138,7 @@ func TestHTTPHeadersBestPracticesWithoutCORSScanHandler(t *testing.T) { token := "token" securityScheme := auth.NewAuthorizationBearerSecurityScheme("default", &token) - o := auth.Operation{ + o := request.Operation{ Method: "GET", Url: "http://localhost:8080/", } @@ -166,7 +167,7 @@ func TestHTTPHeadersBestPracticesWithPermissiveCORSScanHandler(t *testing.T) { token := "token" securityScheme := auth.NewAuthorizationBearerSecurityScheme("default", &token) - o := auth.Operation{ + o := request.Operation{ Method: "GET", Url: "http://localhost:8080/", } @@ -195,7 +196,7 @@ func TestHTTPHeadersBestPracticesWithoutHSTSScanHandler(t *testing.T) { token := "token" securityScheme := auth.NewAuthorizationBearerSecurityScheme("default", &token) - o := auth.Operation{ + o := request.Operation{ Method: "GET", Url: "http://localhost:8080/", } @@ -224,7 +225,7 @@ func TestHTTPHeadersBestPracticesWithoutXContentTypeOptionsScanHandler(t *testin token := "token" securityScheme := auth.NewAuthorizationBearerSecurityScheme("default", &token) - o := auth.Operation{ + o := request.Operation{ Method: "GET", Url: "http://localhost:8080/", } @@ -253,7 +254,7 @@ func TestHTTPHeadersBestPracticesWithoutXFrameOptionsScanHandler(t *testing.T) { token := "token" securityScheme := auth.NewAuthorizationBearerSecurityScheme("default", &token) - o := auth.Operation{ + o := request.Operation{ Method: "GET", Url: "http://localhost:8080/", } diff --git a/scan/best_practices/http_trace_method.go b/scan/best_practices/http_trace_method.go index 954e679..c3f2495 100644 --- a/scan/best_practices/http_trace_method.go +++ b/scan/best_practices/http_trace_method.go @@ -2,7 +2,7 @@ package bestpractices import ( "github.com/cerberauth/vulnapi/internal/auth" - restapi "github.com/cerberauth/vulnapi/internal/rest_api" + "github.com/cerberauth/vulnapi/internal/request" "github.com/cerberauth/vulnapi/report" ) @@ -12,15 +12,18 @@ const ( HTTPTraceMethodVulnerabilityDescription = "HTTP Trace method seems enabled for this request." ) -func HTTPTraceMethodScanHandler(o *auth.Operation, ss auth.SecurityScheme) (*report.ScanReport, error) { +func HTTPTraceMethodScanHandler(o *request.Operation, ss auth.SecurityScheme) (*report.ScanReport, error) { r := report.NewScanReport() newOperation := o.Clone() newOperation.Method = "TRACE" token := ss.GetValidValue().(string) ss.SetAttackValue(token) - vsa := restapi.ScanRestAPI(&newOperation, ss) + vsa, err := request.ScanURL(&newOperation, &ss) r.AddScanAttempt(vsa).End() + if err != nil { + return r, err + } if vsa.Response.StatusCode < 300 { r.AddVulnerabilityReport(&report.VulnerabilityReport{ diff --git a/scan/best_practices/http_trace_method_test.go b/scan/best_practices/http_trace_method_test.go index 463f8f9..5dd6d40 100644 --- a/scan/best_practices/http_trace_method_test.go +++ b/scan/best_practices/http_trace_method_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/cerberauth/vulnapi/internal/auth" + "github.com/cerberauth/vulnapi/internal/request" "github.com/cerberauth/vulnapi/report" bestpractices "github.com/cerberauth/vulnapi/scan/best_practices" "github.com/jarcoal/httpmock" @@ -17,7 +18,7 @@ func TestHTTPTraceMethodScanHandler(t *testing.T) { token := "token" securityScheme := auth.NewAuthorizationBearerSecurityScheme("default", &token) - o := auth.Operation{ + o := request.Operation{ Method: "GET", Url: "http://localhost:8080/", } @@ -37,7 +38,7 @@ func TestHTTPTraceMethodWhenTraceIsEnabledScanHandler(t *testing.T) { token := "token" securityScheme := auth.NewAuthorizationBearerSecurityScheme("default", &token) - o := auth.Operation{ + o := request.Operation{ Method: "GET", Url: "http://localhost:8080/", } diff --git a/scan/jwt/alg_none.go b/scan/jwt/alg_none.go index 5c0b044..83d0c08 100644 --- a/scan/jwt/alg_none.go +++ b/scan/jwt/alg_none.go @@ -2,18 +2,18 @@ package jwt import ( "github.com/cerberauth/vulnapi/internal/auth" - restapi "github.com/cerberauth/vulnapi/internal/rest_api" + "github.com/cerberauth/vulnapi/internal/request" "github.com/cerberauth/vulnapi/report" "github.com/golang-jwt/jwt/v5" ) const ( AlgNoneVulnerabilitySeverityLevel = 9 - AlgNoneVulnerabilityName = "JWT Alg None" - AlgNoneVulnerabilityDescription = "JWT accepts none algorithm and does verify jwt." + AlgNoneVulnerabilityName = "JWT None Algorithm" + AlgNoneVulnerabilityDescription = "JWT with none algorithm is accepted allowing to bypass authentication." ) -func AlgNoneJwtScanHandler(o *auth.Operation, ss auth.SecurityScheme) (*report.ScanReport, error) { +func AlgNoneJwtScanHandler(o *request.Operation, ss auth.SecurityScheme) (*report.ScanReport, error) { r := report.NewScanReport() token := ss.GetValidValue().(string) @@ -22,7 +22,10 @@ func AlgNoneJwtScanHandler(o *auth.Operation, ss auth.SecurityScheme) (*report.S return r, err } ss.SetAttackValue(newToken) - vsa := restapi.ScanRestAPI(o, ss) + vsa, err := request.ScanURL(o, &ss) + if err != nil { + return r, err + } r.AddScanAttempt(vsa).End() if vsa.Response.StatusCode < 300 { diff --git a/scan/jwt/not_verified.go b/scan/jwt/not_verified.go index 3075167..5c3edfd 100644 --- a/scan/jwt/not_verified.go +++ b/scan/jwt/not_verified.go @@ -2,7 +2,7 @@ package jwt import ( "github.com/cerberauth/vulnapi/internal/auth" - restapi "github.com/cerberauth/vulnapi/internal/rest_api" + "github.com/cerberauth/vulnapi/internal/request" "github.com/cerberauth/vulnapi/report" "github.com/golang-jwt/jwt/v5" ) @@ -10,10 +10,10 @@ import ( const ( NotVerifiedVulnerabilitySeverityLevel = 9 NotVerifiedVulnerabilityName = "JWT Not Verified" - NotVerifiedVulnerabilityDescription = "JWT is not verified." + NotVerifiedVulnerabilityDescription = "JWT is not verified allowing attackers to issue valid JWT." ) -func NotVerifiedScanHandler(o *auth.Operation, ss auth.SecurityScheme) (*report.ScanReport, error) { +func NotVerifiedScanHandler(o *request.Operation, ss auth.SecurityScheme) (*report.ScanReport, error) { r := report.NewScanReport() token := ss.GetValidValue().(string) @@ -28,13 +28,19 @@ func NotVerifiedScanHandler(o *auth.Operation, ss auth.SecurityScheme) (*report. } ss.SetAttackValue(newTokenA) - vsa1 := restapi.ScanRestAPI(o, ss) + vsa1, err := request.ScanURL(o, &ss) + if err != nil { + return r, err + } r.AddScanAttempt(vsa1) ss.SetAttackValue(newTokenB) - vsa2 := restapi.ScanRestAPI(o, ss) - r.AddScanAttempt(vsa2) + vsa2, err := request.ScanURL(o, &ss) + if err != nil { + return r, err + } + r.AddScanAttempt(vsa2) r.End() if vsa1.Response.StatusCode != vsa2.Response.StatusCode { diff --git a/scan/jwt/null_signature.go b/scan/jwt/null_signature.go index 8733a27..e1e70a9 100644 --- a/scan/jwt/null_signature.go +++ b/scan/jwt/null_signature.go @@ -4,7 +4,7 @@ import ( "strings" "github.com/cerberauth/vulnapi/internal/auth" - restapi "github.com/cerberauth/vulnapi/internal/rest_api" + "github.com/cerberauth/vulnapi/internal/request" "github.com/cerberauth/vulnapi/report" ) @@ -24,7 +24,7 @@ func createNewJWTWithoutSignature(originalTokenString string) (string, error) { return strings.Join([]string{parts[0], parts[1], ""}, "."), nil } -func NullSignatureScanHandler(o *auth.Operation, ss auth.SecurityScheme) (*report.ScanReport, error) { +func NullSignatureScanHandler(o *request.Operation, ss auth.SecurityScheme) (*report.ScanReport, error) { r := report.NewScanReport() token := ss.GetValidValue().(string) @@ -33,8 +33,11 @@ func NullSignatureScanHandler(o *auth.Operation, ss auth.SecurityScheme) (*repor return r, err } ss.SetAttackValue(newToken) - vsa := restapi.ScanRestAPI(o, ss) + vsa, err := request.ScanURL(o, &ss) r.AddScanAttempt(vsa).End() + if err != nil { + return r, err + } if vsa.Response.StatusCode < 300 { r.AddVulnerabilityReport(&report.VulnerabilityReport{ diff --git a/scan/jwt/weak_secret.go b/scan/jwt/weak_secret.go index fb70bcb..a9a2ace 100644 --- a/scan/jwt/weak_secret.go +++ b/scan/jwt/weak_secret.go @@ -2,17 +2,17 @@ package jwt import ( "github.com/cerberauth/vulnapi/internal/auth" - restapi "github.com/cerberauth/vulnapi/internal/rest_api" + "github.com/cerberauth/vulnapi/internal/request" "github.com/cerberauth/vulnapi/report" ) const ( WeakSecretVulnerabilitySeverityLevel = 9 - WeakSecretVulnerabilityName = "Weak Secret Vulnerability" - WeakSecretVulnerabilityDescription = "JWT is signed with a weak secret allowing attackers to issue valid JWT." + WeakSecretVulnerabilityName = "JWT Weak Secret" + WeakSecretVulnerabilityDescription = "JWT secret is weak and can be easily guessed." ) -func BlankSecretScanHandler(o *auth.Operation, ss auth.SecurityScheme) (*report.ScanReport, error) { +func BlankSecretScanHandler(o *request.Operation, ss auth.SecurityScheme) (*report.ScanReport, error) { r := report.NewScanReport() token := ss.GetValidValue().(string) @@ -21,8 +21,11 @@ func BlankSecretScanHandler(o *auth.Operation, ss auth.SecurityScheme) (*report. return r, err } ss.SetAttackValue(newToken) - vsa := restapi.ScanRestAPI(o, ss) + vsa, err := request.ScanURL(o, &ss) r.AddScanAttempt(vsa).End() + if err != nil { + return r, err + } if vsa.Response.StatusCode < 300 { r.AddVulnerabilityReport(&report.VulnerabilityReport{ @@ -36,10 +39,10 @@ func BlankSecretScanHandler(o *auth.Operation, ss auth.SecurityScheme) (*report. return r, nil } -func DictSecretScanHandler(o *auth.Operation, ss auth.SecurityScheme) (*report.ScanReport, error) { +func DictSecretScanHandler(o *request.Operation, ss auth.SecurityScheme) (*report.ScanReport, error) { r := report.NewScanReport() - // Use a dictionary attack to try finding the secret + // TODO: Use a dictionary attack to try finding the secret r.End() diff --git a/scan/openapi.go b/scan/openapi.go index 51cb865..42fe508 100644 --- a/scan/openapi.go +++ b/scan/openapi.go @@ -8,7 +8,8 @@ import ( "github.com/brianvoe/gofakeit/v6" "github.com/cerberauth/vulnapi/internal/auth" - restapi "github.com/cerberauth/vulnapi/internal/rest_api" + "github.com/cerberauth/vulnapi/internal/openapi" + "github.com/cerberauth/vulnapi/internal/request" "github.com/cerberauth/vulnapi/report" "github.com/getkin/kin-openapi/openapi3" stduritemplate "github.com/std-uritemplate/std-uritemplate/go" @@ -93,7 +94,7 @@ func getOperationPath(p string, params openapi3.Parameters) (string, error) { } func NewOpenAPIScan(openAPIUrlOrPath string, validToken *string, reporter *report.Reporter) (*Scan, error) { - doc, err := restapi.LoadOpenAPI(openAPIUrlOrPath) + doc, err := openapi.LoadOpenAPI(openAPIUrlOrPath) if err != nil { return nil, err } @@ -113,7 +114,7 @@ func NewOpenAPIScan(openAPIUrlOrPath string, validToken *string, reporter *repor } } - operations := auth.Operations{} + operations := request.Operations{} for docPath, p := range doc.Paths { for method, o := range p.Operations() { headers := http.Header{} @@ -148,7 +149,7 @@ func NewOpenAPIScan(openAPIUrlOrPath string, validToken *string, reporter *repor operationUrl := *baseUrl operationUrl.Path = path.Join(operationUrl.Path, operationPath) - operations = append(operations, auth.Operation{ + operations = append(operations, request.Operation{ Url: operationUrl.String(), Method: method, Headers: &headers, diff --git a/scan/openapi_test.go b/scan/openapi_test.go index b475e8b..6765fd9 100644 --- a/scan/openapi_test.go +++ b/scan/openapi_test.go @@ -6,6 +6,7 @@ import ( "github.com/brianvoe/gofakeit/v6" "github.com/cerberauth/vulnapi/internal/auth" + "github.com/cerberauth/vulnapi/internal/request" "github.com/cerberauth/vulnapi/report" "github.com/cerberauth/vulnapi/scan" "github.com/stretchr/testify/assert" @@ -18,7 +19,7 @@ func TestNewOpenAPIScan(t *testing.T) { require.NoError(t, err) assert.Equal(t, &scan.Scan{ - Operations: auth.Operations{{ + Operations: request.Operations{{ Method: "GET", Url: "http://localhost:8080/", Headers: &http.Header{}, diff --git a/scan/scan.go b/scan/scan.go index db0a9c1..dc51596 100644 --- a/scan/scan.go +++ b/scan/scan.go @@ -4,19 +4,19 @@ import ( "fmt" "github.com/cerberauth/vulnapi/internal/auth" - restapi "github.com/cerberauth/vulnapi/internal/rest_api" + "github.com/cerberauth/vulnapi/internal/request" "github.com/cerberauth/vulnapi/report" ) -type ScanHandler func(o *auth.Operation, ss auth.SecurityScheme) (*report.ScanReport, error) +type ScanHandler func(o *request.Operation, ss auth.SecurityScheme) (*report.ScanReport, error) type Scan struct { - Operations auth.Operations + Operations request.Operations Handlers []ScanHandler Reporter *report.Reporter } -func NewScan(operations auth.Operations, reporter *report.Reporter) (*Scan, error) { +func NewScan(operations request.Operations, reporter *report.Reporter) (*Scan, error) { if len(operations) == 0 { return nil, fmt.Errorf("a scan must have at least one operation") } @@ -60,37 +60,37 @@ func (s *Scan) Execute() (*report.Reporter, []error, error) { return s.Reporter, errors, nil } -func (s *Scan) ExecuteOperation(o *auth.Operation) ([]error, error) { - if len(o.SecuritySchemes) == 0 { +func (s *Scan) ExecuteOperation(operation *request.Operation) ([]error, error) { + if len(operation.SecuritySchemes) == 0 { return nil, fmt.Errorf("no security schemes has been configured") } var errors []error for _, handler := range s.Handlers { - rep, err := handler(o, o.SecuritySchemes[0]) + report, err := handler(operation, operation.SecuritySchemes[0]) // TODO: handle multiple security schemes if err != nil { errors = append(errors, err) } - s.Reporter.AddReport(rep) + s.Reporter.AddReport(report) } return errors, nil } -func (s *Scan) ValidateOperation(o *auth.Operation) error { - if len(o.SecuritySchemes) == 0 { +func (s *Scan) ValidateOperation(operation *request.Operation) error { + if len(operation.SecuritySchemes) == 0 { return fmt.Errorf("no security schemes has been configured") } - r := restapi.ScanRestAPI(o, o.SecuritySchemes[0]) - if r.Err != nil { - return r.Err + attempt, err := request.ScanURL(operation, &operation.SecuritySchemes[0]) + if err != nil { + return err } - if r.Response.StatusCode >= 300 { - return fmt.Errorf("the request with the passed JWT should return 2xx status code") + if attempt.Err != nil { + return attempt.Err } return nil diff --git a/scan/scan_test.go b/scan/scan_test.go index eb44154..8a7dbcd 100644 --- a/scan/scan_test.go +++ b/scan/scan_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/cerberauth/vulnapi/internal/auth" + "github.com/cerberauth/vulnapi/internal/request" "github.com/cerberauth/vulnapi/report" "github.com/cerberauth/vulnapi/scan" "github.com/stretchr/testify/assert" @@ -12,13 +13,13 @@ import ( ) func TestNewScanWithNoOperations(t *testing.T) { - _, err := scan.NewScan(auth.Operations{}, nil) + _, err := scan.NewScan(request.Operations{}, nil) require.Error(t, err) } func TestNewScan(t *testing.T) { - operations := auth.Operations{{ + operations := request.Operations{{ Method: "GET", Url: "http://localhost:8080", Headers: &http.Header{}, @@ -38,7 +39,7 @@ func TestNewScan(t *testing.T) { } func TestNewScanWithReporter(t *testing.T) { - operations := auth.Operations{{ + operations := request.Operations{{ Method: "GET", Url: "http://localhost:8080", Headers: &http.Header{}, diff --git a/scan/url.go b/scan/url.go index 6c21790..356566b 100644 --- a/scan/url.go +++ b/scan/url.go @@ -5,6 +5,7 @@ import ( "strings" "github.com/cerberauth/vulnapi/internal/auth" + "github.com/cerberauth/vulnapi/internal/request" "github.com/cerberauth/vulnapi/report" ) @@ -51,7 +52,7 @@ func NewURLScan(method string, url string, headers *http.Header, cookies []http. securitySchemes = append(securitySchemes, securityScheme) } - operations := auth.Operations{{ + operations := request.Operations{{ Url: url, Method: method, Headers: headers, diff --git a/scan/url_test.go b/scan/url_test.go index cb75e96..05890e6 100644 --- a/scan/url_test.go +++ b/scan/url_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/cerberauth/vulnapi/internal/auth" + "github.com/cerberauth/vulnapi/internal/request" "github.com/cerberauth/vulnapi/report" "github.com/cerberauth/vulnapi/scan" "github.com/stretchr/testify/assert" @@ -16,7 +17,7 @@ func TestNewURLScan(t *testing.T) { require.NoError(t, err) assert.Equal(t, &scan.Scan{ - Operations: auth.Operations{{ + Operations: request.Operations{{ Method: "GET", Url: "http://localhost:8080", Headers: &http.Header{}, @@ -35,7 +36,7 @@ func TestNewURLScanWithHeaders(t *testing.T) { require.NoError(t, err) assert.Equal(t, &scan.Scan{ - Operations: auth.Operations{{ + Operations: request.Operations{{ Method: "GET", Url: "http://localhost:8080", Headers: &headers, @@ -56,7 +57,7 @@ func TestNewURLScanWithCookies(t *testing.T) { require.NoError(t, err) assert.Equal(t, &scan.Scan{ - Operations: auth.Operations{{ + Operations: request.Operations{{ Method: "GET", Url: "http://localhost:8080", Headers: &http.Header{}, @@ -76,7 +77,7 @@ func TestNewURLScanWithUpperCaseAuthorizationHeader(t *testing.T) { require.NoError(t, err) assert.Equal(t, &scan.Scan{ - Operations: auth.Operations{{ + Operations: request.Operations{{ Method: "GET", Url: "http://localhost:8080", Headers: &headers, @@ -98,7 +99,7 @@ func TestNewURLScanWithUpperCaseAuthorizationAndLowerCaseBearerHeader(t *testing require.NoError(t, err) assert.Equal(t, &scan.Scan{ - Operations: auth.Operations{{ + Operations: request.Operations{{ Method: "GET", Url: "http://localhost:8080", Headers: &headers, @@ -120,7 +121,7 @@ func TestNewURLScanWithLowerCaseAuthorizationHeader(t *testing.T) { require.NoError(t, err) assert.Equal(t, &scan.Scan{ - Operations: auth.Operations{{ + Operations: request.Operations{{ Method: "GET", Url: "http://localhost:8080", Headers: &headers,