-
Notifications
You must be signed in to change notification settings - Fork 222
Labels
bugSomething isn't workingSomething isn't workingstaleInactive issues or pull requestsInactive issues or pull requests
Description
What happened in your environment?
When copying an artifact, it seems that oras uses only the target authentication for both the source and target artifact if both artifacts are in the same registry:
# copy from docker hub to harbor demo, works as expected
$ oras copy \
'docker.io/library/alpine:latest' \
'demo.goharbor.io/oras-src/alpine:latest' \
--to-username='robot_oras-src+src' --to-password='DX37nuS39P7Hb7AbhaC9Ed1TtuulcSYG'
Copied [registry] docker.io/library/alpine:latest => [registry] demo.goharbor.io/oras-src/alpine:latest
# copy from harbor demo to harbor demo, fails with authorization error
$ oras copy \
'demo.goharbor.io/oras-src/alpine:latest' \
--from-username='robot_oras-src+src' --from-password='DX37nuS39P7Hb7AbhaC9Ed1TtuulcSYG' \
'demo.goharbor.io/oras-dst/alpine:latest' \
--to-username='robot_oras-dst+dst' --to-password='COhhaKcEy2i1IMwHVjQ00a8GyVgDTrc3'
Error from source registry for "demo.goharbor.io/oras-src/alpine:latest": unauthorized: unauthorized to access repository: oras-src/alpine, action: pull: unauthorized to access repository: oras-src/alpine, action: pullDebug Logs
$ oras copy --debug \
'demo.goharbor.io/oras-src/alpine:latest' \
--from-username='robot_oras-src+src' --from-password='DX37nuS39P7Hb7AbhaC9Ed1TtuulcSYG' \
'demo.goharbor.io/oras-dst/alpine:latest' \
--to-username='robot_oras-dst+dst' --to-password='COhhaKcEy2i1IMwHVjQ00a8GyVgDTrc3'
[2025-11-05T14:40:40.115127814+01:00][DEBUG]: --> Request #0
> Request URL: "https://demo.goharbor.io/v2/oras-src/alpine/manifests/latest"
> Request method: "GET"
> Request headers:
"Accept": "application/vnd.docker.distribution.manifest.v2+json, application/vnd.docker.distribution.manifest.list.v2+json, application/vnd.oci.image.manifest.v1+json, application/vnd.oci.image.index.v1+json, application/vnd.oci.artifact.manifest.v1+json"
"User-Agent": "oras/1.3.0"
[2025-11-05T14:40:40.198292177+01:00][DEBUG]: <-- Response #0
< Response Status: "401 Unauthorized"
< Response headers:
"Strict-Transport-Security": "max-age=31536000; includeSubDomains"
"Date": "Wed, 05 Nov 2025 13:36:17 GMT"
"Content-Type": "application/json; charset=utf-8"
"Content-Length": "152"
"Docker-Distribution-Api-Version": "registry/2.0"
"Set-Cookie": "*****"
"Www-Authenticate": "Bearer realm=\"https://demo.goharbor.io/service/token\",service=\"harbor-registry\",scope=\"repository:oras-src/alpine:pull\""
"X-Request-Id": "26993d607654ddbc23e3ef82b646af75"
< Response body:
{"errors":[{"code":"UNAUTHORIZED","message":"authorize header needed to send HEAD to repository: authorize header needed to send HEAD to repository"}]}
[2025-11-05T14:40:40.198417478+01:00][DEBUG]: --> Request #1
> Request URL: "https://demo.goharbor.io/service/token?scope=repository%3Aoras-dst%2Falpine%3Apull%2Cpush&scope=repository%3Aoras-src%2Falpine%3Apull&service=harbor-registry"
> Request method: "GET"
> Request headers:
"Authorization": "*****"
"User-Agent": "oras/1.3.0"
[2025-11-05T14:40:40.231140378+01:00][DEBUG]: <-- Response #1
< Response Status: "200 OK"
< Response headers:
"Set-Cookie": "*****"
"X-Request-Id": "31ae690e60b9787d8280dc8f08ae7996"
"Strict-Transport-Security": "max-age=31536000; includeSubDomains"
"Date": "Wed, 05 Nov 2025 13:36:17 GMT"
"Content-Type": "application/json; charset=utf-8"
< Response body:
Response body redacted due to potential credentials
[2025-11-05T14:40:40.231308662+01:00][DEBUG]: --> Request #2
> Request URL: "https://demo.goharbor.io/v2/oras-src/alpine/manifests/latest"
> Request method: "GET"
> Request headers:
"Accept": "application/vnd.docker.distribution.manifest.v2+json, application/vnd.docker.distribution.manifest.list.v2+json, application/vnd.oci.image.manifest.v1+json, application/vnd.oci.image.index.v1+json, application/vnd.oci.artifact.manifest.v1+json"
"Authorization": "*****"
"User-Agent": "oras/1.3.0"
[2025-11-05T14:40:40.254262499+01:00][DEBUG]: <-- Response #2
< Response Status: "401 Unauthorized"
< Response headers:
"Content-Length": "180"
"Docker-Distribution-Api-Version": "registry/2.0"
"Set-Cookie": "*****"
"Www-Authenticate": "Basic realm=\"harbor\""
"X-Request-Id": "ba4e559bc202e7472ec357a640722e3f"
"Strict-Transport-Security": "max-age=31536000; includeSubDomains"
"Date": "Wed, 05 Nov 2025 13:36:17 GMT"
"Content-Type": "application/json; charset=utf-8"
< Response body:
{"errors":[{"code":"UNAUTHORIZED","message":"unauthorized to access repository: oras-src/alpine, action: pull: unauthorized to access repository: oras-src/alpine, action: pull"}]}
Error from source registry for "demo.goharbor.io/oras-src/alpine:latest": unauthorized: unauthorized to access repository: oras-src/alpine, action: pull: unauthorized to access repository: oras-src/alpine, action: pullWhat did you expect to happen?
oras copy should use the from-credentials for the source artifact and the to-credentials for the target artifact, even if both artifacts share the same registry (hostname).
How can we reproduce it?
- Create two private projects at https://demo.goharbor.io/
- Create a robot account with full permissions in each project
- Push an artifact into the first project
oras copythe artifact into the second project
What is the version of your ORAS CLI?
$ oras version
Version: 1.3.0
Go version: go1.25.0
OS/Arch: linux/amd64
Git commit: 40530fe4c68e5825b868cd874bd46fc0cdd0f432
Git tree state: cleanWhat is your OS environment?
rhel 8.8
Are you willing to submit PRs to fix it?
- Yes, I am willing to fix it.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workingstaleInactive issues or pull requestsInactive issues or pull requests