CVE-2024-27916 (Go, published 2024-03-21T02:52Z)
Description: value: Minder is a software supply chain security platform. Prior to version 0.0.33, a Minder user can use the endpoints `GetRepositoryByName`, `DeleteRepositoryByName`, and `GetArtifactByName` to access any repository in the database, irrespective of who owns the repo and any permissions present. The database query checks by repo owner, repo name and provider name (which is always `github`). These query values are not distinct for the particular user - as long as the user has valid credentials and a provider, they can set the repo owner/name to any value they want and the server will return information on this repo. Version 0.0.33 contains a patch for this issue.
Severity: nan (CVSS v3 base score: )
Weakness: NVD-CWE-noinfo \u2014 Insufficient Information
There is insufficient information about the issue to classify it; details are unkown or unspecified.
Repository: https://github.com/stacklok/minder
Files changed:
database/query/repositories.sql
internal/controlplane/handlers_artifacts.go
internal/controlplane/handlers_repositories.go
internal/db/repositories.sql.go
internal/db/repositories_test.go
Commit message: Merge pull request from GHSA-v627-69v2-xx37

Fixes #GHSA-v627-69v2-xx37

Change GetRepositoryByRepoName query to include project ID. This enforces that
the user can only access the repos in the project they authorized with.
This fixes a security issue where several API endpoints allowed any
authenticated user to manipulate any repo in the DB, irrespective of who
owned it.

Vulnerable code:
SELECT * FROM repositories WHERE provider = $1 AND repo_owner = $2 AND repo_name = $3;
	repo, err := s.store.GetRepositoryByRepoName(ctx,
		db.GetRepositoryByRepoNameParams{Provider: provider.Name, RepoOwner: fragments[0], RepoName: fragments[1]})
	repo, err := s.store.GetRepositoryByRepoName(ctx,
		db.GetRepositoryByRepoNameParams{Provider: provider.Name, RepoOwner: fragments[0], RepoName: fragments[1]})
SELECT id, provider, project_id, repo_owner, repo_name, repo_id, is_private, is_fork, webhook_id, webhook_url, deploy_url, clone_url, created_at, updated_at, default_branch FROM repositories WHERE provider = $1 AND repo_owner = $2 AND repo_name = $3
	Provider  string `json:"provider"`
	RepoOwner string `json:"repo_owner"`
	RepoName  string `json:"repo_name"`
	row := q.db.QueryRowContext(ctx, getRepositoryByRepoName, arg.Provider, arg.RepoOwner, arg.RepoName)
		Provider: repo1.Provider, RepoOwner: repo1.RepoOwner, RepoName: repo1.RepoName})

Fixed code:
SELECT * FROM repositories WHERE provider = $1 AND repo_owner = $2 AND repo_name = $3 AND project_id = $4;
	entityCtx := engine.EntityFromContext(ctx)
	projectID := entityCtx.Project.ID

		ProjectID: projectID,
	repo, err := s.store.GetRepositoryByRepoName(ctx, db.GetRepositoryByRepoNameParams{
		Provider:  provider.Name,
		RepoOwner: fragments[0],
		RepoName:  fragments[1],
		ProjectID: projectID,
	})
	repo, err := s.store.GetRepositoryByRepoName(ctx, db.GetRepositoryByRepoNameParams{
		Provider:  provider.Name,
		RepoOwner: fragments[0],
		RepoName:  fragments[1],
		ProjectID: projectID,
	})
SELECT id, provider, project_id, repo_owner, repo_name, repo_id, is_private, is_fork, webhook_id, webhook_url, deploy_url, clone_url, created_at, updated_at, default_branch FROM repositories WHERE provider = $1 AND repo_owner = $2 AND repo_name = $3 AND project_id = $4
	Provider  string    `json:"provider"`
	RepoOwner string    `json:"repo_owner"`
	RepoName  string    `json:"repo_name"`
	ProjectID uuid.UUID `json:"project_id"`
	row := q.db.QueryRowContext(ctx, getRepositoryByRepoName,
		arg.Provider,
		arg.RepoOwner,
		arg.RepoName,
		arg.ProjectID,
	)
		Provider:  repo1.Provider,
		RepoOwner: repo1.RepoOwner,
		RepoName:  repo1.RepoName,
		ProjectID: project.ID,
	})