fix(store): scope SetDomainStatus by project (IDOR); scheduler reuses DeriveStatus
handleCheck's error branch wrote last_check_status via an id-only UPDATE, so an authenticated caller's own valid project id paired with a foreign domain id in the URL could flip a stranger's domain to "error" even though Check itself is project-scoped and would 404/error out first. Add project_id to the WHERE clause (queries/domains.sql + generated db/domains.sql.go), thread projectID through Store/TenantStore/SchedStore SetDomainStatus, and pass pid from context at both call sites in handleCheck plus the scheduler. Also collapse checkDomain's inline status derivation in scheduler.go into a call to service.DeriveStatus, the same helper handleCheck already uses, so there's a single source of truth for "drift vs in_sync" instead of two copies that could drift apart. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BwxdSt4reTm7Dj1oxRvpP3
This commit is contained in:
@@ -39,7 +39,7 @@ func (a *API) handleCheck(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil {
|
||||
// Persist the failure so the domain badge reflects it instead of stale
|
||||
// "unknown"; the write error (if any) is logged, never masks the 500.
|
||||
if serr := a.Store.SetDomainStatus(r.Context(), did, service.StatusError); serr != nil {
|
||||
if serr := a.Store.SetDomainStatus(r.Context(), did, pid, service.StatusError); serr != nil {
|
||||
log.Printf("api: set domain status (error) failed: %v", serr)
|
||||
}
|
||||
log.Printf("api: check failed: %v", err)
|
||||
@@ -48,7 +48,7 @@ func (a *API) handleCheck(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
// Manual check persists status/history only — no notification. Notify
|
||||
// remains the scheduler's responsibility (see internal/scheduler).
|
||||
if serr := a.Store.SetDomainStatus(r.Context(), did, service.DeriveStatus(cs)); serr != nil {
|
||||
if serr := a.Store.SetDomainStatus(r.Context(), did, pid, service.DeriveStatus(cs)); serr != nil {
|
||||
log.Printf("api: set domain status failed: %v", serr)
|
||||
}
|
||||
writeJSON(w, http.StatusOK, toChangesetResponse(cs))
|
||||
|
||||
Reference in New Issue
Block a user