Skip to content

fix(controlplane): enforce project RBAC on CAS download redirect lookups (PFM-6716) - #3400

Merged
migmartri merged 1 commit into
chainloop-dev:mainfrom
migmartri:miguel/pfm-6716-cross-project-artifact-download-via
Sep 4, 2026
Merged

fix(controlplane): enforce project RBAC on CAS download redirect lookups (PFM-6716)#3400
migmartri merged 1 commit into
chainloop-dev:mainfrom
migmartri:miguel/pfm-6716-cross-project-artifact-download-via

Conversation

@migmartri

@migmartri migmartri commented Sep 4, 2026

Copy link
Copy Markdown
Member

What does this PR do?

Closes a project-isolation bypass in CASRedirectService/GetDownloadURL (PFM-6716). The endpoint resolved CAS mappings without RBAC scopes for API-token callers, so a project-scoped API token could mint a download URL for any artifact in its organization as long as it knew the digest. The sibling CASCredentialsService/Get endpoint already restricted the same lookup to the token's visible projects.

Both download endpoints now derive the lookup scopes from a single shared helper, rbacScopesForOrg, so the token-to-scope resolution lives in one place and cannot drift between the two download paths again. The helper documents the scope convention at the point of use: an organization present in the scopes map limits access to the caller's visible projects, while an absent one keeps the organization fully reachable for callers RBAC does not apply to.

🤖 Posted by Maximus bot (Claude Code) on behalf of @migmartri

Review in cubic

…ups (PFM-6716)

CASRedirectService/GetDownloadURL resolved CAS mappings with no RBAC
scopes for API-token callers, so a project-scoped token could mint a
download URL for any artifact in its organization as long as it knew
the digest. The guarded sibling endpoint, CASCredentialsService/Get,
already restricted the same lookup to the token's visible projects.

Both endpoints now build the scopes through a shared service helper,
rbacScopesForOrg, so the token-to-scope resolution lives in one place
and cannot drift between the two download paths again.

Assisted-by: OpenCode
Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev>

Chainloop-Trace-Sessions: ses_f92e40175ffePQw6J062DZywDK
@chainloop-platform

chainloop-platform Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

AI Session Checks — 🟡 83% · ✅ 0 failing

Avg score Sessions Failing policies Attribution Files Lines Total Duration
🟡 83% 1 ✅ 0 100% AI / 0% Human 5 +293 / -7 35m49s

🟡 83% — 100% AI — ✅ All policies passing

Sep 4, 2026 15:49 UTC · 35m49s · $3.75 · 723.9k in / 19.5k out · opencode 1.17.20 (z-ai/glm-5.3)

View session details ↗

Change Summary

  • Adds rbacScopesForOrg to centralize per-org project scope resolution.
  • Routes GetDownloadURL and CASCredentialsService.Get through the shared scoped lookup.
  • Adds casredirect_integration_test.go for cross-project and org-scoped download cases.
  • Extends service_test.go with TestRBACScopesForOrg, including empty-scope deny-all coverage.

AI Session Overall Score

🟡 83% — Strong fix, but verification and PR-closeout evidence stop short of fully clean.

AI Session Analysis Breakdown

🟢 93% · solution-quality

🟢 Shared scope resolution prevents the sibling CAS endpoints from drifting again. · High Impact

🟢 92% · user-trust-signal

No notes.

🟢 91% · context-and-planning

🟢 A five-step todo plan preceded the branch, tests, and code edits. · High Impact

🟢 90% · scope-discipline

No notes.

🟡 74% · verification

🟢 Regression and helper tests were added around the vulnerable path. · High Impact

🟠 Recorded test runs are filtered commands, so the pass signal stays indirect. · Medium Severity

💡 Keep one unfiltered pass line or exit status before declaring the change green.

🟡 68% · alignment

🟠 The user asked for PR creation, but the transcript ends after the signed commit. · Medium Severity

💡 When you promise PR creation, include the PR step or say you stopped at commit.


File Attribution

████████████████████ 100% AI / 0% Human

Status Attribution File Lines
created ai app/controlplane/internal/service/casredirect_integration_test.go +214 / -0
modified ai app/controlplane/internal/service/service_test.go +63 / -0
modified ai app/controlplane/internal/service/service.go +14 / -0
modified ai app/controlplane/internal/service/cascredential.go +1 / -6
modified ai app/controlplane/internal/service/casredirect.go +1 / -1

Policies (4)

Status Policy Material Messages
✅ Passed ai-config-ai-agents-allowed ai-coding-session-ses-f9 -
✅ Passed ai-config-no-dangerous-commands ai-coding-session-ses-f9 -
✅ Passed ai-config-no-secrets ai-coding-session-ses-f9 -
✅ Passed ai-config-mcp-servers-allowed ai-coding-session-ses-f9 -

Security Checks — ✅ 7 passing

secret-scan

Status Policy Messages
✅ Passed secrets-detection -

sast-scan

Status Policy Messages
✅ Passed owasp-top10-2025 -
✅ Passed sast -
✅ Passed cwe-top25 -
✅ Passed cwe-top26-40-cusp -

PR info

Status Policy Messages
✅ Passed pr-description-required -
✅ Passed pr-user-story-linked -

⏭️ 3 scans not applied

Scan Reason
vulnerability-scan no manifest/lockfile changed
github-actions-scan no workflow files changed
iac-scan no IaC files changed

View attestation ↗


Powered by Chainloop and Chainloop Trace

@matiasinsaurralde
matiasinsaurralde requested a review from a team September 4, 2026 16:27

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 5 files

Heads up: you’re close to your included review allowance. Set a flex budget so reviews don’t pause.

Re-trigger cubic

@migmartri
migmartri merged commit e2dde78 into chainloop-dev:main Sep 4, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants