@mrrlin-dev/mcp 0.4.126 → 0.4.128

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/bin.cjs +144 -20
  2. package/package.json +1 -1
package/dist/bin.cjs CHANGED
@@ -58153,12 +58153,81 @@ function emptyHooksDir() {
58153
58153
  function gitArgs(repo, args) {
58154
58154
  return ["-C", repo, "-c", `core.hooksPath=${emptyHooksDir()}`, ...args];
58155
58155
  }
58156
+ var STEP_ENV_NAMES = /* @__PURE__ */ new Set([
58157
+ // user, shell, temp dirs, locale
58158
+ "PATH",
58159
+ "HOME",
58160
+ "USER",
58161
+ "LOGNAME",
58162
+ "SHELL",
58163
+ "TERM",
58164
+ "TMPDIR",
58165
+ "TMP",
58166
+ "TEMP",
58167
+ "LANG",
58168
+ "LANGUAGE",
58169
+ "TZ",
58170
+ // what a Windows toolchain needs to start at all
58171
+ "USERPROFILE",
58172
+ "APPDATA",
58173
+ "LOCALAPPDATA",
58174
+ "PROGRAMDATA",
58175
+ "PROGRAMFILES",
58176
+ "SYSTEMROOT",
58177
+ "WINDIR",
58178
+ "COMSPEC",
58179
+ "PATHEXT",
58180
+ "HOMEDRIVE",
58181
+ "HOMEPATH",
58182
+ // proxies and the operator's own CA bundle
58183
+ "HTTP_PROXY",
58184
+ "HTTPS_PROXY",
58185
+ "NO_PROXY",
58186
+ "ALL_PROXY",
58187
+ "NODE_EXTRA_CA_CERTS",
58188
+ "SSL_CERT_FILE",
58189
+ "SSL_CERT_DIR",
58190
+ // Node and its version managers
58191
+ "NODE_ENV",
58192
+ "NODE_PATH",
58193
+ "NVM_BIN",
58194
+ "NVM_DIR",
58195
+ "VOLTA_HOME",
58196
+ "FNM_DIR",
58197
+ "ASDF_DIR",
58198
+ "ASDF_DATA_DIR",
58199
+ // the toolchains a `make test` may drive
58200
+ "JAVA_HOME",
58201
+ "GOPATH",
58202
+ "GOROOT",
58203
+ "GOCACHE",
58204
+ "GOMODCACHE",
58205
+ "CARGO_HOME",
58206
+ "RUSTUP_HOME",
58207
+ "VIRTUAL_ENV",
58208
+ "PYENV_ROOT",
58209
+ // git+ssh dependencies and commit signing
58210
+ "SSH_AUTH_SOCK",
58211
+ "GNUPGHOME"
58212
+ ]);
58213
+ var STEP_ENV_PREFIXES = ["LC_", "XDG_", "NPM_CONFIG_", "YARN_", "PNPM_", "COREPACK_"];
58214
+ var CREDENTIAL_NAME = /AUTH|TOKEN|PASSWORD|SECRET/;
58215
+ function buildLocalStepEnv(baseEnv = process.env) {
58216
+ const env = {};
58217
+ for (const [name, value] of Object.entries(baseEnv)) {
58218
+ if (value === void 0) continue;
58219
+ const upper = name.toUpperCase();
58220
+ const inFamily = STEP_ENV_PREFIXES.some((prefix) => upper.startsWith(prefix));
58221
+ if (STEP_ENV_NAMES.has(upper) || inFamily && !CREDENTIAL_NAME.test(upper)) env[name] = value;
58222
+ }
58223
+ return env;
58224
+ }
58156
58225
  function git(repo, args) {
58157
58226
  return (0, import_node_child_process15.execFileSync)("git", gitArgs(repo, args), {
58158
58227
  encoding: "utf8",
58159
58228
  timeout: 3e4,
58160
58229
  stdio: ["ignore", "pipe", "pipe"],
58161
- env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
58230
+ env: { ...buildLocalStepEnv(), GIT_TERMINAL_PROMPT: "0" }
58162
58231
  }).trim();
58163
58232
  }
58164
58233
  function gitTry(repo, args) {
@@ -58166,7 +58235,7 @@ function gitTry(repo, args) {
58166
58235
  encoding: "utf8",
58167
58236
  timeout: 3e4,
58168
58237
  stdio: ["ignore", "pipe", "pipe"],
58169
- env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
58238
+ env: { ...buildLocalStepEnv(), GIT_TERMINAL_PROMPT: "0" }
58170
58239
  });
58171
58240
  return {
58172
58241
  status: typeof result.status === "number" ? result.status : 1,
@@ -58244,7 +58313,7 @@ function createStepRunner(options = {}) {
58244
58313
  let killTimer = null;
58245
58314
  const child = (0, import_node_child_process15.spawn)(command.file, command.args, {
58246
58315
  cwd,
58247
- env: { ...process.env, CI: "1", GIT_TERMINAL_PROMPT: "0" },
58316
+ env: { ...buildLocalStepEnv(), CI: "1", GIT_TERMINAL_PROMPT: "0" },
58248
58317
  stdio: ["ignore", "pipe", "pipe"],
58249
58318
  detached: process.platform !== "win32"
58250
58319
  });
@@ -58606,11 +58675,11 @@ function withDisabledGitHooksEnv(env, hooksDir) {
58606
58675
  [`GIT_CONFIG_VALUE_${count2}`]: hooksDir
58607
58676
  };
58608
58677
  }
58609
- function git2(checkout, args, hooksDir) {
58678
+ function git2(checkout, args, hooksDir, baseEnv = process.env) {
58610
58679
  return (0, import_node_child_process16.execFileSync)("git", ["-C", checkout, "-c", `core.hooksPath=${hooksDir}`, ...args], {
58611
58680
  encoding: "utf8",
58612
58681
  timeout: 3e4,
58613
- env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
58682
+ env: { ...baseEnv, GIT_TERMINAL_PROMPT: "0" }
58614
58683
  });
58615
58684
  }
58616
58685
  async function createRunWorktree(opts) {
@@ -58645,10 +58714,11 @@ async function openRunWorktree(opts) {
58645
58714
  const worktreePath = (0, import_node_path19.join)(opts.worktreeRoot, opts.slug, opts.runId);
58646
58715
  const hooksDir = prepareDisabledGitHooksDir(opts.locksDir, opts.runId);
58647
58716
  const branch = worktreeBranch(opts.runId);
58717
+ const env = buildLocalStepEnv();
58648
58718
  await withCheckoutLock(opts.locksDir, opts.slug, async () => {
58649
58719
  if ((0, import_node_fs12.existsSync)(worktreePath)) {
58650
58720
  const real = (0, import_node_fs12.realpathSync)(worktreePath);
58651
- const listed = git2(opts.checkout, ["worktree", "list", "--porcelain"], hooksDir).split(/\n\s*\n/).map((block) => block.split("\n")).find((lines2) => {
58721
+ const listed = git2(opts.checkout, ["worktree", "list", "--porcelain"], hooksDir, env).split(/\n\s*\n/).map((block) => block.split("\n")).find((lines2) => {
58652
58722
  const listedPath = lines2.find((line) => line.startsWith("worktree "))?.slice("worktree ".length);
58653
58723
  return listedPath !== void 0 && (0, import_node_fs12.existsSync)(listedPath) && (0, import_node_fs12.realpathSync)(listedPath) === real;
58654
58724
  });
@@ -58661,13 +58731,13 @@ async function openRunWorktree(opts) {
58661
58731
  return;
58662
58732
  }
58663
58733
  try {
58664
- git2(opts.checkout, ["rev-parse", "--verify", "--quiet", `refs/heads/${branch}`], hooksDir);
58734
+ git2(opts.checkout, ["rev-parse", "--verify", "--quiet", `refs/heads/${branch}`], hooksDir, env);
58665
58735
  } catch {
58666
58736
  throw new Error(`run_branch_missing: ${opts.checkout} has no branch ${branch}`);
58667
58737
  }
58668
58738
  (0, import_node_fs12.mkdirSync)(opts.worktreeRoot, { recursive: true });
58669
- git2(opts.checkout, ["worktree", "prune"], hooksDir);
58670
- git2(opts.checkout, ["worktree", "add", worktreePath, branch], hooksDir);
58739
+ git2(opts.checkout, ["worktree", "prune"], hooksDir, env);
58740
+ git2(opts.checkout, ["worktree", "add", worktreePath, branch], hooksDir, env);
58671
58741
  });
58672
58742
  return worktreePath;
58673
58743
  }
@@ -58803,13 +58873,16 @@ async function sweepOrphanWorktrees(opts) {
58803
58873
  }
58804
58874
 
58805
58875
  // src/local-apply.ts
58876
+ function gitEnv() {
58877
+ return { ...buildLocalStepEnv(), GIT_TERMINAL_PROMPT: "0" };
58878
+ }
58806
58879
  function gitRead(cwd, args) {
58807
58880
  try {
58808
58881
  return (0, import_node_child_process17.execFileSync)("git", ["-C", cwd, ...args], {
58809
58882
  encoding: "utf8",
58810
58883
  stdio: ["ignore", "pipe", "pipe"],
58811
58884
  timeout: 3e4,
58812
- env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
58885
+ env: gitEnv()
58813
58886
  }).trim();
58814
58887
  } catch {
58815
58888
  return null;
@@ -58972,7 +59045,7 @@ async function applyLocalRunForTool(deps, input) {
58972
59045
  return { outcome: "conflict", previousSha: null, headSha: delivered.headSha, detail: integration.files.join(", ") };
58973
59046
  }
58974
59047
  const build = await runDetectedBuild({ worktreePath, runStep: deps.runStep });
58975
- const headSha = (0, import_node_child_process17.execFileSync)("git", ["-C", worktreePath, "rev-parse", "HEAD"], { encoding: "utf8" }).trim();
59048
+ const headSha = (0, import_node_child_process17.execFileSync)("git", ["-C", worktreePath, "rev-parse", "HEAD"], { encoding: "utf8", env: gitEnv() }).trim();
58976
59049
  if (build.failed) {
58977
59050
  record2({ integration, applied: false, reason: "build_failed", headSha, steps: build.steps, logs: build.logs });
58978
59051
  return { outcome: "build_failed", previousSha: null, headSha, detail: build.failed.command };
@@ -59018,7 +59091,8 @@ async function applyLocalRunForTool(deps, input) {
59018
59091
  if (!runBranchStillSigned()) return branchChanged();
59019
59092
  (0, import_node_child_process17.execFileSync)("git", ["-C", worktreePath, "-c", `core.hooksPath=${hooksDir}`, "checkout", "-q", "--detach", delivered.headSha], {
59020
59093
  stdio: ["ignore", "pipe", "pipe"],
59021
- timeout: 3e4
59094
+ timeout: 3e4,
59095
+ env: gitEnv()
59022
59096
  });
59023
59097
  try {
59024
59098
  return await reintegrate(worktreePath);
@@ -59027,9 +59101,14 @@ async function applyLocalRunForTool(deps, input) {
59027
59101
  if (runBranchStillSigned()) {
59028
59102
  (0, import_node_child_process17.execFileSync)("git", ["-C", worktreePath, "-c", `core.hooksPath=${hooksDir}`, "checkout", "-q", "-f", runBranch], {
59029
59103
  stdio: ["ignore", "pipe", "pipe"],
59030
- timeout: 3e4
59104
+ timeout: 3e4,
59105
+ env: gitEnv()
59106
+ });
59107
+ (0, import_node_child_process17.execFileSync)("git", ["-C", worktreePath, "clean", "-q", "-f", "-d"], {
59108
+ stdio: ["ignore", "pipe", "pipe"],
59109
+ timeout: 3e4,
59110
+ env: gitEnv()
59031
59111
  });
59032
- (0, import_node_child_process17.execFileSync)("git", ["-C", worktreePath, "clean", "-q", "-f", "-d"], { stdio: ["ignore", "pipe", "pipe"], timeout: 3e4 });
59033
59112
  }
59034
59113
  }
59035
59114
  },
@@ -63221,7 +63300,7 @@ Do NOT derail the current task - if the operator has an in-flight question, answ
63221
63300
  }
63222
63301
 
63223
63302
  // src/_generated/version.ts
63224
- var PKG_VERSION = "0.4.126";
63303
+ var PKG_VERSION = "0.4.128";
63225
63304
 
63226
63305
  // src/receipt-signing.ts
63227
63306
  var import_node_crypto17 = __toESM(require("node:crypto"), 1);
@@ -69861,6 +69940,28 @@ function startArtifactsGc(baseStateDir, intervalMs = 10 * 60 * 1e3, options) {
69861
69940
  };
69862
69941
  }
69863
69942
 
69943
+ // src/bridge-host-guard.ts
69944
+ var LOOPBACK_HOST_NAMES = ["127.0.0.1", "localhost", "[::1]"];
69945
+ function hostHeaderName(host) {
69946
+ const lower = host.trim().toLowerCase();
69947
+ return lower.includes(":") && !lower.startsWith("[") ? `[${lower}]` : lower;
69948
+ }
69949
+ function isAllowedBridgeHost(hostHeader, opts) {
69950
+ const { port, configuredHost } = opts;
69951
+ if (!hostHeader || port === void 0) return false;
69952
+ const names = new Set(LOOPBACK_HOST_NAMES);
69953
+ if (configuredHost?.trim()) names.add(hostHeaderName(configuredHost));
69954
+ const actual = hostHeader.trim().toLowerCase();
69955
+ for (const name of names) {
69956
+ if (actual === `${name}:${port}`) return true;
69957
+ if (port === 80 && actual === name) return true;
69958
+ }
69959
+ return false;
69960
+ }
69961
+ function isAllowedBridgeRequestHost(req, configuredHost) {
69962
+ return isAllowedBridgeHost(req.headers.host, { port: req.socket.localPort, configuredHost });
69963
+ }
69964
+
69864
69965
  // src/chat-compaction.ts
69865
69966
  var DEFAULT_COMPACTION_SEED_BUDGET_BYTES = 8e3;
69866
69967
  var DEFAULT_COMPACTION_TIMEOUT_MS = 3e4;
@@ -76752,6 +76853,10 @@ function applyPnaHeaders(res, requestOrigin, allowed) {
76752
76853
  function createBridgeRequestListener(opts) {
76753
76854
  const { host, port, token, allowedOrigins, stateDir, getHealth } = opts;
76754
76855
  return (req, res) => {
76856
+ if (!isAllowedBridgeRequestHost(req, host)) {
76857
+ res.writeHead(421).end();
76858
+ return;
76859
+ }
76755
76860
  const requestOrigin = typeof req.headers.origin === "string" ? req.headers.origin : void 0;
76756
76861
  if (req.method === "OPTIONS") {
76757
76862
  applyPnaHeaders(res, requestOrigin, allowedOrigins);
@@ -76841,7 +76946,16 @@ function sessionIdOf(msg) {
76841
76946
  }
76842
76947
  function attachBridgeWss(server, opts) {
76843
76948
  const { token, allowedOrigins, onReady, logger, onPaired, bridgeInstanceId, selfUpdate, codex } = opts;
76844
- const wss = new import_websocket_server.default({ server, path: "/ws" });
76949
+ const wss = new import_websocket_server.default({
76950
+ server,
76951
+ path: "/ws",
76952
+ // The DNS-rebinding Host check from createBridgeRequestListener, applied to the upgrade: a bad
76953
+ // Host is answered 421 and the socket is never opened, so no `ready` frame goes out.
76954
+ verifyClient: (info, done) => {
76955
+ if (isAllowedBridgeRequestHost(info.req, opts.host)) done(true);
76956
+ else done(false, 421);
76957
+ }
76958
+ });
76845
76959
  wss.on("connection", (socket, request) => {
76846
76960
  const origin = request.headers.origin;
76847
76961
  if (!isOriginAllowed(origin, allowedOrigins)) {
@@ -78453,14 +78567,20 @@ function createSelectedProviderRefresher(deps) {
78453
78567
  }
78454
78568
  });
78455
78569
  }
78570
+ var envSigningProvider;
78456
78571
  function buildBridgeSigningProvider() {
78457
78572
  const signingKeyId = process.env.MRRLIN_SIGNING_KEY_ID;
78458
78573
  const signingPrivateKey = process.env.MRRLIN_SIGNING_PRIVATE_KEY;
78574
+ delete process.env.MRRLIN_SIGNING_PRIVATE_KEY;
78459
78575
  if (signingKeyId && signingPrivateKey) {
78460
- return new LocalEd25519SigningProvider({
78576
+ envSigningProvider = new LocalEd25519SigningProvider({
78461
78577
  keyId: signingKeyId,
78462
78578
  privateKey: signingPrivateKey
78463
78579
  });
78580
+ return envSigningProvider;
78581
+ }
78582
+ if (signingKeyId && envSigningProvider?.getKeyId() === signingKeyId) {
78583
+ return envSigningProvider;
78464
78584
  }
78465
78585
  const isTestOrSmoke = process.env.NODE_ENV === "test" || process.env.MRRLIN_TEST === "1" || process.env.MRRLIN_SMOKE_TEST === "1";
78466
78586
  if (isTestOrSmoke) {
@@ -78472,6 +78592,7 @@ function buildBridgeSigningProvider() {
78472
78592
  return void 0;
78473
78593
  }
78474
78594
  async function startDirectorBridge() {
78595
+ const signingProvider = buildBridgeSigningProvider();
78475
78596
  const config2 = parseConfig();
78476
78597
  const failureLog = createFailureLog();
78477
78598
  const suppressedPushLine = (label, error51) => {
@@ -78609,7 +78730,6 @@ async function startDirectorBridge() {
78609
78730
  });
78610
78731
  const checkoutRegistry = new CheckoutRegistry(config2.stateDir);
78611
78732
  const staleSeconds = readEnvInt("MRRLIN_DIRECTOR_BRIDGE_STALE_SECONDS", DEFAULT_STALE_SECONDS);
78612
- const signingProvider = buildBridgeSigningProvider();
78613
78733
  const consumerDeps = {
78614
78734
  client,
78615
78735
  signingProvider,
@@ -78793,8 +78913,7 @@ async function startDirectorBridge() {
78793
78913
  inFlightRunIds: Array.from(consumerState.inFlightRunIds),
78794
78914
  inFlightCount: consumerState.inFlightRunIds.size,
78795
78915
  lastClaimAt: consumerState.lastClaimAt,
78796
- service: health.snapshot(),
78797
- localArtifactToken: config2.token
78916
+ service: health.snapshot()
78798
78917
  })
78799
78918
  })
78800
78919
  );
@@ -79058,6 +79177,7 @@ async function startDirectorBridge() {
79058
79177
  attachBridgeWss(server, {
79059
79178
  token: config2.token,
79060
79179
  allowedOrigins: config2.allowedOrigins,
79180
+ host: config2.host,
79061
79181
  onReady: createBridgeMessageHandler({
79062
79182
  ...sharedHandlerDeps,
79063
79183
  threads,
@@ -79111,6 +79231,10 @@ async function startDirectorBridge() {
79111
79231
  }
79112
79232
  const workerToken = readOrCreateWorkerToken();
79113
79233
  const dispatchServer = import_node_http3.default.createServer((req, res) => {
79234
+ if (!isAllowedBridgeRequestHost(req, "127.0.0.1")) {
79235
+ res.writeHead(421).end();
79236
+ return;
79237
+ }
79114
79238
  if (req.method !== "POST" || req.url !== "/worker/dispatch") {
79115
79239
  res.writeHead(404).end();
79116
79240
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrrlin-dev/mcp",
3
- "version": "0.4.126",
3
+ "version": "0.4.128",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "mrrlin-mcp": "dist/bin.cjs"