ECOPROJECT-4722 | fix: Add missing organization check to GetSourceDownloadURL endpoint#1218
Conversation
📝 WalkthroughWalkthroughHandler enforces ownership for GetSourceDownloadURL: it loads the source, maps GetSource errors (not-found -> 404, others -> 500), requires authenticated user's Username/Organization to match source owner (mismatch -> 403), and maps downstream download errors to 500. OpenAPI, generated client/server, and tests updated. ChangesSource Download Authorization
Sequence Diagram(s)sequenceDiagram
participant Client
participant Handler as GetSourceDownloadURLHandler
participant Auth as auth.MustHaveUser
participant SourceSvc as sourceSrv
Client->>Handler: GET /api/v1/sources/{id}/image-url
Handler->>SourceSvc: GetSource(id)
alt ErrResourceNotFound
SourceSvc-->>Handler: ErrResourceNotFound
Handler-->>Client: 404 Error
else Other GetSource error
SourceSvc-->>Handler: Error
Handler-->>Client: 500 Error
end
Handler->>Auth: extract user (Username, Organization)
Auth-->>Handler: User
alt User/Org matches source owner
Handler->>SourceSvc: GetSourceDownloadURL(id)
alt Success
SourceSvc-->>Handler: {Url, ExpiresAt}
Handler-->>Client: 200 {Url, ExpiresAt}
else Error
SourceSvc-->>Handler: Error
Handler-->>Client: 500 Error
end
else Ownership mismatch
Handler-->>Client: 403 Error
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@internal/handlers/v1alpha1/source_test.go`:
- Around line 1118-1120: The test currently only asserts result.Url is
non-empty; also assert the ExpiresAt field on the success response (the
server.GetSourceDownloadURL200JSONResponse value assigned to result) to ensure
it is set and meaningful. Update the test around the result variable to check
result.ExpiresAt is not nil/zero and represents a future timestamp (e.g., after
time.Now()) so callers relying on the expiry get a valid value.
- Around line 1122-1145: Add a test case where the requesting User has the same
Username but a different Organization to ensure the handler checks organization,
not just username: create a source row with Username "sharedUser" and
Organization "victimOrg" (similar to victimSourceID insertion), then call
handlers.NewServiceHandler(...).GetSourceDownloadURL with
auth.NewTokenContext(context.TODO(), attackerUser) where attackerUser.Username
== "sharedUser" but attackerUser.Organization == "attackerOrg", and assert the
response type is server.GetSourceDownloadURL404JSONResponse{}; this verifies
GetSourceDownloadURL (and related auth path) enforces org ownership rather than
only username.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: ad7bf7aa-9e03-47de-9798-884044025be0
📒 Files selected for processing (2)
internal/handlers/v1alpha1/source.gointernal/handlers/v1alpha1/source_test.go
25d4676 to
f3069b0
Compare
f3069b0 to
b954990
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@internal/handlers/v1alpha1/source_test.go`:
- Around line 1095-1194: Add a new It test under the GetSourceDownloadURL
Context that covers the 500 path: create a source and its image_infra (same as
other tests) and authenticate as the owning user, but configure the downstream
URL generator to fail (e.g., inject a mock/storage client or URLProvider that
returns an error into service.NewSourceService or service.NewSizerService so URL
generation fails) then call handlers.NewServiceHandler(...).GetSourceDownloadURL
and assert no error and that the response type equals
server.GetSourceDownloadURL500JSONResponse; place cleanup in the existing
AfterEach.
In `@internal/handlers/v1alpha1/source.go`:
- Around line 243-255: The two places returning an empty
server.GetSourceDownloadURL500JSONResponse must return the required Error body
with a message and include context; replace both empty returns with returning
server.GetSourceDownloadURL500JSONResponse{Error: server.Error{Message:
fmt.Sprintf("failed to prefetch source: %v", err)}} or similar for the prefetch
path and server.GetSourceDownloadURL500JSONResponse{Error: server.Error{Message:
fmt.Sprintf("failed to get download URL for source %s: %v", request.Id, err)}}
for the s.sourceSrv.GetSourceDownloadURL error path, and wrap/log the original
error where appropriate (use fmt.Errorf or %w upstream) so the message surfaces
useful context.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 9a0e6a96-8511-4499-a5ce-f1ffa30f3162
📒 Files selected for processing (6)
api/v1alpha1/openapi.yamlapi/v1alpha1/spec.gen.gointernal/api/client/client.gen.gointernal/api/server/server.gen.gointernal/handlers/v1alpha1/source.gointernal/handlers/v1alpha1/source_test.go
b954990 to
4f3bfd0
Compare
…nloadURL endpoint Signed-off-by: Ronen Avraham <ravraham@redhat.com>
4f3bfd0 to
00950cc
Compare
|
/hold |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@internal/handlers/v1alpha1/source.go`:
- Around line 237-256: The handler currently calls s.sourceSrv.GetSource(ctx,
request.Id) and then s.sourceSrv.GetSourceDownloadURL(ctx, request.Id), causing
two DB fetches; refactor the service by adding a method that accepts a
pre-loaded *model.Source (e.g., GetSourceDownloadURLFromSource(ctx
context.Context, src *model.Source) (url string, expireAt time.Time, err error)
or change GetSourceDownloadURL to accept *model.Source) and implement the
download-URL logic there, then update the handler to pass the already-loaded
source into that new method (replace the second call to
s.sourceSrv.GetSourceDownloadURL(ctx, request.Id) with
s.sourceSrv.GetSourceDownloadURLFromSource(ctx, source)), keeping error handling
and return types unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 210ab3d2-61f2-466e-ab5e-2ec058654720
📒 Files selected for processing (6)
api/v1alpha1/openapi.yamlapi/v1alpha1/spec.gen.gointernal/api/client/client.gen.gointernal/api/server/server.gen.gointernal/handlers/v1alpha1/source.gointernal/handlers/v1alpha1/source_test.go
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: AvielSegev, nirarg The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
|
/hold cancel |
The GET /api/v1/sources/{id}/image-url endpoint was missing authorization checks, allowing any authenticated user to download OVA images from sources they don't own. This is a high-priority security vulnerability as OVA files
contain:
This fix adds the same ownership verification pattern used by sibling endpoints (GetSource, UpdateSource, DeleteSource):
Summary by CodeRabbit
Bug Fixes
Tests
Documentation
Chores