diff --git a/workspace-server/internal/handlers/org.go b/workspace-server/internal/handlers/org.go index 233cc69f..8b5c4585 100644 --- a/workspace-server/internal/handlers/org.go +++ b/workspace-server/internal/handlers/org.go @@ -607,7 +607,16 @@ func (h *OrgHandler) Import(c *gin.Context) { orgFile := filepath.Join(orgBaseDir, "org.yaml") data, err := os.ReadFile(orgFile) if err != nil { - c.JSON(http.StatusNotFound, gin.H{"error": fmt.Sprintf("org template not found: %s", body.Dir)}) + // Audit 2026-05-09 (Core-Security): the prior message echoed + // the user-supplied `body.Dir` verbatim. Path traversal is + // already blocked by resolveInsideRoot above, but echoing + // the raw input back lets a client probe for the existence + // of relative paths inside h.orgDir (a 404 with the input + // vs. a 400 from resolveInsideRoot is itself a signal). + // Drop the input from the message; log full context server- + // side via the resolved path for operator triage. + log.Printf("OrgImport: failed to read %s (requested dir=%q): %v", orgFile, body.Dir, err) + c.JSON(http.StatusNotFound, gin.H{"error": "org template not found"}) return } // Expand !include directives before unmarshal. Splits org.yaml diff --git a/workspace-server/internal/handlers/workspace_crud.go b/workspace-server/internal/handlers/workspace_crud.go index cc487a4a..c2674d32 100644 --- a/workspace-server/internal/handlers/workspace_crud.go +++ b/workspace-server/internal/handlers/workspace_crud.go @@ -331,8 +331,14 @@ func (h *WorkspaceHandler) Delete(c *gin.Context) { // stay in this handler. descendantIDs, stopErrs, err := h.CascadeDelete(ctx, id) if err != nil { + // Audit 2026-05-09 (Core-Security): raw `err.Error()` here was + // exposed to HTTP clients verbatim, including wrapped lib/pq + // driver strings that disclose schema column names + index + // hints. Log full error server-side; return a sanitized message + // to the client. Operators trace via the log line below using + // the workspace id. log.Printf("Delete: CascadeDelete(%s) failed: %v", id, err) - c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + c.JSON(http.StatusInternalServerError, gin.H{"error": "internal error processing delete request"}) return } allIDs := append([]string{id}, descendantIDs...)