Skip to content

feat: mcp build tool hardening#40717

Open
cryptotavares wants to merge 1 commit intomainfrom
cryptotavares/mcp-hardening
Open

feat: mcp build tool hardening#40717
cryptotavares wants to merge 1 commit intomainfrom
cryptotavares/mcp-hardening

Conversation

@cryptotavares
Copy link
Contributor

@cryptotavares cryptotavares commented Mar 9, 2026

Description

Open in GitHub Codespaces

Changelog

CHANGELOG entry:

Related issues

Fixes:

Manual testing steps

  1. Go to this page...

Screenshots/Recordings

Before

After

Pre-merge author checklist

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

Note

Medium Risk
Moderate risk because it changes how build commands are spawned and how fixture/chain/mock-server capabilities are started/stopped during session launch and cleanup, which could affect e2e workflow stability despite added tests and validation.

Overview
Hardens mm_build execution. MetaMaskBuildCapability now runs yarn via spawn('yarn', args) with shell: false, pipes child output to stderr to avoid corrupting MCP stdout, and adds an allowlist/validation for buildType and custom command parts to prevent injection.

Improves session lifecycle reliability. The MCP session manager now disposes capabilities on context switches, adds rollback logic to stop any partially-started services (fixture server, Anvil chain, mock server, launcher) when launch fails, and makes cleanup() stop services in parallel with warning logs.

Config/docs updates. The LLM workflow README updates MCP client configs to prefer absolute node + local tsx paths (avoiding yarn tsx in GUI clients), documents OpenCode timeouts, and adds startup troubleshooting guidance.

Written by Cursor Bugbot for commit 1e6ac1e. This will update automatically on new commits. Configure here.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 9, 2026

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@metamaskbot metamaskbot added the team-product-safety Push issues to Product Safety team label Mar 9, 2026
@github-actions github-actions bot added the size-M label Mar 9, 2026
@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Mar 9, 2026

Builds ready [9ebb5b9]
⚡ Performance Benchmarks
👆 Interaction Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Load New Accountload_new_account29227132219292322
total29227132219292322
Confirm Txconfirm_tx605060476052260526052
total605060476052260526052
Bridge User Actionsbridge_load_page2412372485248248
bridge_load_asset_picker2162102204220220
bridge_search_token71870274115722741
total1201110813449212711344
🔌 Startup Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Standard HomeuiStartup13401116166110013751527
load112694113779011661291
domContentLoaded111892713499011621281
domInteractive271591182374
firstPaint185611349173208316
backgroundConnect19217523812194217
firstReactRender18114361929
initialActions109114
loadScripts9437491175899841102
setupStore1163141320
numNetworkReqs3122100212290
Power User HomeuiStartup2349136510547152522195324
load11861014170415312291551
domContentLoaded11691007168614812051534
domInteractive3519146213677
firstPaint1848257991262323
backgroundConnect63525442288053822458
firstReactRender23165262434
initialActions104113
loadScripts95980114421409801319
setupStore1464861724
numNetworkReqs66261542985125
🧭 User Journey Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Onboarding Import WalletimportWalletToSocialScreen2202192210221221
srpButtonToSrpForm94949509595
confirmSrpToPwForm22212202222
pwFormToMetricsScreen16151601616
metricsToWalletReadyScreen17161701717
doneButtonToHomeScreen896595123027512241230
openAccountMenuToAccountListLoaded75787009804445079278044
total88428607916020189049160
Onboarding New WalletcreateWalletToSocialScreen2212192242223224
srpButtonToPwForm1061051082107108
createPwToRecoveryScreen888088
skipBackupToMetricsScreen36353713637
agreeButtonToOnboardingSuccess16161601616
doneButtonToAssetList57148069891618698
total96187710838710031083
Asset DetailsassetClickToPriceChart37334134041
total37334134041
Solana Asset DetailsassetClickToPriceChart46434924749
total46434924749
Import Srp HomeloginToHomeScreen1955188320055220032005
openAccountMenuAfterLogin38354233942
homeAfterImportWithNewWallet24582330261910325072619
total4506443045605245494560
Send TransactionsopenSendPageFromHome38374013840
selectTokenToSendFormLoaded18181901919
reviewTransactionToConfirmationPage88485591225904912
total93590396829961968
SwapopenSwapPageFromHome12810116728158167
fetchAndDisplaySwapQuotes4626458546522746504652
total4758474347851647544785
🌐 Dapp Page Load Benchmarks

Current Commit: 9ebb5b9 | Date: 3/9/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.08s (±73ms) 🟡 | historical mean value: 1.03s ⬆️ (historical data)
  • domContentLoaded-> current mean value: 747ms (±70ms) 🟢 | historical mean value: 722ms ⬆️ (historical data)
  • firstContentfulPaint-> current mean value: 83ms (±13ms) 🟢 | historical mean value: 80ms ⬆️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.08s 73ms 1.04s 1.37s 1.30s 1.37s
domContentLoaded 747ms 70ms 712ms 1.03s 959ms 1.03s
firstPaint 83ms 13ms 68ms 204ms 88ms 204ms
firstContentfulPaint 83ms 13ms 68ms 204ms 88ms 204ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 5.24 MiB (100%)
  • ui: 8.14 MiB (100%)
  • common: 10.9 MiB (100%)

