From d17f57e29ffe5d2e8281fcd38297de76a6817080 Mon Sep 17 00:00:00 2001 From: Hongming Wang Date: Sat, 18 Apr 2026 01:15:26 -0700 Subject: [PATCH] fix(plugins): wire VerifyManifestIntegrity into install pipeline The supply_chain.go implementation was merged in #937 but never called from the actual install handler. Plugins with a manifest.json sha256 field now get verified before staging completes. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../internal/handlers/plugins_install_pipeline.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/workspace-server/internal/handlers/plugins_install_pipeline.go b/workspace-server/internal/handlers/plugins_install_pipeline.go index 9cac22f0..c4454b1f 100644 --- a/workspace-server/internal/handlers/plugins_install_pipeline.go +++ b/workspace-server/internal/handlers/plugins_install_pipeline.go @@ -210,7 +210,18 @@ func (h *PluginsHandler) resolveAndStage(ctx context.Context, req installRequest }) } - // SHA-256 content integrity check (SAFE-T1102). + // Manifest-declared SHA-256 content integrity check. + // If the staged plugin ships a manifest.json with a "sha256" field, verify + // the declared hash matches the actual staged tree contents. + if err := plugins.VerifyManifestIntegrity(stagedDir); err != nil { + cleanup() + return nil, newHTTPErr(http.StatusUnprocessableEntity, gin.H{ + "error": err.Error(), + "source": source.Raw(), + }) + } + + // Caller-pinned SHA-256 content integrity check (SAFE-T1102). // If the caller pinned a hash, verify it against the staged plugin.yaml. // A mismatch means the fetched content differs from what was audited — // abort rather than silently install an unexpected plugin.