From ffac4f0286f0c27c21de17ef9b1a440a11b04152 Mon Sep 17 00:00:00 2001 From: devitway Date: Sun, 22 Feb 2026 20:35:04 +0000 Subject: [PATCH] fix(auth): replace starts_with with explicit matches for token paths Prevent accidental exposure of unknown /api/tokens/* sub-paths. Only the three known routes are now explicitly whitelisted in is_public_path: /api/tokens, /api/tokens/list, /api/tokens/revoke. --- nora-registry/src/auth.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/nora-registry/src/auth.rs b/nora-registry/src/auth.rs index e8b56ec..3f784b0 100644 --- a/nora-registry/src/auth.rs +++ b/nora-registry/src/auth.rs @@ -63,11 +63,17 @@ impl HtpasswdAuth { fn is_public_path(path: &str) -> bool { matches!( path, - "/" | "/health" | "/ready" | "/metrics" | "/v2/" | "/v2" + "/" | "/health" + | "/ready" + | "/metrics" + | "/v2/" + | "/v2" + | "/api/tokens" + | "/api/tokens/list" + | "/api/tokens/revoke" ) || path.starts_with("/ui") || path.starts_with("/api-docs") || path.starts_with("/api/ui") - || path.starts_with("/api/tokens") } /// Auth middleware - supports Basic auth and Bearer tokens @@ -404,8 +410,12 @@ mod tests { assert!(is_public_path("/api/ui/stats")); assert!(is_public_path("/api/tokens")); assert!(is_public_path("/api/tokens/list")); + assert!(is_public_path("/api/tokens/revoke")); // Protected paths + assert!(!is_public_path("/api/tokens/unknown")); + assert!(!is_public_path("/api/tokens/admin")); + assert!(!is_public_path("/api/tokens/extra/path")); assert!(!is_public_path("/v2/myimage/blobs/sha256:abc")); assert!(!is_public_path("/v2/library/nginx/manifests/latest")); assert!(!is_public_path(