Skip to content

feat(dockhand): support transitive dependency overrides/constraints in spec.yaml#669

Draft
JAORMX wants to merge 1 commit into
mainfrom
feat/dep-overrides
Draft

feat(dockhand): support transitive dependency overrides/constraints in spec.yaml#669
JAORMX wants to merge 1 commit into
mainfrom
feat/dep-overrides

Conversation

@JAORMX
Copy link
Copy Markdown
Collaborator

@JAORMX JAORMX commented Jun 3, 2026

Implements the dependency-override mechanism from #668.

What

Renovate version bumps fail the build-containers Grype gate (--fail-on high --only-fixed) when the bumped package pins/caps a transitive dependency to a vulnerable version. This adds an optional override mechanism to spec.yaml, plumbed into the generated Dockerfile. toolhive needs no changes — its BuildFromProtocolSchemeWithName(..., dryRun=true) returns the Dockerfile as a string, which is the injection seam.

Schema (cmd/dockhand/main.go)

# npx -> npm "overrides"
spec:
  overrides:
    - package: "@modelcontextprotocol/sdk"
      version: "1.26.0"
      reason: "required, auditable justification"

# uvx -> uv "--overrides" requirements file
spec:
  constraints:
    - spec: "fastmcp>=3.2.0"
      reason: "required, auditable justification"
  • Overrides []OverrideEntry{Package, Version, Reason} (npx only)
  • Constraints []ConstraintEntry{Spec, Reason} (uvx only)
  • Reason is mandatory — validation fails otherwise, mirroring security.allowed_issues.
  • Overrides are rejected on non-npx protocols; constraints on non-uvx protocols.

Injection

  • npx: rewrites the RUN echo '{...}' > package.json step to embed an overrides block (npm honors overrides only from package.json), kept before the npm install step.
  • uvx: injects a RUN printf ... > /tmp/uv-overrides.txt step before the install step and adds --overrides /tmp/uv-overrides.txt to the uv tool install invocation. The install line is matched by content, ignoring comment lines that merely mention uv tool install.

Verification (end-to-end: dockhand-generated Dockerfile -> docker build -> grype --fail-on high --only-fixed)

PR Override Result
#469 npm override @modelcontextprotocol/sdk 1.26.0 SDK resolves to 1.26.0; grype gate passes (exit 0)
#527 uv constraint fastmcp>=3.2.0 fastmcp 3.4.0; import mcp_clickhouse OK; grype gate passes
#528 uv constraint fastmcp>=3.2.0 fastmcp 3.4.0; import mcp_neo4j_cypher OK; grype passes — but crosses upstream's deliberate <2.14 cap (major 2->3); functional testing of the neo4j tools is required before relying on it.

go build ./..., go vet, go test ./cmd/dockhand/..., and golangci-lint run ./cmd/dockhand/... all pass.

Follow-up

This PR only adds the mechanism — it does not modify the three renovate spec.yaml files. After this merges to main, each renovate PR (#469, #527, #528) needs to be rebased on main and have its override/constraint block added to its spec.yaml.

Refs #668

🤖 Generated with Claude Code

…n spec.yaml

Renovate version bumps fail the build-containers Grype gate when the bumped
package pins or caps a transitive dependency to a vulnerable version. Add an
optional dependency-override mechanism to the spec.yaml schema, plumbed into the
generated Dockerfile.

- npx: spec.overrides ([]{package, version, reason}) is injected as an npm
  "overrides" block in the generated package.json before the npm install step.
- uvx: spec.constraints ([]{spec, reason}) is written to a uv overrides
  requirements file and passed to "uv tool install --overrides".

Both injection points match the install step by content (not line number) so
they stay robust to toolhive template formatting. Every entry requires a
non-empty reason (validation fails otherwise) so the justification for
circumventing an upstream pin is auditable in-repo.

Verified end-to-end against the CI build + Grype recipe:
- #469 @brightdata/mcp 2.9.5 + override @modelcontextprotocol/sdk 1.26.0:
  resolves to SDK 1.26.0, grype --fail-on high --only-fixed passes.
- #527 mcp-clickhouse 0.3.0 + constraint fastmcp>=3.2.0: fastmcp 3.4.0,
  import mcp_clickhouse OK, grype passes.

Refs #668

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@toolhive-release-app
Copy link
Copy Markdown
Contributor

🔒 MCP Security Scan Results

⚠️ No MCP servers were scanned in this PR.

@toolhive-release-app
Copy link
Copy Markdown
Contributor

🛡️ Skill Security Scan Results

⚠️ No skills were scanned in this PR.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant