CVE-2024-31455 (Go, published 2024-04-09T17:16Z)
Description: value: Minder by Stacklok is an open source software supply chain security platform. A refactoring in commit `5c381cf` added the ability to get GitHub repositories registered to a project without specifying a specific provider.  Unfortunately, the SQL query for doing so was missing parenthesis, and would select a random repository. This issue is patched in pull request 2941. As a workaround, revert prior to `5c381cf`, or roll forward past `2eb94e7`.
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/db/repositories.sql.go
internal/db/repositories_test.go
Commit message: Fix repository delete by name (#2941)

Fix #2938

Vulnerable code:
    AND lower(provider) = lower(sqlc.narg('provider')::text) OR sqlc.narg('provider')::text IS NULL;
    AND lower(provider) = lower(sqlc.narg('provider')::text) OR sqlc.narg('provider')::text IS NULL
    AND lower(provider) = lower($4::text) OR $4::text IS NULL
    AND lower(provider) = lower($2::text) OR $2::text IS NULL

Fixed code:
    AND (lower(provider) = lower(sqlc.narg('provider')::text) OR sqlc.narg('provider')::text IS NULL);
    AND (lower(provider) = lower(sqlc.narg('provider')::text) OR sqlc.narg('provider')::text IS NULL)
    AND (lower(provider) = lower($4::text) OR $4::text IS NULL)
    AND (lower(provider) = lower($2::text) OR $2::text IS NULL)
func TestGetRepositoryByRepoNameNoProvider(t *testing.T) {
	t.Parallel()

	org := createRandomOrganization(t)
	project := createRandomProject(t, org.ID)
	prov := createRandomProvider(t, project.ID)
	createRandomRepository(t, project.ID, prov)
	repo1 := createRandomRepository(t, project.ID, prov)

	repo2, err := testQueries.GetRepositoryByRepoName(context.Background(), GetRepositoryByRepoNameParams{
		RepoOwner: repo1.RepoOwner,
		RepoName:  repo1.RepoName,
		ProjectID: project.ID,
	})
	require.NoError(t, err)
	require.NotEmpty(t, repo2)

	require.Equal(t, repo1.ID, repo2.ID)
	require.Equal(t, repo1.Provider, repo2.Provider)
	require.Equal(t, repo1.ProjectID, repo2.ProjectID)
	require.Equal(t, repo1.RepoOwner, repo2.RepoOwner)
	require.Equal(t, repo1.RepoName, repo2.RepoName)
	require.Equal(t, repo1.RepoID, repo2.RepoID)
	require.Equal(t, repo1.IsPrivate, repo2.IsPrivate)
	require.Equal(t, repo1.IsFork, repo2.IsFork)
	require.Equal(t, repo1.WebhookID, repo2.WebhookID)
	require.Equal(t, repo1.WebhookUrl, repo2.WebhookUrl)
	require.Equal(t, repo1.DeployUrl, repo2.DeployUrl)
	require.Equal(t, repo1.CreatedAt, repo2.CreatedAt)
	require.Equal(t, repo1.UpdatedAt, repo2.UpdatedAt)
}

func TestListRepositoriesByProjectIDAndProvider(t *testing.T) {
	t.Parallel()

	org := createRandomOrganization(t)
	otherProject := createRandomProject(t, org.ID)
	project := createRandomProject(t, org.ID)
	otherProv := createRandomProvider(t, otherProject.ID)
	prov := createRandomProvider(t, project.ID)
	createRandomRepository(t, project.ID, otherProv)
	createRandomRepository(t, otherProject.ID, prov)

	for i := 1001; i < 1020; i++ {
		createRandomRepository(t, project.ID, prov, func(r *CreateRepositoryParams) {
			r.RepoID = int64(i)
		})
	}

	arg := ListRegisteredRepositoriesByProjectIDAndProviderParams{
		ProjectID: project.ID,
	}

	repos, err := testQueries.ListRegisteredRepositoriesByProjectIDAndProvider(context.Background(), arg)
	require.NoError(t, err)
	require.NotEmpty(t, repos)

	for _, repo := range repos {
		require.NotEmpty(t, repo)
		require.Equal(t, arg.ProjectID, repo.ProjectID)
	}
}