Skip to content

Verify signed MCPB bundles#286

Open
jstar0 wants to merge 1 commit into
modelcontextprotocol:mainfrom
jstar0:fix/verify-signed-bundles
Open

Verify signed MCPB bundles#286
jstar0 wants to merge 1 commit into
modelcontextprotocol:mainfrom
jstar0:fix/verify-signed-bundles

Conversation

@jstar0

@jstar0 jstar0 commented Jun 19, 2026

Copy link
Copy Markdown

Summary

Fixes mcpb verify reporting freshly signed bundles as unsigned.

verifyMcpbFile parsed the embedded PKCS#7 SignedData with node-forge and then called p7.verify(), but node-forge does not implement PKCS#7 verification. That made valid signed bundles fall through to { status: "unsigned" }.

This change verifies detached CMS signatures with platform tooling instead:

  • Windows uses PowerShell/.NET System.Security.Cryptography.Pkcs.SignedCms.
  • macOS/Linux use openssl cms -verify -noverify -binary.

Refs #277.

Motivation and Context

Signing currently breaks the end-to-end publisher workflow in two ways: mcpb sign can produce a bundle with a signature block, but mcpb verify reports that same bundle as unsigned. The failure happens because node-forge parses the PKCS#7 SignedData but does not implement the verification method being called.

Changes

  • Keep node-forge for generating and parsing PKCS#7 metadata, but stop using its unimplemented p7.verify() method.
  • Verify the detached signature against the original bundle bytes before returning signed metadata.
  • Preserve the existing trusted-certificate behavior for non-self-signed certificates.
  • Sign the final ZIP bytes after the EOCD comment length has been updated for the appended signature block, so the bytes being verified match the bytes that were signed.
  • Tighten the signing e2e test so a freshly self-signed bundle must verify as self-signed, not unsigned.

How Has This Been Tested?

The focused signing e2e test fails before the implementation because the self-signed bundle verifies as unsigned; it passes after the change.

Verification

npm test -- test/sign.e2e.test.ts --runInBand
npm test -- --runInBand
npm run lint
npm run build
git diff --check

Breaking Changes

None expected. This keeps the existing signature block format and status values.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

I could not execute the Windows SignedCms branch on this macOS host. The macOS/Linux OpenSSL branch is covered by the signing e2e tests, and the Windows branch is covered by TypeScript build/lint.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant