chore: fix dependabot alerts (#4048)

* chore: fix dependabot alerts

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: fix dependabot alerts

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: fix dependabot alerts

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: fix golangci-lint findings from CI

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: fix golangci-lint gosec warnings

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: update code to use slices package and address gosec linting issues

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* build: fix makefile target

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: update tests to use context in HTTP requests and add gosec annotations

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: update tests to use context in HTTP requests

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: update tests to use context in HTTP requests

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: update tests to use context in HTTP requests

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: update tests to use context in HTTP requests

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: bump zui version

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: update test helpers and improve security settings in tests

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

* chore: add gosec linting directive for test path construction

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>

---------

Signed-off-by: Ramkumar Chinchani <rchincha.dev@gmail.com>
This commit is contained in:
Ramkumar Chinchani
2026-05-10 23:29:05 -07:00
committed by GitHub
parent 9757f7cf41
commit 9aff5b8d08
60 changed files with 2320 additions and 3008 deletions
+1 -1
View File
@@ -75,7 +75,7 @@ func (amw *AuthnMiddleware) sessionAuthn(ctlr *Controller, userAc *reqCtx.UserAc
identity, ok := GetAuthUserFromRequestSession(ctlr.CookieStore, request, ctlr.Log)
if !ok {
// let the client know that this session is invalid/expired
cookie := &http.Cookie{
cookie := &http.Cookie{ //nolint: gosec
Name: "session",
Value: "",
Path: "/",
+4 -4
View File
@@ -1706,10 +1706,10 @@ func mockWorkloadOIDCServer(t *testing.T, pubKey *rsa.PublicKey) *httptest.Serve
// Calculate modulus and exponent for JWK
nBytes := pubKey.N.Bytes()
eBytes := make([]byte, 4)
eBytes[0] = byte(pubKey.E >> 24)
eBytes[1] = byte(pubKey.E >> 16)
eBytes[2] = byte(pubKey.E >> 8)
eBytes[3] = byte(pubKey.E)
eBytes[0] = byte(pubKey.E >> 24) //nolint: gosec
eBytes[1] = byte(pubKey.E >> 16) //nolint: gosec
eBytes[2] = byte(pubKey.E >> 8) //nolint: gosec
eBytes[3] = byte(pubKey.E) //nolint: gosec
// Trim leading zeros from exponent
for len(eBytes) > 1 && eBytes[0] == 0 {
+2 -2
View File
@@ -115,10 +115,10 @@ func TestConfig(t *testing.T) {
Issuer: "https://accounts.google.com",
Scopes: []string{"openid", "email"},
},
"github": {
"github": { //nolint: gosec
Name: "GitHub",
ClientID: "github-client-id",
ClientSecret: "github-client-secret",
ClientSecret: "github-client-secret", //nolint: gosec
AuthURL: "github-auth-url",
TokenURL: "github-token-url",
Scopes: []string{"user:email"},
+1 -1
View File
@@ -74,7 +74,7 @@ func TestRedisOptions(t *testing.T) {
So(clientIntf, ShouldBeNil)
// Success
config = map[string]any{"url": "redis://user:password@localhost:6379/1?dial_timeout=5s"}
config = map[string]any{"url": "redis://user:password@localhost:6379/1?dial_timeout=5s"} //nolint: gosec
clientIntf, err = rediscfg.GetRedisClient(config, log)
So(err, ShouldBeNil)
+15 -6
View File
@@ -152,6 +152,7 @@ func setupBearerAuthServerCerts(t *testing.T, keyType tlsutils.KeyType) (
if err != nil {
t.Fatalf("Failed to extract public key from cert: %v", err)
}
//nolint:gosec // Path is generated from t.TempDir() within this test helper.
err = os.WriteFile(serverPublicKeyPath, publicKeyPKIX, 0o600)
if err != nil {
t.Fatalf("Failed to write server public key: %v", err)
@@ -163,6 +164,7 @@ func setupBearerAuthServerCerts(t *testing.T, keyType tlsutils.KeyType) (
if err != nil {
t.Fatalf("Failed to extract PKCS1 public key: %v", err)
}
//nolint:gosec // Path is generated from t.TempDir() within this test helper.
err = os.WriteFile(serverPublicKeyPKCS1Path, publicKeyPKCS1, 0o600)
if err != nil {
t.Fatalf("Failed to write server PKCS1 public key: %v", err)
@@ -173,6 +175,7 @@ func setupBearerAuthServerCerts(t *testing.T, keyType tlsutils.KeyType) (
if err != nil {
t.Fatalf("Failed to extract public key from cert: %v", err)
}
//nolint:gosec // Path is generated from t.TempDir() within this test helper.
err = os.WriteFile(serverPublicKeyPath, publicKeyPKIX, 0o600)
if err != nil {
t.Fatalf("Failed to write server public key: %v", err)
@@ -5215,7 +5218,12 @@ func TestAuthnSessionErrors(t *testing.T) {
client := resty.New()
client.SetRedirectPolicy(test.CustomRedirectPolicy(20))
client.SetCookie(&http.Cookie{Name: "session"})
client.SetCookie(&http.Cookie{
Name: "session",
Secure: true,
HttpOnly: true,
SameSite: http.SameSiteLaxMode,
})
// call endpoint with session (added to client after previous request)
resp, err := client.R().
@@ -11926,6 +11934,7 @@ func TestGCSignaturesAndUntaggedManifestsWithMetaDB(t *testing.T) {
err = gc.CleanRepo(ctx, repoName)
So(err, ShouldNotBeNil)
//nolint:gosec // Test path is constructed from t.TempDir() repo data and known blob layout.
err = os.WriteFile(path.Join(dir, repoName, "blobs", "sha256", refs.Manifests[0].Digest.Encoded()), content, 0o600)
So(err, ShouldBeNil)
})
@@ -12993,8 +13002,8 @@ func TestGetGithubUserInfo(t *testing.T) {
mock.GetUserEmails,
[]github.UserEmail{
{
Email: github.String("test@test"),
Primary: github.Bool(true),
Email: new("test@test"),
Primary: new(true),
},
},
),
@@ -13002,7 +13011,7 @@ func TestGetGithubUserInfo(t *testing.T) {
mock.GetUserOrgs,
[]github.Organization{
{
Login: github.String("testOrg"),
Login: new("testOrg"),
},
},
),
@@ -13040,8 +13049,8 @@ func TestGetGithubUserInfo(t *testing.T) {
mock.GetUserEmails,
[]github.UserEmail{
{
Email: github.String("test@test"),
Primary: github.Bool(true),
Email: new("test@test"),
Primary: new(true),
},
},
),
+2
View File
@@ -135,6 +135,7 @@ func proxyHTTPRequest(ctx context.Context, req *http.Request,
requestBody = req.Body
}
//nolint:gosec // target host is selected from trusted cluster membership config (not client-controlled input)
fwdRequest, err := http.NewRequestWithContext(ctx, req.Method, cloneURL.String(), requestBody)
if err != nil {
return nil, err
@@ -178,6 +179,7 @@ func proxyHTTPRequest(ctx context.Context, req *http.Request,
return nil, err
}
//nolint:gosec // outbound request is restricted to the trusted cluster member selected above
resp, err := httpClient.Do(fwdRequest)
if err != nil {
return nil, err
+5 -5
View File
@@ -2498,7 +2498,7 @@ func (rh *RouteHandler) GithubCodeExchangeCallback() rp.CodeExchangeCallback[*oi
}
if callbackUI != "" {
http.Redirect(w, r, callbackUI, http.StatusFound)
http.Redirect(w, r, callbackUI, http.StatusFound) //nolint: gosec
return
}
@@ -2554,7 +2554,7 @@ func (rh *RouteHandler) OpenIDCodeExchangeCallbackWithProvider(providerName stri
}
if callbackUI != "" {
http.Redirect(w, r, callbackUI, http.StatusFound)
http.Redirect(w, r, callbackUI, http.StatusFound) //nolint: gosec
return
}
@@ -2654,7 +2654,7 @@ func getImageManifest(ctx context.Context, routeHandler *RouteHandler, imgStore
return imgStore.GetImageManifest(name, reference)
}
type APIKeyPayload struct { //nolint:revive
type APIKeyPayload struct { //nolint:revive,gosec
Label string `json:"label"`
Scopes []string `json:"scopes"`
ExpirationDate string `json:"expirationDate"`
@@ -2686,7 +2686,7 @@ func (rh *RouteHandler) GetAPIKeys(resp http.ResponseWriter, req *http.Request)
json := jsoniter.ConfigCompatibleWithStandardLibrary
data, err := json.Marshal(apiKeyResponse)
data, err := json.Marshal(apiKeyResponse) //nolint:gosec // API key is intentionally returned on creation
if err != nil {
rh.c.Log.Error().Err(err).Msg("failed to marshal api key response")
@@ -2795,7 +2795,7 @@ func (rh *RouteHandler) CreateAPIKey(resp http.ResponseWriter, req *http.Request
json := jsoniter.ConfigCompatibleWithStandardLibrary
data, err := json.Marshal(apiKeyResponse)
data, err := json.Marshal(apiKeyResponse) //nolint:gosec // API key is intentionally returned on creation
if err != nil {
rh.c.Log.Error().Err(err).Msg("failed to marshal api key response")
+120 -20
View File
@@ -2135,7 +2135,12 @@ func TestCheckBlobUsesDescriptorContentType(t *testing.T) {
layerDigest, _, _ := descriptorTestDigests()
req := httptest.NewRequest(http.MethodHead, "http://example.com/v2/test/blobs/sha256:test", nil)
req := httptest.NewRequestWithContext(
context.Background(),
http.MethodHead,
"http://example.com/v2/test/blobs/sha256:test",
http.NoBody,
)
req.Header.Set("Accept", "application/vnd.oci.image.layer.v1.tar+gzip, */*")
req = mux.SetURLVars(req, map[string]string{
"name": "test",
@@ -2169,7 +2174,12 @@ func TestCheckBlobFallsBackToBinaryContentType(t *testing.T) {
layerDigest, _, _ := descriptorTestDigests()
req := httptest.NewRequest(http.MethodHead, "http://example.com/v2/test/blobs/sha256:test", nil)
req := httptest.NewRequestWithContext(
context.Background(),
http.MethodHead,
"http://example.com/v2/test/blobs/sha256:test",
http.NoBody,
)
req.Header.Set("Accept", "*/*")
req = mux.SetURLVars(req, map[string]string{
"name": "test",
@@ -2201,7 +2211,12 @@ func TestGetBlobUsesDescriptorContentType(t *testing.T) {
layerDigest, _, _ := descriptorTestDigests()
req := httptest.NewRequest(http.MethodGet, "http://example.com/v2/test/blobs/sha256:test", nil)
req := httptest.NewRequestWithContext(
context.Background(),
http.MethodGet,
"http://example.com/v2/test/blobs/sha256:test",
http.NoBody,
)
// Wildcard / mixed Accept must not leak into the response.
req.Header.Set("Accept", "application/vnd.oci.image.layer.v1.tar+gzip, */*")
req = mux.SetURLVars(req, map[string]string{
@@ -2249,7 +2264,12 @@ func TestGetBlobFallsBackOnInvalidDescriptorContentType(t *testing.T) {
layerDigest, _, _ := descriptorTestDigests()
req := httptest.NewRequest(http.MethodGet, "http://example.com/v2/test/blobs/sha256:test", nil)
req := httptest.NewRequestWithContext(
context.Background(),
http.MethodGet,
"http://example.com/v2/test/blobs/sha256:test",
http.NoBody,
)
req = mux.SetURLVars(req, map[string]string{
"name": "test",
"digest": layerDigest.String(),
@@ -2281,7 +2301,12 @@ func TestGetBlobFallsBackToBinaryContentType(t *testing.T) {
layerDigest, _, _ := descriptorTestDigests()
req := httptest.NewRequest(http.MethodGet, "http://example.com/v2/test/blobs/sha256:test", nil)
req := httptest.NewRequestWithContext(
context.Background(),
http.MethodGet,
"http://example.com/v2/test/blobs/sha256:test",
http.NoBody,
)
// Comma-separated Accept must not produce a malformed Content-Type.
req.Header.Set("Accept", "typeA, typeB")
req = mux.SetURLVars(req, map[string]string{
@@ -2319,7 +2344,12 @@ func TestGetBlobPartialUsesDescriptorContentType(t *testing.T) {
layerDigest, _, _ := descriptorTestDigests()
req := httptest.NewRequest(http.MethodGet, "http://example.com/v2/test/blobs/sha256:test", nil)
req := httptest.NewRequestWithContext(
context.Background(),
http.MethodGet,
"http://example.com/v2/test/blobs/sha256:test",
http.NoBody,
)
req.Header.Set("Range", "bytes=0-1")
req = mux.SetURLVars(req, map[string]string{
"name": "test",
@@ -2361,7 +2391,12 @@ func TestGetBlobPartialFallsBackToBinaryContentType(t *testing.T) {
},
})
req := httptest.NewRequest(http.MethodGet, "http://example.com/v2/test/blobs/sha256:test", nil)
req := httptest.NewRequestWithContext(
context.Background(),
http.MethodGet,
"http://example.com/v2/test/blobs/sha256:test",
http.NoBody,
)
req.Header.Set("Range", "bytes=0-1")
req.Header.Set("Accept", "application/vnd.oci.image.layer.v1.tar+gzip, */*")
req = mux.SetURLVars(req, map[string]string{
@@ -2405,7 +2440,12 @@ func TestGetBlobMultipartPartHasDescriptorContentType(t *testing.T) {
layerDigest, _, _ := descriptorTestDigests()
req := httptest.NewRequest(http.MethodGet, "http://example.com/v2/test/blobs/sha256:test", nil)
req := httptest.NewRequestWithContext(
context.Background(),
http.MethodGet,
"http://example.com/v2/test/blobs/sha256:test",
http.NoBody,
)
req.Header.Set("Range", "bytes=0-1,5-7")
req = mux.SetURLVars(req, map[string]string{
"name": "test",
@@ -2559,7 +2599,12 @@ func TestGetBlobMultipartContentLengthMatchesBody(t *testing.T) {
layerDigest, _, _ := descriptorTestDigests()
req := httptest.NewRequest(http.MethodGet, "http://example.com/v2/test/blobs/sha256:test", nil)
req := httptest.NewRequestWithContext(
context.Background(),
http.MethodGet,
"http://example.com/v2/test/blobs/sha256:test",
http.NoBody,
)
req.Header.Set("Range", "bytes=0-1,5-7,12-15")
req = mux.SetURLVars(req, map[string]string{
"name": "test",
@@ -2631,7 +2676,12 @@ func TestGetBlobMultipartOpensOneReaderAtATime(t *testing.T) {
layerDigest, _, _ := descriptorTestDigests()
req := httptest.NewRequest(http.MethodGet, "http://example.com/v2/test/blobs/sha256:test", nil)
req := httptest.NewRequestWithContext(
context.Background(),
http.MethodGet,
"http://example.com/v2/test/blobs/sha256:test",
http.NoBody,
)
// Four non-coalescing ranges so the producer must open four
// distinct readers in sequence.
req.Header.Set("Range", "bytes=0-3,8-11,16-19,24-27")
@@ -2688,7 +2738,12 @@ func TestGetBlobMultipartTruncatesOnReaderError(t *testing.T) {
layerDigest, _, _ := descriptorTestDigests()
req := httptest.NewRequest(http.MethodGet, "http://example.com/v2/test/blobs/sha256:test", nil)
req := httptest.NewRequestWithContext(
context.Background(),
http.MethodGet,
"http://example.com/v2/test/blobs/sha256:test",
http.NoBody,
)
req.Header.Set("Range", "bytes=0-1,5-7")
req = mux.SetURLVars(req, map[string]string{
"name": "test",
@@ -2727,7 +2782,12 @@ func TestGetBlobRangeUnsatisfiable(t *testing.T) {
},
})
req := httptest.NewRequest(http.MethodGet, "http://example.com/v2/test/blobs/sha256:test", nil)
req := httptest.NewRequestWithContext(
context.Background(),
http.MethodGet,
"http://example.com/v2/test/blobs/sha256:test",
http.NoBody,
)
req.Header.Set("Range", "bytes=999-1000")
req = mux.SetURLVars(req, map[string]string{
"name": "test",
@@ -2753,7 +2813,12 @@ func TestGetBlobRangeCheckBlobError(t *testing.T) {
},
})
req := httptest.NewRequest(http.MethodGet, "http://example.com/v2/test/blobs/sha256:test", nil)
req := httptest.NewRequestWithContext(
context.Background(),
http.MethodGet,
"http://example.com/v2/test/blobs/sha256:test",
http.NoBody,
)
req.Header.Set("Range", "bytes=0-1")
req = mux.SetURLVars(req, map[string]string{
"name": "test",
@@ -2779,7 +2844,12 @@ func TestGetBlobRangeCheckBlobMissing(t *testing.T) {
},
})
req := httptest.NewRequest(http.MethodGet, "http://example.com/v2/test/blobs/sha256:test", nil)
req := httptest.NewRequestWithContext(
context.Background(),
http.MethodGet,
"http://example.com/v2/test/blobs/sha256:test",
http.NoBody,
)
req.Header.Set("Range", "bytes=0-1")
req = mux.SetURLVars(req, map[string]string{
"name": "test",
@@ -2826,7 +2896,12 @@ func TestGetBlobSingleRangePartialBlobNotFound(t *testing.T) {
},
})
req := httptest.NewRequest(http.MethodGet, "http://example.com/v2/test/blobs/sha256:test", nil)
req := httptest.NewRequestWithContext(
context.Background(),
http.MethodGet,
"http://example.com/v2/test/blobs/sha256:test",
http.NoBody,
)
req.Header.Set("Range", "bytes=0-1")
req = mux.SetURLVars(req, map[string]string{
"name": "test",
@@ -2869,7 +2944,12 @@ func TestGetBlobSingleRangePartialUnexpectedError(t *testing.T) {
},
})
req := httptest.NewRequest(http.MethodGet, "http://example.com/v2/test/blobs/sha256:test", nil)
req := httptest.NewRequestWithContext(
context.Background(),
http.MethodGet,
"http://example.com/v2/test/blobs/sha256:test",
http.NoBody,
)
req.Header.Set("Range", "bytes=0-1")
req = mux.SetURLVars(req, map[string]string{
"name": "test",
@@ -2914,7 +2994,12 @@ func TestGetBlobSingleRangeLengthMismatch(t *testing.T) {
},
})
req := httptest.NewRequest(http.MethodGet, "http://example.com/v2/test/blobs/sha256:test", nil)
req := httptest.NewRequestWithContext(
context.Background(),
http.MethodGet,
"http://example.com/v2/test/blobs/sha256:test",
http.NoBody,
)
req.Header.Set("Range", "bytes=0-1")
req = mux.SetURLVars(req, map[string]string{
"name": "test",
@@ -2965,7 +3050,12 @@ func TestGetBlobMultipartShortReaderTruncates(t *testing.T) {
layerDigest, _, _ := descriptorTestDigests()
req := httptest.NewRequest(http.MethodGet, "http://example.com/v2/test/blobs/sha256:test", nil)
req := httptest.NewRequestWithContext(
context.Background(),
http.MethodGet,
"http://example.com/v2/test/blobs/sha256:test",
http.NoBody,
)
req.Header.Set("Range", "bytes=0-1,5-7")
req = mux.SetURLVars(req, map[string]string{
"name": "test",
@@ -3026,7 +3116,12 @@ func TestGetBlobRangeCheckBlobNamedErrors(t *testing.T) {
},
})
req := httptest.NewRequest(http.MethodGet, "http://example.com/v2/test/blobs/sha256:test", nil)
req := httptest.NewRequestWithContext(
context.Background(),
http.MethodGet,
"http://example.com/v2/test/blobs/sha256:test",
http.NoBody,
)
req.Header.Set("Range", "bytes=0-1")
req = mux.SetURLVars(req, map[string]string{
"name": "test",
@@ -3099,7 +3194,12 @@ func TestGetBlobMultipartReaderCloseError(t *testing.T) {
layerDigest, _, _ := descriptorTestDigests()
req := httptest.NewRequest(http.MethodGet, "http://example.com/v2/test/blobs/sha256:test", nil)
req := httptest.NewRequestWithContext(
context.Background(),
http.MethodGet,
"http://example.com/v2/test/blobs/sha256:test",
http.NoBody,
)
req.Header.Set("Range", "bytes=0-1,5-7")
req = mux.SetURLVars(req, map[string]string{
"name": "test",
+10 -4
View File
@@ -2,6 +2,7 @@ package api_test
import (
"bytes"
"context"
"encoding/json"
"net/http"
"net/http/httptest"
@@ -100,7 +101,12 @@ func TestSessionAuditLogger(t *testing.T) {
wrapped := zotapi.SessionAuditLogger(audit)(inner)
req := httptest.NewRequest(testCase.method, "/v2/repo/test/uploads", http.NoBody)
req := httptest.NewRequestWithContext(
context.Background(),
testCase.method,
"/v2/repo/test/uploads",
http.NoBody,
)
req.RemoteAddr = "127.0.0.1:12345"
recorder := httptest.NewRecorder()
@@ -147,7 +153,7 @@ func TestSessionAuditLogger_rawQueryAppendedToObject(t *testing.T) {
wrapped := zotapi.SessionAuditLogger(audit)(inner)
req := httptest.NewRequest(http.MethodPost, "/v2/a/b", http.NoBody)
req := httptest.NewRequestWithContext(context.Background(), http.MethodPost, "/v2/a/b", http.NoBody)
req.URL.RawQuery = "digest=sha256:abc"
recorder := httptest.NewRecorder()
@@ -185,7 +191,7 @@ func TestSessionLogger_redactsAuthorizationAndLogsUsernameFromContext(t *testing
wrapped := zotapi.SessionLogger(ctlr)(inner)
req := httptest.NewRequest(http.MethodGet, "/v2/_catalog", http.NoBody)
req := httptest.NewRequestWithContext(context.Background(), http.MethodGet, "/v2/_catalog", http.NoBody)
req.Header.Set("Authorization", "Bearer super-secret-token")
req.RemoteAddr = "10.0.0.1:4444"
@@ -217,7 +223,7 @@ func TestSessionLogger_omitsUsernameWhenAnonymous(t *testing.T) {
wrapped := zotapi.SessionLogger(ctlr)(inner)
req := httptest.NewRequest(http.MethodGet, "/v2/_catalog", http.NoBody)
req := httptest.NewRequestWithContext(context.Background(), http.MethodGet, "/v2/_catalog", http.NoBody)
recorder := httptest.NewRecorder()
wrapped.ServeHTTP(recorder, req)