Skip to content

Commit 898ebf6

Browse files
committed
fix(lint): clear golangci-lint findings for CI green
1 parent 16cbc2e commit 898ebf6

13 files changed

Lines changed: 51 additions & 46 deletions

File tree

api_security.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package inspect
22

33
import (
4+
"context"
45
"encoding/base64"
56
"encoding/json"
67
"fmt"
@@ -40,8 +41,8 @@ func (a *APISecurityChecker) httpClient() *http.Client {
4041
}
4142

4243
// newRequest creates a request with the configured headers.
43-
func (a *APISecurityChecker) newRequest(method, url string, body io.Reader) (*http.Request, error) {
44-
req, err := http.NewRequest(method, url, body)
44+
func (a *APISecurityChecker) newRequest(ctx context.Context, method, url string, body io.Reader) (*http.Request, error) {
45+
req, err := http.NewRequestWithContext(ctx, method, url, body)
4546
if err != nil {
4647
return nil, err
4748
}
@@ -64,7 +65,7 @@ func (a *APISecurityChecker) CheckCORS(url string) []Finding {
6465
}
6566

6667
for _, origin := range testOrigins {
67-
req, err := a.newRequest("GET", url, nil)
68+
req, err := a.newRequest(context.Background(), "GET", url, nil)
6869
if err != nil {
6970
continue
7071
}
@@ -131,7 +132,7 @@ func (a *APISecurityChecker) CheckRateLimiting(url string) []Finding {
131132
var rateLimitHeaderFound bool
132133

133134
for i := 0; i < requestCount; i++ {
134-
req, err := a.newRequest("GET", url, nil)
135+
req, err := a.newRequest(context.Background(), "GET", url, nil)
135136
if err != nil {
136137
continue
137138
}
@@ -179,7 +180,7 @@ func (a *APISecurityChecker) CheckAuthHeaders(url string) []Finding {
179180
var findings []Finding
180181
client := a.httpClient()
181182

182-
req, err := a.newRequest("GET", url, nil)
183+
req, err := a.newRequest(context.Background(), "GET", url, nil)
183184
if err != nil {
184185
return findings
185186
}
@@ -246,7 +247,7 @@ func (a *APISecurityChecker) CheckVerbTampering(url string) []Finding {
246247
}
247248

248249
for _, m := range dangerousMethods {
249-
req, err := a.newRequest(m.Method, url, nil)
250+
req, err := a.newRequest(context.Background(), m.Method, url, nil)
250251
if err != nil {
251252
continue
252253
}
@@ -285,7 +286,7 @@ func (a *APISecurityChecker) CheckVerbTampering(url string) []Finding {
285286
}
286287

287288
// Check OPTIONS to see what methods are advertised
288-
req, err := a.newRequest("OPTIONS", url, nil)
289+
req, err := a.newRequest(context.Background(), "OPTIONS", url, nil)
289290
if err == nil {
290291
resp, err := client.Do(req)
291292
if err == nil {
@@ -357,7 +358,7 @@ func (a *APISecurityChecker) CheckErrorLeakage(url string) []Finding {
357358
bodyReader = strings.NewReader(mr.Body)
358359
}
359360

360-
req, err := a.newRequest(mr.Method, mr.Path, bodyReader)
361+
req, err := a.newRequest(context.Background(), mr.Method, mr.Path, bodyReader)
361362
if err != nil {
362363
continue
363364
}

check.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ func (r *ruleCheckAdapter) Run(ctx context.Context, pages []*crawler.Page) []che
295295
for _, h := range r.rule.HeaderMissing {
296296
if page.Headers.Get(h) == "" {
297297
findings = append(findings, check.Finding{
298-
Severity: check.Severity(r.rule.RuleSeverity),
298+
Severity: r.rule.RuleSeverity,
299299
URL: page.URL,
300300
Message: r.rule.Description + ": missing header " + h,
301301
Fix: r.rule.FixSuggestion,
@@ -311,7 +311,7 @@ func (r *ruleCheckAdapter) Run(ctx context.Context, pages []*crawler.Page) []che
311311
}
312312
if matchWithTimeout(re, val) {
313313
findings = append(findings, check.Finding{
314-
Severity: check.Severity(r.rule.RuleSeverity),
314+
Severity: r.rule.RuleSeverity,
315315
URL: page.URL,
316316
Message: r.rule.Description,
317317
Evidence: header + ": " + val,
@@ -326,7 +326,7 @@ func (r *ruleCheckAdapter) Run(ctx context.Context, pages []*crawler.Page) []che
326326
for _, re := range r.bodyRegexs {
327327
if loc := findWithTimeout(re, body); loc != "" {
328328
findings = append(findings, check.Finding{
329-
Severity: check.Severity(r.rule.RuleSeverity),
329+
Severity: r.rule.RuleSeverity,
330330
URL: page.URL,
331331
Message: r.rule.Description,
332332
Evidence: truncateEvidence(loc, 100),
@@ -340,7 +340,7 @@ func (r *ruleCheckAdapter) Run(ctx context.Context, pages []*crawler.Page) []che
340340
for _, re := range r.bodyMissing {
341341
if !matchWithTimeout(re, body) {
342342
findings = append(findings, check.Finding{
343-
Severity: check.Severity(r.rule.RuleSeverity),
343+
Severity: r.rule.RuleSeverity,
344344
URL: page.URL,
345345
Message: r.rule.Description + ": expected pattern not found",
346346
Fix: r.rule.FixSuggestion,
@@ -385,7 +385,7 @@ func (a *customCheckAdapter) Run(ctx context.Context, pages []*crawler.Page) []c
385385
internal := make([]check.Finding, len(findings))
386386
for i, f := range findings {
387387
internal[i] = check.Finding{
388-
Severity: check.Severity(f.Severity),
388+
Severity: f.Severity,
389389
URL: f.URL,
390390
Element: f.Element,
391391
Message: f.Message,

ci_output.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@ func (ci *CIOutput) formatGitHub(findings []Finding) string {
3131
var sb strings.Builder
3232
for _, f := range findings {
3333
level := "warning"
34-
if f.Severity == SeverityCritical || f.Severity == SeverityHigh {
34+
switch f.Severity {
35+
case SeverityCritical, SeverityHigh:
3536
level = "error"
36-
} else if f.Severity == SeverityInfo {
37+
case SeverityInfo:
3738
level = "notice"
3839
}
3940
sb.WriteString(fmt.Sprintf("::%s file=%s,line=%d::%s\n", level, f.URL, 0, f.Message))

internal/check/a11y.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func (a *A11yCheck) checkPage(page *crawler.Page) []Finding {
5454
findings = append(findings, Finding{
5555
Severity: SeverityHigh,
5656
URL: page.URL,
57-
Element: fmt.Sprintf(`<img src="%s">`, truncateStr(src, 60)),
57+
Element: fmt.Sprintf(`<img src=%q>`, truncateStr(src, 60)),
5858
Message: "Image missing alt attribute",
5959
Fix: "Add descriptive alt text or alt=\"\" for decorative images",
6060
})
@@ -67,7 +67,7 @@ func (a *A11yCheck) checkPage(page *crawler.Page) []Finding {
6767
findings = append(findings, Finding{
6868
Severity: SeverityMedium,
6969
URL: page.URL,
70-
Element: fmt.Sprintf(`<a href="%s">`, truncateStr(href, 60)),
70+
Element: fmt.Sprintf(`<a href=%q>`, truncateStr(href, 60)),
7171
Message: "Link has no accessible text",
7272
Fix: "Add visible text, aria-label, or aria-labelledby to the link",
7373
})
@@ -94,7 +94,7 @@ func (a *A11yCheck) checkPage(page *crawler.Page) []Finding {
9494
findings = append(findings, Finding{
9595
Severity: SeverityMedium,
9696
URL: page.URL,
97-
Element: fmt.Sprintf(`<input name="%s">`, name),
97+
Element: fmt.Sprintf(`<input name=%q>`, name),
9898
Message: "Form input has no associated label",
9999
Fix: "Add a <label for=\"...\"> or aria-label attribute",
100100
})

internal/check/links.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ func (l *LinksCheck) Run(ctx context.Context, pages []*crawler.Page) []Finding {
103103
findings = append(findings, Finding{
104104
Severity: SeverityMedium,
105105
URL: page.URL,
106-
Element: fmt.Sprintf(`<a href="%s">`, truncateHref(link.Href, 80)),
106+
Element: fmt.Sprintf(`<a href=%q>`, truncateHref(link.Href, 80)),
107107
Message: fmt.Sprintf("Fragment #%s not found on target page", fragment),
108108
Fix: "Add an element with id=\"" + fragment + "\" on the target page, or fix the link",
109109
Evidence: fmt.Sprintf("Target: %s", resolved),
@@ -224,7 +224,7 @@ func (l *LinksCheck) checkExternalLinkWithDetector(ctx context.Context, pageURL,
224224
return &Finding{
225225
Severity: SeverityHigh,
226226
URL: pageURL,
227-
Element: fmt.Sprintf(`<a href="%s">`, href),
227+
Element: fmt.Sprintf(`<a href=%q>`, href),
228228
Message: fmt.Sprintf("External link unreachable: %s", resolved),
229229
Fix: "Remove or update the broken link",
230230
Evidence: err.Error(),
@@ -250,7 +250,7 @@ func (l *LinksCheck) checkExternalLinkWithDetector(ctx context.Context, pageURL,
250250
return &Finding{
251251
Severity: severityForStatus(getResp.StatusCode),
252252
URL: pageURL,
253-
Element: fmt.Sprintf(`<a href="%s">`, href),
253+
Element: fmt.Sprintf(`<a href=%q>`, href),
254254
Message: fmt.Sprintf("External link returns HTTP %d: %s", getResp.StatusCode, resolved),
255255
Fix: "Remove or update the broken link",
256256
}
@@ -262,7 +262,7 @@ func (l *LinksCheck) checkExternalLinkWithDetector(ctx context.Context, pageURL,
262262
return &Finding{
263263
Severity: severityForStatus(resp.StatusCode),
264264
URL: pageURL,
265-
Element: fmt.Sprintf(`<a href="%s">`, href),
265+
Element: fmt.Sprintf(`<a href=%q>`, href),
266266
Message: fmt.Sprintf("External link returns HTTP %d: %s", resp.StatusCode, resolved),
267267
Fix: "Remove or update the broken link",
268268
}

internal/check/perf.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func (p *PerfCheck) checkPage(page *crawler.Page) []Finding {
7070
findings = append(findings, Finding{
7171
Severity: SeverityMedium,
7272
URL: page.URL,
73-
Element: fmt.Sprintf(`<script src="%s">`, truncateStr(src, 60)),
73+
Element: fmt.Sprintf(`<script src=%q>`, truncateStr(src, 60)),
7474
Message: "Render-blocking script in <head> without async or defer",
7575
Fix: "Add async or defer attribute, or move to end of <body>",
7676
})
@@ -83,7 +83,7 @@ func (p *PerfCheck) checkPage(page *crawler.Page) []Finding {
8383
findings = append(findings, Finding{
8484
Severity: SeverityLow,
8585
URL: page.URL,
86-
Element: fmt.Sprintf(`<link href="%s">`, truncateStr(href, 60)),
86+
Element: fmt.Sprintf(`<link href=%q>`, truncateStr(href, 60)),
8787
Message: "Render-blocking stylesheet without media query",
8888
Fix: "Add media attribute for non-critical CSS or load asynchronously",
8989
})
@@ -97,7 +97,7 @@ func (p *PerfCheck) checkPage(page *crawler.Page) []Finding {
9797
findings = append(findings, Finding{
9898
Severity: SeverityLow,
9999
URL: page.URL,
100-
Element: fmt.Sprintf(`<img src="%s">`, truncateStr(src, 60)),
100+
Element: fmt.Sprintf(`<img src=%q>`, truncateStr(src, 60)),
101101
Message: "Image missing width/height attributes (causes layout shift)",
102102
Fix: "Add explicit width and height attributes to prevent CLS",
103103
})
@@ -111,7 +111,7 @@ func (p *PerfCheck) checkPage(page *crawler.Page) []Finding {
111111
findings = append(findings, Finding{
112112
Severity: SeverityLow,
113113
URL: page.URL,
114-
Element: fmt.Sprintf(`<img src="%s">`, truncateStr(src, 60)),
114+
Element: fmt.Sprintf(`<img src=%q>`, truncateStr(src, 60)),
115115
Message: "Image missing loading=\"lazy\" attribute",
116116
Fix: "Add loading=\"lazy\" for below-fold images",
117117
})

internal/check/reachability.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ func extractResourceRefs(page *crawler.Page) []resourceRef {
186186
if src := getAttr(n, "src"); src != "" {
187187
refs = append(refs, resourceRef{
188188
URL: src,
189-
Element: fmt.Sprintf(`<img src="%s">`, truncateResRef(src, 80)),
189+
Element: fmt.Sprintf(`<img src=%q>`, truncateResRef(src, 80)),
190190
PageURL: page.URL,
191191
Resource: "image",
192192
})
@@ -195,7 +195,7 @@ func extractResourceRefs(page *crawler.Page) []resourceRef {
195195
if src := getAttr(n, "src"); src != "" {
196196
refs = append(refs, resourceRef{
197197
URL: src,
198-
Element: fmt.Sprintf(`<script src="%s">`, truncateResRef(src, 80)),
198+
Element: fmt.Sprintf(`<script src=%q>`, truncateResRef(src, 80)),
199199
PageURL: page.URL,
200200
Resource: "script",
201201
})
@@ -206,7 +206,7 @@ func extractResourceRefs(page *crawler.Page) []resourceRef {
206206
if href := getAttr(n, "href"); href != "" {
207207
refs = append(refs, resourceRef{
208208
URL: href,
209-
Element: fmt.Sprintf(`<link rel="stylesheet" href="%s">`, truncateResRef(href, 80)),
209+
Element: fmt.Sprintf(`<link rel="stylesheet" href=%q>`, truncateResRef(href, 80)),
210210
PageURL: page.URL,
211211
Resource: "stylesheet",
212212
})
@@ -216,7 +216,7 @@ func extractResourceRefs(page *crawler.Page) []resourceRef {
216216
if href := getAttr(n, "href"); href != "" {
217217
refs = append(refs, resourceRef{
218218
URL: href,
219-
Element: fmt.Sprintf(`<link rel="%s" href="%s">`, rel, truncateResRef(href, 80)),
219+
Element: fmt.Sprintf(`<link rel=%q href=%q>`, rel, truncateResRef(href, 80)),
220220
PageURL: page.URL,
221221
Resource: "preload",
222222
})
@@ -226,7 +226,7 @@ func extractResourceRefs(page *crawler.Page) []resourceRef {
226226
if src := getAttr(n, "src"); src != "" {
227227
refs = append(refs, resourceRef{
228228
URL: src,
229-
Element: fmt.Sprintf(`<video src="%s">`, truncateResRef(src, 80)),
229+
Element: fmt.Sprintf(`<video src=%q>`, truncateResRef(src, 80)),
230230
PageURL: page.URL,
231231
Resource: "media",
232232
})
@@ -235,7 +235,7 @@ func extractResourceRefs(page *crawler.Page) []resourceRef {
235235
if src := getAttr(n, "src"); src != "" {
236236
refs = append(refs, resourceRef{
237237
URL: src,
238-
Element: fmt.Sprintf(`<audio src="%s">`, truncateResRef(src, 80)),
238+
Element: fmt.Sprintf(`<audio src=%q>`, truncateResRef(src, 80)),
239239
PageURL: page.URL,
240240
Resource: "media",
241241
})
@@ -244,7 +244,7 @@ func extractResourceRefs(page *crawler.Page) []resourceRef {
244244
if src := getAttr(n, "src"); src != "" {
245245
refs = append(refs, resourceRef{
246246
URL: src,
247-
Element: fmt.Sprintf(`<source src="%s">`, truncateResRef(src, 80)),
247+
Element: fmt.Sprintf(`<source src=%q>`, truncateResRef(src, 80)),
248248
PageURL: page.URL,
249249
Resource: "media",
250250
})
@@ -253,7 +253,7 @@ func extractResourceRefs(page *crawler.Page) []resourceRef {
253253
if src := getAttr(n, "src"); src != "" {
254254
refs = append(refs, resourceRef{
255255
URL: src,
256-
Element: fmt.Sprintf(`<iframe src="%s">`, truncateResRef(src, 80)),
256+
Element: fmt.Sprintf(`<iframe src=%q>`, truncateResRef(src, 80)),
257257
PageURL: page.URL,
258258
Resource: "iframe",
259259
})

internal/check/sri.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ func (s *SRICheck) checkSRI(pageURL string, n *html.Node, tag, src string) []Fin
6868
integrity := getAttr(n, "integrity")
6969
crossorigin := getAttr(n, "crossorigin")
7070

71-
element := fmt.Sprintf(`<%s src="%s">`, tag, truncateStr(src, 60))
71+
element := fmt.Sprintf(`<%s src=%q>`, tag, truncateStr(src, 60))
7272
if tag == "link" {
73-
element = fmt.Sprintf(`<link href="%s">`, truncateStr(src, 60))
73+
element = fmt.Sprintf(`<link href=%q>`, truncateStr(src, 60))
7474
}
7575

7676
if integrity == "" {

internal/crawler/parse_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,8 +288,9 @@ func TestExtractLinks_TrackElement(t *testing.T) {
288288
func TestExtractLinks_EmptyBody(t *testing.T) {
289289
links := extractLinks("https://example.com", []byte(""))
290290
// html.Parse handles empty input gracefully
291-
if links == nil {
292-
// This is fine; empty body produces no links
291+
// Empty body produces no links (nil slice is fine).
292+
if len(links) != 0 {
293+
t.Fatalf("expected no links, got %d", len(links))
293294
}
294295
}
295296

internal/crawler/serve.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ func ServeDir(ctx context.Context, dir string) (*http.Server, string, error) {
2121
ReadHeaderTimeout: 5 * time.Second,
2222
}
2323

24-
go srv.Serve(listener)
24+
go func() { _ = srv.Serve(listener) }()
2525

2626
return srv, listener.Addr().String(), nil
2727
}

0 commit comments

Comments
 (0)