Conversation
NitayRabi
added a commit
that referenced
this pull request
Jul 13, 2026
…harden unverified escape hatch Three follow-ups from review of #74: - Dockerfile: the production stage never copied dependencies.manifest.json, which DependencyResolver requires from the package root at construction time. Every run in the container died with MODULE_NOT_FOUND before it could resolve anything. Verified by building the image before and after. - ib-client: runtimeDir still pointed at <package>/ib-gateway/.runtime, so the tickler recreated state inside the installed package (the directory v2 removes) and split session state across two locations. It also fails with EACCES on a root-owned global install. It now uses DependencyResolver.runDir() like the gateway manager. - dependency-resolver: IB_GATEWAY_ALLOW_UNVERIFIED waived the pinned sha256 even when the live CDN ETag was unavailable, installing wholly unverified bytes while the error text claimed the ETag was still checked. The escape hatch now requires the live ETag check to have actually run. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ries Stop checking in and publishing the IB Client Portal Gateway jars and the per-platform Java runtimes (~350MB). They are now downloaded on demand from official vendor sources, verified, and cached in a per-user directory outside the package. - New DependencyResolver resolves user-managed deps first (IB_GATEWAY_DIR, IB_JAVA_HOME/JAVA_HOME, or a compatible system java), else downloads and verifies pinned artifacts recorded in dependencies.manifest.json. - Java: BellSoft Liberica JRE 11 for all platforms (glibc + musl), pinned sha256. - Gateway: downloaded only over HTTPS from the official IB host and verified against both the live CDN ETag MD5 and a pinned sha256; IB_GATEWAY_ALLOW_UNVERIFIED allows proceeding past a sha256 rotation while the live ETag check still runs. - The downloaded gateway runs with IB's own default configuration (no overlay); hardening guidance is in SECURITY.md. - Controls: IB_DOWNLOADS_DISABLED, IB_CACHE_DIR, IB_GATEWAY_DIR, IB_JAVA_HOME, IB_GATEWAY_ALLOW_UNVERIFIED. Session metadata/locks/logs moved to <cache>/run/. - Add SECURITY.md documenting the supply-chain and network posture. - Replace bundled-runtime build scripts with scripts/update-dependency-manifest.mjs. Closes #67. Addresses #62 and #63. BREAKING CHANGE: the package no longer bundles the IB Gateway or a Java runtime. First run requires network access to download and verify them. Users who need the previous fully-offline behavior can pin to interactive-brokers-mcp@1, or pre-install the dependencies and set IB_DOWNLOADS_DISABLED=true. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…harden unverified escape hatch Three follow-ups from review of #74: - Dockerfile: the production stage never copied dependencies.manifest.json, which DependencyResolver requires from the package root at construction time. Every run in the container died with MODULE_NOT_FOUND before it could resolve anything. Verified by building the image before and after. - ib-client: runtimeDir still pointed at <package>/ib-gateway/.runtime, so the tickler recreated state inside the installed package (the directory v2 removes) and split session state across two locations. It also fails with EACCES on a root-owned global install. It now uses DependencyResolver.runDir() like the gateway manager. - dependency-resolver: IB_GATEWAY_ALLOW_UNVERIFIED waived the pinned sha256 even when the live CDN ETag was unavailable, installing wholly unverified bytes while the error text claimed the ETag was still checked. The escape hatch now requires the live ETag check to have actually run. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ResolvedGateway is only used inside dependency-resolver.ts as the return type of resolveGateway(); nothing imports it (unlike ResolvedJava, which gateway-manager does import). Exporting it tripped knip's unused-exports check. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #67 (umbrella for #62, #63).
Summary
v2stops checking in and publishing the IB Client Portal Gateway jars and the per-platform Java runtimes (~350 MB). They are now downloaded on demand from official vendor sources, verified, and cached in a per-user directory outside the package. The npm tarball drops from hundreds of MB to ~265 kB packed / 46 files / 0 binaries.This is a breaking change (first run needs network access), released as
2.0.0.What changed
DependencyResolver(src/dependency-resolver.ts) resolves dependencies in order:IB_GATEWAY_DIR,IB_JAVA_HOME/JAVA_HOME, or a compatible systemjava(auto-adopted only for major 11–17).dependencies.manifest.json.~/.cache/interactive-brokers-mcp(orIB_CACHE_DIR) and reuse.sha256(verified against the vendor's publishedsha1at pin time).ETagMD5 and a pinnedsha256. IB publishes no checksum file, so this hybrid gives an always-from-IB dynamic check plus a reviewed anchor.IB_GATEWAY_ALLOW_UNVERIFIED=trueallows proceeding past asha256rotation while the live ETag check still runs.IB_GATEWAY_DIRgateway is used as-is. (See the security note below.)IB_DOWNLOADS_DISABLED,IB_CACHE_DIR,IB_GATEWAY_DIR,IB_JAVA_HOME,IB_GATEWAY_ALLOW_UNVERIFIED. Session metadata/locks/logs moved to<cache>/run/.SECURITY.mddocumenting the supply-chain and network posture + vulnerability reporting; linked from the README.scripts/update-dependency-manifest.mjs(maintainer tool,npm run manifest:update).extract-zip→adm-zip(extract-zip's promise never resolves under Node 24).Dropping the config overlay means the gateway now uses IB's default
ips.allow, which permits IB's default ranges (192.*,131.216.*) in addition to loopback — vs. the previous loopback-only hardening. This was a deliberate choice (prefer not modifying IB's defaults). The loopback-only hardening recipe and network exposure are documented inSECURITY.md.User impact / migration
npxrun may require network access, take longer, and create a local cache.interactive-brokers-mcp@1, or pre-install Java + the gateway and setIB_DOWNLOADS_DISABLED=truewithIB_GATEWAY_DIR/IB_JAVA_HOME.Verification
npm run build✅ ·vitest✅ 193 passed / 2 skipped (added 11 resolver tests) ·oxlint✅ (warnings only) ·npm audit --omit=dev✅ 0 vulns ·knip✅ clean.IBGatewayManagerstarts the gateway on IB's unmodified default config (came up READY).🤖 Generated with Claude Code