From 80e3c2696701cb9853984b24baa12765b4aab5ee Mon Sep 17 00:00:00 2001 From: Xi Xu Date: Wed, 10 Dec 2025 13:04:33 +0800 Subject: [PATCH] Transform scope parameter for container registry auth Added logic to remove the cr/[registry]/ prefix from the scope parameter and handle official Docker Hub images by adding the library/ prefix. Updated tests to verify correct scope transformation for Docker Hub, GHCR, and official images. --- src/index.js | 22 ++++++++++++++++- test/platforms/container-registry.test.js | 30 +++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index 7ec9f85..a16d950 100644 --- a/src/index.js +++ b/src/index.js @@ -840,7 +840,27 @@ async function handleRequest(request, env, ctx) { return resp; } const wwwAuthenticate = parseAuthenticate(authenticateStr); - const scope = url.searchParams.get('scope'); + let scope = url.searchParams.get('scope'); + + // Transform scope to remove Xget path prefix (cr/[registry]/) + // Original scope: repository:cr/docker/mlikiowa/napcat-docker:pull + // Transformed scope: repository:mlikiowa/napcat-docker:pull + if (scope && scope.startsWith('repository:')) { + const scopeParts = scope.split(':'); + if (scopeParts.length === 3) { + const repoPath = scopeParts[1]; + // Remove cr/[registry]/ prefix (e.g., cr/docker/, cr/ghcr/, etc.) + const transformedRepo = repoPath.replace(/^cr\/[^/]+\//, ''); + + // Special handling for Docker Hub: official images need 'library/' prefix + if (platform === 'cr-docker' && transformedRepo && !transformedRepo.includes('/')) { + scope = `repository:library/${transformedRepo}:${scopeParts[2]}`; + } else { + scope = `repository:${transformedRepo}:${scopeParts[2]}`; + } + } + } + return await fetchToken(wwwAuthenticate, scope || '', authorization || ''); } diff --git a/test/platforms/container-registry.test.js b/test/platforms/container-registry.test.js index 253ef37..ad61904 100644 --- a/test/platforms/container-registry.test.js +++ b/test/platforms/container-registry.test.js @@ -76,6 +76,36 @@ describe('Container Registry Support', () => { // Should attempt to proxy auth requests expect(response.status).not.toBe(400); }); + + it('should transform scope parameter correctly for Docker Hub', async () => { + // Test that scope parameter removes Xget path prefix + const testUrl = + 'https://example.com/cr/docker/v2/auth?scope=repository:cr/docker/mlikiowa/napcat-docker:pull&service=Xget'; + const response = await SELF.fetch(testUrl); + + // Should not return 400 Bad Request (which indicates malformed scope) + expect(response.status).not.toBe(400); + }); + + it('should transform scope parameter correctly for GHCR', async () => { + // Test that scope parameter removes Xget path prefix + const testUrl = + 'https://example.com/cr/ghcr/v2/auth?scope=repository:cr/ghcr/user/repo:pull&service=Xget'; + const response = await SELF.fetch(testUrl); + + // Should not return 400 Bad Request (which indicates malformed scope) + expect(response.status).not.toBe(400); + }); + + it('should handle scope parameter for official Docker Hub images', async () => { + // Test that scope parameter is transformed and adds library/ prefix for official images + const testUrl = + 'https://example.com/cr/docker/v2/auth?scope=repository:cr/docker/nginx:pull&service=Xget'; + const response = await SELF.fetch(testUrl); + + // Should not return 400 Bad Request + expect(response.status).not.toBe(400); + }); }); describe('Docker Request Detection', () => {