From 7333619f155a9064e30c71ce5e2258978ab0b325 Mon Sep 17 00:00:00 2001 From: Xvvln <3369759202@qq.com> Date: Tue, 24 Mar 2026 00:27:44 +0800 Subject: [PATCH] fix: reject oversized downloads instead of truncating; warn on unverified fallback - Read maxAssetDownloadSize+1 bytes and error if exceeded, preventing silent truncation that could write a broken management.html to disk - Log explicit warning when fallback URL is used without digest verification, so users are aware of the reduced security guarantee --- internal/managementasset/updater.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/internal/managementasset/updater.go b/internal/managementasset/updater.go index 642dbf2f..473c1a91 100644 --- a/internal/managementasset/updater.go +++ b/internal/managementasset/updater.go @@ -288,6 +288,9 @@ func ensureFallbackManagementHTML(ctx context.Context, client *http.Client, loca return false } + log.Warnf("management asset downloaded from fallback URL without digest verification (hash=%s) — "+ + "consider setting auto-update-panel: true to receive verified updates from GitHub", downloadedHash) + if err = atomicWriteFile(localPath, data); err != nil { log.WithError(err).Warn("failed to persist fallback management control panel page") return false @@ -398,10 +401,13 @@ func downloadAsset(ctx context.Context, client *http.Client, downloadURL string) return nil, "", fmt.Errorf("unexpected download status %d: %s", resp.StatusCode, strings.TrimSpace(string(body))) } - data, err := io.ReadAll(io.LimitReader(resp.Body, maxAssetDownloadSize)) + data, err := io.ReadAll(io.LimitReader(resp.Body, maxAssetDownloadSize+1)) if err != nil { return nil, "", fmt.Errorf("read download body: %w", err) } + if int64(len(data)) > maxAssetDownloadSize { + return nil, "", fmt.Errorf("download exceeds maximum allowed size of %d bytes", maxAssetDownloadSize) + } sum := sha256.Sum256(data) return data, hex.EncodeToString(sum[:]), nil