From 78058b147538e733f18b7e92afc8160a05f78e01 Mon Sep 17 00:00:00 2001 From: Delicious233 Date: Sun, 7 Jun 2026 18:28:42 +0800 Subject: [PATCH 1/3] =?UTF-8?q?fix(security+quality):=20audit=20remediatio?= =?UTF-8?q?n=20=E2=80=94=20safe-zone=20fixes=20only?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Security: - S-3: hub oidc service — truncate token exchange error logs to 128 chars to avoid logging potentially sensitive response bodies - S-4: hub repository — escape ILIKE wildcards (%/_) in message search to prevent user input from matching arbitrary patterns - S-6: edge CORS — explicitly set Access-Control-Allow-Credentials: false Quality: - D-1: align react/react-dom to ^19.2.7 across all packages (shared peerDep widened to >=19.2.7, mobile bumped from ^19.1.0) - BU-2: align Cargo.toml version to 0.2.0 matching tauri.conf.json Based on audit report: docs/review-2026-06-07-glm-5.1/00-SUMMARY.md Conflicting fixes deferred to backend/frontend branches — see HANDOFF-BACKEND.md and HANDOFF-FRONTEND.md. --- app/desktop/src-tauri/Cargo.toml | 2 +- app/mobile/package.json | 4 ++-- app/shared/package.json | 10 +++++----- edge-server/internal/httpserver/server.go | 2 ++ hub-server/internal/repository/message.go | 13 +++++++++++-- hub-server/internal/service/oidc.go | 9 +++++++-- 6 files changed, 28 insertions(+), 12 deletions(-) diff --git a/app/desktop/src-tauri/Cargo.toml b/app/desktop/src-tauri/Cargo.toml index dc9619cc..956240dc 100644 --- a/app/desktop/src-tauri/Cargo.toml +++ b/app/desktop/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "agenthub-desktop" -version = "0.1.0" +version = "0.2.0" edition = "2021" [lib] diff --git a/app/mobile/package.json b/app/mobile/package.json index c37a0fae..0f2040fa 100644 --- a/app/mobile/package.json +++ b/app/mobile/package.json @@ -25,8 +25,8 @@ "clsx": "^2.1.1", "i18next": "^26.2.0", "lucide-react": "^1.16.0", - "react": "^19.1.0", - "react-dom": "^19.1.0", + "react": "^19.2.7", + "react-dom": "^19.2.7", "react-i18next": "^17.0.8", "zustand": "^5.0.13" }, diff --git a/app/shared/package.json b/app/shared/package.json index 4bb98248..625448fe 100644 --- a/app/shared/package.json +++ b/app/shared/package.json @@ -32,9 +32,9 @@ }, "peerDependencies": { "lucide-react": ">=0.400.0 <2.0.0", - "react": "^19.0.0", - "react-dom": "^19.0.0", - "react-i18next": "^15.0.0" + "react": ">=19.2.7", + "react-dom": ">=19.2.7", + "react-i18next": ">=15.0.0" }, "dependencies": { "@pierre/diffs": "^1.1.0-beta.18", @@ -50,8 +50,8 @@ "@types/react-dom": "^19.1.0", "jsdom": "^29.1.1", "lucide-react": "^1.16.0", - "react": "^19.0.0", - "react-dom": "^19.0.0", + "react": "^19.2.7", + "react-dom": "^19.2.7", "typescript": "~5.8.0", "vitest": "^4.1.7" } diff --git a/edge-server/internal/httpserver/server.go b/edge-server/internal/httpserver/server.go index 8b1af2e4..be5f18c8 100644 --- a/edge-server/internal/httpserver/server.go +++ b/edge-server/internal/httpserver/server.go @@ -421,6 +421,8 @@ func corsMiddleware(next http.Handler, remoteMode bool) http.Handler { w.Header().Set("Vary", "Origin") w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PATCH, DELETE, OPTIONS") w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization, X-AgentHub-Edge-Token") + // Explicitly deny credential forwarding; edge uses Authorization headers, not cookies. + w.Header().Set("Access-Control-Allow-Credentials", "false") } if r.Method == http.MethodOptions { diff --git a/hub-server/internal/repository/message.go b/hub-server/internal/repository/message.go index 171d2285..10206cfd 100644 --- a/hub-server/internal/repository/message.go +++ b/hub-server/internal/repository/message.go @@ -2,6 +2,7 @@ package repository import ( "errors" + "strings" "gorm.io/gorm" @@ -131,11 +132,19 @@ func GetMessagesBySessionAndIDs(db *gorm.DB, sessionID string, ids []string) ([] return msgs, err } +// escapeILIKE escapes ILIKE wildcards so user input cannot match arbitrary patterns. +func escapeILIKE(s string) string { + s = strings.ReplaceAll(s, `\`, `\\`) + s = strings.ReplaceAll(s, `%`, `\%`) + s = strings.ReplaceAll(s, `_`, `\_`) + return s +} + func SearchMessages(db *gorm.DB, q, sessionID, contentType, from, to string) ([]model.Message, error) { var msgs []model.Message query := db.Where("session_id = ?", sessionID). Where("recalled = false"). - Where("content->>'text' ILIKE ?", "%"+q+"%") + Where("content->>'text' ILIKE ?", "%"+escapeILIKE(q)+"%") if contentType != "" { query = query.Where("content_type = ?", contentType) } @@ -156,7 +165,7 @@ func SearchAllMessages(db *gorm.DB, userID, q, contentType, from, to string) ([] WHERE sm.member_type = ? AND sm.member_id = ? AND sm.left_at IS NULL AND m.recalled = false AND m.content->>'text' ILIKE ?` - args := []interface{}{"user", userID, "%" + q + "%"} + args := []interface{}{"user", userID, "%" + escapeILIKE(q) + "%"} if contentType != "" { sql += " AND m.content_type = ?" diff --git a/hub-server/internal/service/oidc.go b/hub-server/internal/service/oidc.go index b6082c27..cbea0203 100644 --- a/hub-server/internal/service/oidc.go +++ b/hub-server/internal/service/oidc.go @@ -284,12 +284,17 @@ func (s *OIDCService) exchangeCode(ctx context.Context, code, codeVerifier, redi } if resp.StatusCode != http.StatusOK { + // Truncate body to avoid logging potentially sensitive token exchange data. + bodyPreview := string(body) + if len(bodyPreview) > 128 { + bodyPreview = bodyPreview[:128] + "...(truncated)" + } slog.Error("oidc token endpoint returned non-200", "status", resp.StatusCode, - "response_body", string(body), + "response_body_preview", bodyPreview, "redirect_uri_sent", redirectURI, ) - return nil, fmt.Errorf("token endpoint returned %d: %s", resp.StatusCode, string(body)) + return nil, fmt.Errorf("token endpoint returned %d", resp.StatusCode) } var tokenResp tokenEndpointResponse From d564e5846ad7bf85624bcdc805fefe67d37898a1 Mon Sep 17 00:00:00 2001 From: Delicious233 Date: Sun, 7 Jun 2026 18:34:52 +0800 Subject: [PATCH 2/3] fix(deps+config): remove unused deps, align tsconfig exactOptionalPropertyTypes D-2: Remove unused npm dependencies (zero source references): - @pierre/diffs (shared) - @tanstack/react-virtual (desktop, web) - class-variance-authority (desktop) - zod (web) BU-1: Align exactOptionalPropertyTypes to false across all packages. Web had true while others had false/unset, causing cross-project type signature incompatibility. Mobile now has explicit false. --- app/desktop/package.json | 2 -- app/mobile/tsconfig.json | 1 + app/shared/package.json | 1 - app/web/package.json | 2 -- app/web/tsconfig.json | 2 +- 5 files changed, 2 insertions(+), 6 deletions(-) diff --git a/app/desktop/package.json b/app/desktop/package.json index d9ec2f81..72f30c94 100644 --- a/app/desktop/package.json +++ b/app/desktop/package.json @@ -27,11 +27,9 @@ "dependencies": { "@lobehub/icons": "^5.10.0", "@tanstack/react-query": "^5.100.14", - "@tanstack/react-virtual": "^3.14.2", "@tauri-apps/api": "^2.11.0", "@tauri-apps/plugin-dialog": "2.7.1", "@tauri-apps/plugin-shell": "^2.2.0", - "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "i18next": "^26.2.0", "lucide-react": "^1.16.0", diff --git a/app/mobile/tsconfig.json b/app/mobile/tsconfig.json index 619993c6..31f48ffa 100644 --- a/app/mobile/tsconfig.json +++ b/app/mobile/tsconfig.json @@ -6,6 +6,7 @@ "moduleResolution": "bundler", "jsx": "react-jsx", "strict": true, + "exactOptionalPropertyTypes": false, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, diff --git a/app/shared/package.json b/app/shared/package.json index 625448fe..07b3fb66 100644 --- a/app/shared/package.json +++ b/app/shared/package.json @@ -37,7 +37,6 @@ "react-i18next": ">=15.0.0" }, "dependencies": { - "@pierre/diffs": "^1.1.0-beta.18", "diff": "^8.0.2", "prismjs": "^1.30.0" }, diff --git a/app/web/package.json b/app/web/package.json index be49c3cf..72004e23 100644 --- a/app/web/package.json +++ b/app/web/package.json @@ -16,7 +16,6 @@ "dependencies": { "@lobehub/icons": "^5.10.0", "@tanstack/react-query": "^5.100.14", - "@tanstack/react-virtual": "^3.14.2", "i18next": "^26.2.0", "lucide-react": "^1.16.0", "react": "^19.2.7", @@ -24,7 +23,6 @@ "react-i18next": "^17.0.8", "react-markdown": "^10.1.0", "react-syntax-highlighter": "^16.1.1", - "zod": "^4.4.3", "zustand": "^5.0.13" }, "devDependencies": { diff --git a/app/web/tsconfig.json b/app/web/tsconfig.json index d7430d3d..945e4bef 100644 --- a/app/web/tsconfig.json +++ b/app/web/tsconfig.json @@ -7,7 +7,7 @@ "strict": true, "strictNullChecks": true, "noUncheckedIndexedAccess": true, - "exactOptionalPropertyTypes": true, + "exactOptionalPropertyTypes": false, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, From 1aaf76329a6e844633c6e7fd284b64226d9b84a2 Mon Sep 17 00:00:00 2001 From: Delicious233 Date: Sun, 7 Jun 2026 18:36:20 +0800 Subject: [PATCH 3/3] fix(tsconfig): align Desktop exactOptionalPropertyTypes to true (matching Web) Desktop/Web unified UI requires identical strictness. Both now use exactOptionalPropertyTypes: true. Mobile untouched (not yet active). Desktop typecheck passes. Web typecheck passes. --- app/desktop/tsconfig.json | 2 +- app/mobile/tsconfig.json | 1 - app/web/tsconfig.json | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/desktop/tsconfig.json b/app/desktop/tsconfig.json index b24ab3f7..67d5f84a 100644 --- a/app/desktop/tsconfig.json +++ b/app/desktop/tsconfig.json @@ -6,7 +6,7 @@ "jsx": "react-jsx", "strict": true, "noUncheckedIndexedAccess": true, - "exactOptionalPropertyTypes": false, + "exactOptionalPropertyTypes": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, diff --git a/app/mobile/tsconfig.json b/app/mobile/tsconfig.json index 31f48ffa..619993c6 100644 --- a/app/mobile/tsconfig.json +++ b/app/mobile/tsconfig.json @@ -6,7 +6,6 @@ "moduleResolution": "bundler", "jsx": "react-jsx", "strict": true, - "exactOptionalPropertyTypes": false, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, diff --git a/app/web/tsconfig.json b/app/web/tsconfig.json index 945e4bef..d7430d3d 100644 --- a/app/web/tsconfig.json +++ b/app/web/tsconfig.json @@ -7,7 +7,7 @@ "strict": true, "strictNullChecks": true, "noUncheckedIndexedAccess": true, - "exactOptionalPropertyTypes": false, + "exactOptionalPropertyTypes": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true,