fix: avoid mutating proto App.Healthcheck in insertAgentApp (#22954)

## Problem

`insertAgentApp` mutated its input by writing to `app.Healthcheck` when
it was nil (line 3525):

```go
if app.Healthcheck == nil {
    app.Healthcheck = &sdkproto.Healthcheck{}  // mutation!
}
```

The Devcontainers subtests share the same `tt.resource` pointer across
two parallel goroutines (`WithProtoIDs` and `WithoutProtoIDs`), causing
a data race on the `Healthcheck` field (and its sub-fields `Url`,
`Interval`, `Threshold`).

## Fix

Replace the in-place mutation with a local variable:

```go
healthcheck := app.GetHealthcheck()
if healthcheck == nil {
    healthcheck = &sdkproto.Healthcheck{}
}
```

This avoids writing back to the shared proto message. All downstream
reads now use the local `healthcheck` variable.
This commit is contained in:
Kyle Carberry
2026-03-11 16:29:10 +00:00
committed by GitHub
parent c33dc3e459
commit d39f69f4c2
@@ -3521,10 +3521,11 @@ func insertAgentApp(ctx context.Context, db database.Store, agentID uuid.UUID, a
appSlugs[slug] = struct{}{}
health := database.WorkspaceAppHealthDisabled
if app.Healthcheck == nil {
app.Healthcheck = &sdkproto.Healthcheck{}
healthcheck := app.GetHealthcheck()
if healthcheck == nil {
healthcheck = &sdkproto.Healthcheck{}
}
if app.Healthcheck.Url != "" {
if healthcheck.Url != "" {
health = database.WorkspaceAppHealthInitializing
}
@@ -3579,9 +3580,9 @@ func insertAgentApp(ctx context.Context, db database.Store, agentID uuid.UUID, a
External: app.External,
Subdomain: app.Subdomain,
SharingLevel: sharingLevel,
HealthcheckUrl: app.Healthcheck.Url,
HealthcheckInterval: app.Healthcheck.Interval,
HealthcheckThreshold: app.Healthcheck.Threshold,
HealthcheckUrl: healthcheck.Url,
HealthcheckInterval: healthcheck.Interval,
HealthcheckThreshold: healthcheck.Threshold,
Health: health,
// #nosec G115 - Order represents a display order value that's always small and fits in int32
DisplayOrder: int32(app.Order),