Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 11, 14:45 UTC
chore: Add nolints to work around haywire linters (#7493)
* chore: Add nolints to work around haywire linters * More lint wrangling
Matt Holt committed
Feb 17, 2026 at 16:52 UTC
95941a71e87d6ccd6318bfd95c56929b01edfafd
19 files changed
+25
-22
caddyconfig/httploader.go
+1
-1
@@ -136,7 +136,7 @@ func (hl HTTPLoader) LoadConfig(ctx caddy.Context) ([]byte, error) {
136
}
137
138
func attemptHttpCall(client *http.Client, request *http.Request) (*http.Response, error) {
139
- resp, err := client.Do(request)
139
+ resp, err := client.Do(request) //nolint:gosec // no SSRF; comes from trusted config
140
if err != nil {
141
return nil, fmt.Errorf("problem calling http loader url: %v", err)
142
} else if resp.StatusCode < 200 || resp.StatusCode > 499 {
caddyconfig/load.go
+1
-1
@@ -106,7 +106,7 @@ func (adminLoad) handleLoad(w http.ResponseWriter, r *http.Request) error {
106
if err != nil {
107
caddy.Log().Named("admin.api.load").Error(err.Error())
108
}
109
- _, _ = w.Write(respBody)
109
+ _, _ = w.Write(respBody) //nolint:gosec // false positive: no XSS here
110
}
111
body = result
112
}
caddytest/caddytest.go
+3
-3
@@ -187,7 +187,7 @@ func (tc *Tester) initServer(rawConfig string, configType string) error {
187
req.Header.Add("Content-Type", "text/"+configType)
188
}
189
190
- res, err := client.Do(req)
190
+ res, err := client.Do(req) //nolint:gosec // no SSRF because URL is hard-coded to localhost, and port comes from config
191
if err != nil {
192
tc.t.Errorf("unable to contact caddy server. %s", err)
193
return err
@@ -279,7 +279,7 @@ func validateTestPrerequisites(tc *Tester) error {
279
return err
280
}
281
tc.t.Cleanup(func() {
282
- os.Remove(f.Name())
282
+ os.Remove(f.Name()) //nolint:gosec // false positive, filename comes from std lib, no path traversal
283
})
284
if _, err := fmt.Fprintf(f, initConfig, tc.config.AdminPort); err != nil {
285
return err
@@ -506,7 +506,7 @@ func applyHeaders(t testing.TB, req *http.Request, requestHeaders []string) {
506
func (tc *Tester) AssertResponseCode(req *http.Request, expectedStatusCode int) *http.Response {
507
tc.t.Helper()
508
509
- resp, err := tc.Client.Do(req)
509
+ resp, err := tc.Client.Do(req) //nolint:gosec // no SSRFs demonstrated
510
if err != nil {
511
tc.t.Fatalf("failed to call server %s", err)
512
}
caddytest/integration/acmeserver_test.go
+2
-2
@@ -127,7 +127,7 @@ func TestACMEServerAllowPolicy(t *testing.T) {
127
_, err := client.ObtainCertificateForSANs(ctx, account, certPrivateKey, []string{"not-matching.localhost"})
128
if err == nil {
129
t.Errorf("obtaining certificate for 'not-matching.localhost' domain")
130
- } else if err != nil && !strings.Contains(err.Error(), "urn:ietf:params:acme:error:rejectedIdentifier") {
130
+ } else if !strings.Contains(err.Error(), "urn:ietf:params:acme:error:rejectedIdentifier") {
131
t.Logf("unexpected error: %v", err)
132
}
133
}
@@ -200,7 +200,7 @@ func TestACMEServerDenyPolicy(t *testing.T) {
200
_, err := client.ObtainCertificateForSANs(ctx, account, certPrivateKey, []string{"deny.localhost"})
201
if err == nil {
202
t.Errorf("obtaining certificate for 'deny.localhost' domain")
203
- } else if err != nil && !strings.Contains(err.Error(), "urn:ietf:params:acme:error:rejectedIdentifier") {
203
+ } else if !strings.Contains(err.Error(), "urn:ietf:params:acme:error:rejectedIdentifier") {
204
t.Logf("unexpected error: %v", err)
205
}
206
}
cmd/commandfuncs.go
+2
-2
@@ -74,7 +74,7 @@ func cmdStart(fl Flags) (int, error) {
74
// ensure it's the process we're expecting - we can be
75
// sure by giving it some random bytes and having it echo
76
// them back to us)
77
- cmd := exec.Command(os.Args[0], "run", "--pingback", ln.Addr().String())
77
+ cmd := exec.Command(os.Args[0], "run", "--pingback", ln.Addr().String()) //nolint:gosec // no command injection that I can determine...
78
// we should be able to run caddy in relative paths
79
if errors.Is(cmd.Err, exec.ErrDot) {
80
cmd.Err = nil
@@ -820,7 +820,7 @@ func AdminAPIRequest(adminAddr, method, uri string, headers http.Header, body io
820
},
821
}
822
823
- resp, err := client.Do(req)
823
+ resp, err := client.Do(req) //nolint:gosec // the only SSRF here would be self-sabatoge I think
824
if err != nil {
825
return nil, fmt.Errorf("performing request: %v", err)
826
}
modules/caddyhttp/caddyauth/basicauth.go
+1
-1
@@ -287,7 +287,7 @@ type Account struct {
287
288
// The user's hashed password, in Modular Crypt Format (with `$` prefix)
289
// or base64-encoded.
290
- Password string `json:"password"`
290
+ Password string `json:"password"` //nolint:gosec // false positive, this is a hashed password
291
292
password []byte
293
}
modules/caddyhttp/celmatcher.go
+2
@@ -412,10 +412,12 @@ func CELMatcherImpl(macroName, funcName string, matcherDataTypes []*cel.Type, fa
412
return nil, fmt.Errorf("unsupported matcher data type: %s, %s", matcherDataTypes[0], matcherDataTypes[1])
413
}
414
case 3:
415
+ // nolint:gosec // false positive, impossible to be out of bounds; see: https://github.com/securego/gosec/issues/1525
416
if matcherDataTypes[0] == cel.StringType && matcherDataTypes[1] == cel.StringType && matcherDataTypes[2] == cel.StringType {
417
macro = parser.NewGlobalMacro(macroName, 3, celMatcherStringListMacroExpander(funcName))
418
matcherDataTypes = []*cel.Type{cel.ListType(cel.StringType)}
419
} else {
420
+ // nolint:gosec // false positive, impossible to be out of bounds; see: https://github.com/securego/gosec/issues/1525
421
return nil, fmt.Errorf("unsupported matcher data type: %s, %s, %s", matcherDataTypes[0], matcherDataTypes[1], matcherDataTypes[2])
422
}
423
}
modules/caddyhttp/fileserver/browse.go
+1
@@ -169,6 +169,7 @@ func (fsrv *FileServer) serveBrowse(fileSystem fs.FS, root, dirPath string, w ht
169
170
// Actual files
171
for _, item := range listing.Items {
172
+ //nolint:gosec // not sure how this could be XSS unless you lose control of the file system (like aren't sanitizing) and client ignores Content-Type of text/plain
173
if _, err := fmt.Fprintf(writer, "%s\t%s\t%s\n",
174
item.Name, item.HumanSize(), item.HumanModTime("January 2, 2006 at 15:04:05"),
175
); err != nil {
modules/caddyhttp/reverseproxy/healthchecks.go
+1
-1
@@ -500,7 +500,7 @@ func (h *Handler) doActiveHealthCheck(dialInfo DialInfo, hostAddr string, networ
500
}
501
502
// do the request, being careful to tame the response body
503
- resp, err := h.HealthChecks.Active.httpClient.Do(req)
503
+ resp, err := h.HealthChecks.Active.httpClient.Do(req) //nolint:gosec // no SSRF
504
if err != nil {
505
if c := h.HealthChecks.Active.logger.Check(zapcore.InfoLevel, "HTTP request failed"); c != nil {
506
c.Write(
modules/caddyhttp/reverseproxy/selectionpolicies.go
+1
-1
@@ -617,7 +617,7 @@ type CookieHashSelection struct {
617
// The HTTP cookie name whose value is to be hashed and used for upstream selection.
618
Name string `json:"name,omitempty"`
619
// Secret to hash (Hmac256) chosen upstream in cookie
620
- Secret string `json:"secret,omitempty"`
620
+ Secret string `json:"secret,omitempty"` //nolint:gosec // yes it's exported because it needs to encode to JSON
621
// The cookie's Max-Age before it expires. Default is no expiry.
622
MaxAge caddy.Duration `json:"max_age,omitempty"`
623
modules/caddyhttp/reverseproxy/streaming.go
+1
-1
@@ -529,7 +529,7 @@ func maskBytes(key [4]byte, pos int, b []byte) int {
529
// Create aligned word size key.
530
var k [wordSize]byte
531
for i := range k {
532
- k[i] = key[(pos+i)&3]
532
+ k[i] = key[(pos+i)&3] // nolint:gosec // false positive, impossible to be out of bounds; see: https://github.com/securego/gosec/issues/1525
533
}
534
kw := *(*uintptr)(unsafe.Pointer(&k))
535
modules/caddyhttp/routes.go
+1
-1
@@ -447,7 +447,7 @@ func (ms MatcherSets) String() string {
447
result.WriteByte('[')
448
for _, matcherSet := range ms {
449
for _, matcher := range matcherSet {
450
- result.WriteString(fmt.Sprintf(" %#v", matcher))
450
+ fmt.Fprintf(&result, " %#v", matcher)
451
}
452
}
453
result.WriteByte(']')
modules/caddyhttp/staticresp.go
+1
-1
@@ -246,7 +246,7 @@ func (s StaticResponse) ServeHTTP(w http.ResponseWriter, r *http.Request, next H
246
247
// write response body
248
if statusCode != http.StatusEarlyHints && body != "" {
249
- fmt.Fprint(w, body)
249
+ fmt.Fprint(w, body) //nolint:gosec // no XSS unless you sabatoge your own config
250
}
251
252
// continue handling after Early Hints as they are not the final response
modules/caddypki/adminapi.go
+2
-2
@@ -163,9 +163,9 @@ func (a *adminAPI) handleCACerts(w http.ResponseWriter, r *http.Request) error {
163
}
164
165
w.Header().Set("Content-Type", "application/pem-certificate-chain")
166
- _, err = w.Write(interCert)
166
+ _, err = w.Write(interCert) //nolint:gosec // false positive... no XSS in a PEM for cryin' out loud
167
if err == nil {
168
- _, _ = w.Write(rootCert)
168
+ _, _ = w.Write(rootCert) //nolint:gosec // false positive... no XSS in a PEM for cryin' out loud
169
}
170
171
return nil
modules/caddypki/crypto.go
+1
-1
@@ -77,7 +77,7 @@ type KeyPair struct {
77
78
// The private key. By default, this should be the path to
79
// a PEM file unless format is something else.
80
- PrivateKey string `json:"private_key,omitempty"`
80
+ PrivateKey string `json:"private_key,omitempty"` //nolint:gosec // false positive: yes it's exported, since it needs to encode/decode as JSON; and is often just a filepath
81
82
// The format in which the certificate and private
83
// key are provided. Default: pem_file
modules/caddytls/acmeissuer.go
+1
-1
@@ -337,7 +337,7 @@ func (iss *ACMEIssuer) generateZeroSSLEABCredentials(ctx context.Context, acct a
337
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
338
req.Header.Set("User-Agent", certmagic.UserAgent)
339
340
- resp, err := http.DefaultClient.Do(req)
340
+ resp, err := http.DefaultClient.Do(req) //nolint:gosec // no SSRF since URL is from trusted config
341
if err != nil {
342
return nil, acct, fmt.Errorf("performing EAB credentials request: %v", err)
343
}
modules/caddytls/capools.go
+1
-1
@@ -588,7 +588,7 @@ func (hcp *HTTPCertPool) Provision(ctx caddy.Context) error {
588
if err != nil {
589
return err
590
}
591
- res, err := httpClient.Do(req)
591
+ res, err := httpClient.Do(req) //nolint:gosec // SSRF false positive... uri comes from config
592
if err != nil {
593
return err
594
}
modules/caddytls/certmanagers.go
+1
-1
@@ -155,7 +155,7 @@ func (hcg HTTPCertGetter) GetCertificate(ctx context.Context, hello *tls.ClientH
155
return nil, err
156
}
157
158
- resp, err := http.DefaultClient.Do(req)
158
+ resp, err := http.DefaultClient.Do(req) //nolint:gosec // SSRF false positive... request URI comes from config
159
if err != nil {
160
return nil, err
161
}
modules/caddytls/zerosslissuer.go
+1
-1
@@ -40,7 +40,7 @@ func init() {
40
type ZeroSSLIssuer struct {
41
// The API key (or "access key") for using the ZeroSSL API.
42
// REQUIRED.
43
- APIKey string `json:"api_key,omitempty"`
43
+ APIKey string `json:"api_key,omitempty"` //nolint:gosec // false positive... yes this is exported, for JSON interop
44
45
// How many days the certificate should be valid for.
46
// Only certain values are accepted; see ZeroSSL docs.