Base automatically changed from cryptotavares/add-metamask-extension-mcp to main March 9, 2026 22:29
    - Prevent shell injection in BuildCapability by validating buildType
      against an allowlist and using spawn with shell: false
    - Redirect build stdout/stderr to process.stderr to avoid corrupting
      the MCP stdio protocol
    - Wrap launch() in try/catch with rollback of partially started
      capabilities (fixture, chain, mock server, browser)
    - Isolate cleanup() stop failures with Promise.allSettled so one
      failing stop cannot block the rest; reset state in finally
    - Apply input.ports.fixtureServer at launch time via setPort()
    - Best-effort dispose prior capabilities on setContext() switch
    - Clear forceKill timer when build process exits after SIGTERM
    - Replace unsafe as-casts with instanceof type guards for
      MetaMaskFixtureCapability and MetaMaskContractSeedingCapability
    - Record resolved extensionPath in session metadata instead of
      possibly-undefined input value
@cryptotavares cryptotavares force-pushed the cryptotavares/mcp-hardening branch from 9ebb5b9 to 1e6ac1e Compare March 10, 2026 01:22
@cryptotavares cryptotavares changed the title Cryptotavares/mcp hardening feat: mcp build tool hardening Mar 10, 2026
@cryptotavares cryptotavares marked this pull request as ready for review March 10, 2026 01:23
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

if (stops.length > 0) {
Promise.allSettled(stops).catch(() => undefined);
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unawaited promises in disposeCurrentCapabilities causes race condition

Medium Severity

disposeCurrentCapabilities is a synchronous void method that creates stop promises but never awaits them. The Promise.allSettled(stops) on line 145 is fire-and-forget. The caller setContext immediately proceeds to create and set a new workflow context while old capability servers (fixture, mock, chain) may still be shutting down. This can cause port conflicts or resource leaks if the new context's launch() tries to bind to ports still held by the old capabilities.

Fix in Cursor Fix in Web


const mockServerCapability = this.getMockServerCapability();
if (mockServerCapability) {
await mockServerCapability.stop();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resource leak when post-launch setup throws errors

High Severity

After the try-catch block in launch, errors thrown between lines 482–492 (e.g., getStateSnapshotCapability() returning null, or stateSnapshot.getState() failing) leave the launcher and all started capabilities (fixture, chain, mock server) running with no cleanup. rollbackStartedCapabilities is only called inside the catch block, and this.activeSession isn't set until line 498, so the caller can't use cleanup() either.

Fix in Cursor Fix in Web

@sonarqubecloud
Copy link

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Mar 10, 2026

Builds ready [1e6ac1e]
⚡ Performance Benchmarks
👆 Interaction Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Load New Accountload_new_account28327330915276309
total28327330915276309
Confirm Txconfirm_tx6069604561092460826109
total6069604561092460826109
Bridge User Actionsbridge_load_page21219822611219226
bridge_load_asset_picker25524226611264266
bridge_search_token77175878712778787
total1238122212701912341270
🔌 Startup Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Standard HomeuiStartup14461203166510815241638
load12121003143810512961392
domContentLoaded12051001141810312811372
domInteractive2917126192680
firstPaint175731255170218343
backgroundConnect21219425512214239
firstReactRender19134852026
initialActions106124
loadScripts1010811122210310921176
setupStore1364261723
numNetworkReqs312290192284
Power User HomeuiStartup2772165912125180124394945
load12091030198517912451607
domContentLoaded11931020180917112301588
domInteractive3620131223589
firstPaint217761829207261362
backgroundConnect909262986816163892641
firstReactRender25165672839
initialActions108113
loadScripts97481215621629991350
setupStore1664781736
numNetworkReqs823525047100172
🧭 User Journey Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Onboarding Import WalletimportWalletToSocialScreen2212192232223223
srpButtonToSrpForm96949929899
confirmSrpToPwForm21212202222
pwFormToMetricsScreen16151601616
metricsToWalletReadyScreen16151701617
doneButtonToHomeScreen60358362016615620
openAccountMenuToAccountListLoaded293729322941429412941
total3900388639211339003921
Onboarding New WalletcreateWalletToSocialScreen2202182211220221
srpButtonToPwForm1061021113108111
createPwToRecoveryScreen888088
skipBackupToMetricsScreen35353503535
agreeButtonToOnboardingSuccess16151601616
doneButtonToAssetList4924904963492496
total8798778822879882
Asset DetailsassetClickToPriceChart15713817614165176
total15713817614165176
Solana Asset DetailsassetClickToPriceChart71687537375
total71687537375
Import Srp HomeloginToHomeScreen20481828221313521642213
openAccountMenuAfterLogin49435864958
homeAfterImportWithNewWallet2429230025158124782515
total44914171473920745774739
Send TransactionsopenSendPageFromHome17122341723
selectTokenToSendFormLoaded291845113845
reviewTransactionToConfirmationPage8478448502848850
total8898808998895899
SwapopenSwapPageFromHome38334443944
fetchAndDisplaySwapQuotes268326822683126832683
total271627062723627212723
🌐 Dapp Page Load Benchmarks

Current Commit: 1e6ac1e | Date: 3/10/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 976ms (±39ms) 🟢 | historical mean value: 1.05s ⬇️ (historical data)
  • domContentLoaded-> current mean value: 684ms (±36ms) 🟢 | historical mean value: 740ms ⬇️ (historical data)
  • firstContentfulPaint-> current mean value: 77ms (±11ms) 🟢 | historical mean value: 83ms ⬇️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 976ms 39ms 945ms 1.25s 1.02s 1.25s
domContentLoaded 684ms 36ms 659ms 943ms 718ms 943ms
firstPaint 77ms 11ms 64ms 164ms 88ms 164ms
firstContentfulPaint 77ms 11ms 64ms 164ms 88ms 164ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 5.15 MiB (100%)
  • ui: 8.24 MiB (100%)
  • common: 10.99 MiB (100%)

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

Labels

size-M team-product-safety Push issues to Product Safety team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants