Problem
--build-with (#6116) constrains a transitive dependency that upstream leaves unbounded. That is its design: it maps to uv tool install --with '<spec>', an additive requirement the resolver must satisfy alongside what upstream declared.
It structurally cannot help when upstream pins or caps the vulnerable dependency, because no satisfiable version is left to ask for. fastmcp>=3.2.0 alongside upstream's fastmcp<3.0.0 is an unsatisfiable set, so the resolver errors instead of resolving our way. Beating a pin or a cap needs a force override, a different mechanism.
Real examples of the shape, from dockyard#668: @brightdata/mcp 2.9.5 hard-pins @modelcontextprotocol/sdk at 1.21.2 (fixes are >=1.24); mcp-clickhouse 0.3.0 caps fastmcp<3.0.0 (the CRITICAL fix is 3.2.0); mcp-neo4j-cypher 0.6.0 caps fastmcp<2.14 (all fixes excluded).
This is also why npx:// has no build-time dependency support at all. npm resolves each parent's range independently and nests a private copy, so there is no additive analogue of --with to add: installing @modelcontextprotocol/sdk@1.26.0 at the top level of the generated package.json leaves @brightdata/mcp's pinned 1.21.2 in node_modules/@brightdata/mcp/node_modules/. Overrides is npm's only lever, and it happens to cover both the pin and the cap case.
Sketch
A RuntimeConfig.BuildOverrides []string field with a --build-override flag on thv build and thv run, meaning "force this version wherever it appears in the tree". --build-with unchanged. Entries in each ecosystem's native syntax, matching the existing "interpreted per package ecosystem" convention:
- npx:
@modelcontextprotocol/sdk@1.26.0, split into name + range to become an overrides object in the package.json generated at npx.tmpl:56. npm honors overrides only from the root manifest and only if present before npm install, so that RUN echo ... > package.json line is the injection point, not the install line.
- uvx:
fastmcp>=3.2.0, written as lines of a requirements file passed to uv tool install --overrides <file> (verified present, and composable with the existing --with).
- go: reject, as
--build-with does today.
Validation needs a wider allowlist than buildWithPattern to cover npm syntax (@, /, ^, |) while still excluding anything that could escape a single-quoted shell word or a JSON string literal.
Status
Not scheduled, and there is no current consumer: dockyard is implementing native override support on its own side (dockyard#669), which supersedes its use of --build-with as well. Filing to record the finding so the next person hitting a pinned or capped transitive dep does not rediscover why --build-with will not fix it. Revisit if demand appears outside dockyard.
Problem
--build-with(#6116) constrains a transitive dependency that upstream leaves unbounded. That is its design: it maps touv tool install --with '<spec>', an additive requirement the resolver must satisfy alongside what upstream declared.It structurally cannot help when upstream pins or caps the vulnerable dependency, because no satisfiable version is left to ask for.
fastmcp>=3.2.0alongside upstream'sfastmcp<3.0.0is an unsatisfiable set, so the resolver errors instead of resolving our way. Beating a pin or a cap needs a force override, a different mechanism.Real examples of the shape, from dockyard#668:
@brightdata/mcp2.9.5 hard-pins@modelcontextprotocol/sdkat1.21.2(fixes are >=1.24);mcp-clickhouse0.3.0 capsfastmcp<3.0.0(the CRITICAL fix is 3.2.0);mcp-neo4j-cypher0.6.0 capsfastmcp<2.14(all fixes excluded).This is also why
npx://has no build-time dependency support at all. npm resolves each parent's range independently and nests a private copy, so there is no additive analogue of--withto add: installing@modelcontextprotocol/sdk@1.26.0at the top level of the generatedpackage.jsonleaves@brightdata/mcp's pinned 1.21.2 innode_modules/@brightdata/mcp/node_modules/. Overrides is npm's only lever, and it happens to cover both the pin and the cap case.Sketch
A
RuntimeConfig.BuildOverrides []stringfield with a--build-overrideflag onthv buildandthv run, meaning "force this version wherever it appears in the tree".--build-withunchanged. Entries in each ecosystem's native syntax, matching the existing "interpreted per package ecosystem" convention:@modelcontextprotocol/sdk@1.26.0, split into name + range to become anoverridesobject in thepackage.jsongenerated atnpx.tmpl:56. npm honorsoverridesonly from the root manifest and only if present beforenpm install, so thatRUN echo ... > package.jsonline is the injection point, not the install line.fastmcp>=3.2.0, written as lines of a requirements file passed touv tool install --overrides <file>(verified present, and composable with the existing--with).--build-withdoes today.Validation needs a wider allowlist than
buildWithPatternto cover npm syntax (@,/,^,|) while still excluding anything that could escape a single-quoted shell word or a JSON string literal.Status
Not scheduled, and there is no current consumer: dockyard is implementing native override support on its own side (dockyard#669), which supersedes its use of
--build-withas well. Filing to record the finding so the next person hitting a pinned or capped transitive dep does not rediscover why--build-withwill not fix it. Revisit if demand appears outside dockyard.