Skip to content

feat(sdk): add validateMcpb() for pre-install bundle validation#94

Merged
mgoldsborough merged 5 commits intoNimbleBrainInc:mainfrom
Ovaculos:feat/validate-mcpb
May 7, 2026
Merged

feat(sdk): add validateMcpb() for pre-install bundle validation#94
mgoldsborough merged 5 commits intoNimbleBrainInc:mainfrom
Ovaculos:feat/validate-mcpb

Conversation

@Ovaculos
Copy link
Copy Markdown
Contributor

@Ovaculos Ovaculos commented May 4, 2026

Summary

  • Adds validateMcpb(path) function that validates .mcpb archives without side effects
  • Extracts to temp dir, checks manifest against McpbManifestSchema, verifies entry point exists, cleans up
  • Returns { valid: true, manifest } or { valid: false, errors: string[] }
  • Exports types: McpbValidationResult, McpbValidationSuccess, McpbValidationFailure

Test plan

  • 11 unit tests covering: valid bundles, missing files, non-zip, missing manifest, schema violations, bad server type, invalid JSON, missing entry point, temp cleanup on success/failure
  • npx pnpm@9.15.4 test passes

Closes #93

🤖 Generated with Claude Code

Validates .mcpb archives without side effects: extracts to temp dir,
checks manifest.json against McpbManifestSchema, verifies entry point
exists, cleans up. Returns typed result with manifest or error list.

Closes NimbleBrainInc#93

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ovaculos and others added 4 commits May 5, 2026 23:19
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add valid and broken .mcpb fixtures derived from mcp-obsidian-cli and
assert validateMcpb passes on the well-formed bundle and fails with a
manifest error on the corrupted one.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Tightens the contract at the schema layer: entry_point is now constrained
to a non-empty relative path within the bundle (no NUL bytes, no absolute
POSIX/Windows paths, no UNC paths, no `..` segments).

Previously every consumer that read a manifest trusted entry_point to be a
safe relative path despite the schema saying `z.string()`. validateMcpb,
loadLocalBundle, and prepareServer all do `join(dir, entry_point)`. A
malicious manifest with `entry_point: "../../etc/passwd"` would pass
validation and resolve to a system file at runtime. Fixing one consumer
(validateMcpb) leaves the trust violation in place for the others; fixing
the schema fixes them all.

Adds SafeRelativePathSchema in packages/schemas. Pure-JS so the package
stays browser-safe (consumed by apps/web). Comprehensive schema-level
tests plus end-to-end coverage at the validateMcpb layer.

Also updates the SDK's public-export smoke test and README to include
validateMcpb (gap from PR NimbleBrainInc#94).

Verified: 96 schemas tests pass, 234 sdk-typescript tests pass, every
real manifest in the repo (registry seed, scanner fixtures with a server
block) still parses, and the original entry_point repro now correctly
returns valid: false.
Closes a Windows-traversal gap in SafeRelativePathSchema:

- `\foo` (drive-root-relative) — `path.join("C:\cache\bundle", "\\foo")`
  resolves to `\foo` on the current drive
- `C:foo` (drive without separator) — drive-relative absolute

The simplest correct rule for a path inside a ZIP archive is "no
backslashes anywhere." MCPB bundles are zip archives whose central
directory uses forward slashes; backslash paths have no legitimate use.
Combining that with rejecting any drive-letter prefix subsumes all
Windows-style traversal forms.
@mgoldsborough
Copy link
Copy Markdown
Contributor

Follow-ups from QA review (filed as separate issues — none block this PR):

@mgoldsborough mgoldsborough merged commit 40fe89f into NimbleBrainInc:main May 7, 2026
3 checks passed
@Ovaculos Ovaculos deleted the feat/validate-mcpb branch May 7, 2026 15:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

qa-reviewed QA review completed with no critical issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(sdk): add validateMcpb() for pre-install bundle validation

2 participants