diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b19a38c..125b923 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,92 +1,155 @@ -# Contributing to ToolHive +# Contributing to Dockyard -First off, thank you for taking the time to contribute to ToolHive! :+1: :tada: -ToolHive is released under the Apache 2.0 license. If you would like to -contribute something or want to hack on the code, this document should help you -get started. You can find some hints for starting development in ToolHive's -[README](https://github.com/stacklok/toolhive/blob/main/README.md). +Thank you for your interest in contributing to Dockyard! This document helps you get started. -## Table of contents +## Table of Contents -- [Code of conduct](#code-of-conduct) -- [Reporting security vulnerabilities](#reporting-security-vulnerabilities) -- [How to contribute](#how-to-contribute) - - [Using GitHub Issues](#using-github-issues) - - [Not sure how to start contributing?](#not-sure-how-to-start-contributing) - - [Pull request process](#pull-request-process) - - [Contributing to docs](#contributing-to-docs) - - [Commit message guidelines](#commit-message-guidelines) +- [Code of Conduct](#code-of-conduct) +- [Reporting Security Vulnerabilities](#reporting-security-vulnerabilities) +- [Ways to Contribute](#ways-to-contribute) +- [Adding an MCP Server](#adding-an-mcp-server) +- [Development Setup](#development-setup) +- [Pull Request Process](#pull-request-process) +- [Commit Message Guidelines](#commit-message-guidelines) -## Code of conduct +## Code of Conduct -This project adheres to the -[Contributor Covenant](https://github.com/stacklok/toolhive/blob/main/CODE_OF_CONDUCT.md) -code of conduct. By participating, you are expected to uphold this code. Please -report unacceptable behavior to -[code-of-conduct@stacklok.dev](mailto:code-of-conduct@stacklok.dev). +This project adheres to the [Contributor Covenant](CODE_OF_CONDUCT.md) code of conduct. By participating, you are expected to uphold this code. Please report unacceptable behavior to [code-of-conduct@stacklok.dev](mailto:code-of-conduct@stacklok.dev). -## Reporting security vulnerabilities +## Reporting Security Vulnerabilities -If you think you have found a security vulnerability in ToolHive please DO NOT -disclose it publicly until we've had a chance to fix it. Please don't report -security vulnerabilities using GitHub issues; instead, please follow this -[process](https://github.com/stacklok/toolhive/blob/main/SECURITY.MD) +If you think you have found a security vulnerability in Dockyard, please **DO NOT** disclose it publicly until we've had a chance to fix it. Please don't report security vulnerabilities using GitHub issues; instead, follow the process in [SECURITY.MD](SECURITY.MD). -## How to contribute +## Ways to Contribute -### Using GitHub Issues +### Add an MCP Server -We use GitHub issues to track bugs and enhancements. If you have a general usage -question, please ask in -[ToolHive's discussion forum](https://discord.gg/stacklok). +The most common contribution is adding a new MCP server to Dockyard. See [Adding an MCP Server](#adding-an-mcp-server) below. -If you are reporting a bug, please help to speed up problem diagnosis by -providing as much information as possible. Ideally, that would include a small -sample project that reproduces the problem. +### Report Bugs -### Not sure how to start contributing? +Use [GitHub Issues](https://github.com/stacklok/dockyard/issues) to report bugs. Please include: +- Steps to reproduce the issue +- Expected vs actual behavior +- Container image name and version (if applicable) -PRs to resolve existing issues are greatly appreciated, and issues labeled as -["good first issue"](https://github.com/stacklok/toolhive/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) -are a great place to start! +### Suggest Enhancements -### Pull request process +We welcome feature suggestions! Open an issue describing: +- The problem you're trying to solve +- Your proposed solution +- Any alternatives you've considered -- -All commits must include a Signed-off-by trailer at the end of each commit - message to indicate that the contributor agrees to the Developer Certificate - of Origin. For additional details, check out the [DCO instructions](dco.md). -- Create an issue outlining the fix or feature. -- Fork the ToolHive repository to your own GitHub account and clone it locally. -- Hack on your changes. -- Correctly format your commit messages, see - [Commit message guidelines](#commit-message-guidelines) below. -- Open a PR by ensuring the title and its description reflect the content of the - PR. -- Ensure that CI passes, if it fails, fix the failures. -- Every pull request requires a review from the core ToolHive team before - merging. -- Once approved, all of your commits will be squashed into a single commit with - your PR title. +### Improve Documentation -### Contributing to docs +Documentation improvements are always welcome. See the [docs/](docs/) directory. -The ToolHive user documentation website is maintained in the -[docs-website](https://github.com/stacklok/docs-website) repository. If you want -to contribute to the documentation, please open a PR in that repo. +## Adding an MCP Server -Please review the README and -[STYLE-GUIDE](https://github.com/stacklok/docs-website/blob/main/STYLE-GUIDE.md) -in the docs-website repository for more information on how to contribute to the -documentation. +To add your MCP server to Dockyard: -### Commit message guidelines +1. Create a directory: `{protocol}/{server-name}/` +2. Add a `spec.yaml` configuration file +3. Submit a pull request -We follow the commit formatting recommendations found on -[Chris Beams' How to Write a Git Commit Message article](https://chris.beams.io/posts/git-commit/): +**Full guide:** [Adding MCP Servers](docs/adding-servers.md) + +**Quick example:** + +```yaml +metadata: + name: my-server + description: "What my server does" + protocol: npx + +spec: + package: "@my-org/mcp-server" + version: "1.0.0" +``` + +## Development Setup + +### Prerequisites + +- Go 1.21+ +- Docker or Podman +- [Task](https://taskfile.dev/) (optional, for convenience) + +### Build the CLI + +```bash +go build -o build/dockhand ./cmd/dockhand +``` + +### Run Tests + +```bash +go test ./... +``` + +### Generate a Dockerfile + +```bash +./build/dockhand build -c npx/context7/spec.yaml +``` + +### Verify Provenance + +```bash +./build/dockhand verify-provenance -c npx/context7/spec.yaml -v +``` + +## Pull Request Process + +1. **Fork and clone** the repository +2. **Create a branch** for your changes +3. **Make your changes** with clear, focused commits +4. **Test locally** if adding an MCP server: + ```bash + task build -- {protocol}/{server-name} + task scan -- {protocol}/{server-name} + ``` +5. **Submit a PR** with a clear description + +### PR Requirements + +- All commits must include a Signed-off-by trailer (DCO) +- CI checks must pass (security scan, build, etc.) +- One approval from a maintainer is required + +### For MCP Server PRs + +Include in your PR description: +- What the MCP server does +- Link to the package registry (npm/PyPI) +- Link to the source repository + +## Commit Message Guidelines + +Follow [Chris Beams' guidelines](https://chris.beams.io/posts/git-commit/): 1. Separate subject from body with a blank line -1. Limit the subject line to 50 characters -1. Capitalize the subject line -1. Do not end the subject line with a period -1. Use the imperative mood in the subject line -1. Use the body to explain what and why vs. how +2. Limit the subject line to 50 characters +3. Capitalize the subject line +4. Do not end the subject line with a period +5. Use the imperative mood in the subject line +6. Use the body to explain what and why vs. how + +**Example:** + +``` +Add context7 MCP server + +Add packaging for context7 v1.0.14 from Upstash. +This server provides vector search and context management. + +Package: https://www.npmjs.com/package/@upstash/context7-mcp +Repository: https://github.com/upstash/context7-mcp + +Signed-off-by: Your Name +``` + +## Questions? + +- Open a [GitHub Discussion](https://github.com/stacklok/dockyard/discussions) +- Join the [Stacklok Discord](https://discord.gg/stacklok) diff --git a/README.md b/README.md index 5dea0ce..b405577 100644 --- a/README.md +++ b/README.md @@ -1,514 +1,94 @@ -# Dockyard - MCP Server Container Builder +# Dockyard -> **A centralized repository for packaging Model Context Protocol (MCP) servers into containers** +[![Build Status](https://github.com/stacklok/dockyard/actions/workflows/build-containers.yml/badge.svg)](https://github.com/stacklok/dockyard/actions/workflows/build-containers.yml) +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE) -Dockyard automatically builds and publishes container images for MCP servers that aren't already containerized. It uses [ToolHive](https://docs.stacklok.com/toolhive) to build containers from protocol schemes and provides a simple YAML-based configuration system. +**A centralized repository for packaging Model Context Protocol (MCP) servers into secure, verified containers.** -## 🚀 Quick Start +Dockyard automatically builds, scans, and publishes container images for MCP servers. Every container is security-scanned, signed with Sigstore, and includes full build provenance. -Want to add your MCP server? Just create a YAML file in the appropriate protocol directory and submit a PR! Our automated CI/CD pipeline will build and publish the container image automatically. - -## đŸ“Ļ Supported Protocols - -- **`npx://`** - Node.js packages from npm registry -- **`uvx://`** - Python packages using uv package manager -- **`go://`** - Go packages and modules - -## đŸ—ī¸ Available MCP Servers - -| Server | Protocol | Container Image | Description | -|--------|----------|-----------------|-------------| -| [Context7](https://github.com/upstash/context7-mcp) | npx | `ghcr.io/stacklok/dockyard/npx/context7:1.0.14` | Upstash vector search and context management | -| [AWS Documentation](https://github.com/awslabs/mcp) | uvx | `ghcr.io/stacklok/dockyard/uvx/aws-documentation-mcp-server:1.1.2` | AWS Labs documentation server | - -## 🤝 Contributing Your Own MCP Server - -Adding your MCP server to Dockyard is simple! Follow these steps: - -### Step 1: Choose the Right Protocol Directory - -- **`npx/`** - For Node.js packages published to npm -- **`uvx/`** - For Python packages published to PyPI -- **`go/`** - For Go modules and packages - -### Step 2: Create Your MCP Server Directory and Configuration - -Create a new directory for your MCP server in the appropriate protocol folder, then add a `spec.yaml` file: - -```bash -# Create directory structure -mkdir -p {protocol}/{your-server-name} - -# Create spec.yaml file -``` - -The `spec.yaml` file should have this structure: - -```yaml -# Comments are encouraged! Describe what your MCP server does -# Package URL: https://... -# Repository: https://... -# Will build as: ghcr.io/stacklok/dockyard/{protocol}/{name}:{version} - -metadata: - name: your-server-name # Required: Unique server name - description: "Brief description" # Optional: What does your server do? - version: "1.0.0" # Optional: Server version - protocol: npx # Required: npx, uvx, or go - -spec: - package: "your-package-name" # Required: Package name from registry - version: "1.0.0" # Required: Specific version to build - args: # Optional: Additional arguments for the package - - "arg1" # Arguments are passed to the entrypoint - - "arg2" - -provenance: # Optional but recommended - repository_uri: "https://github.com/user/repo" # Expected source repository (used for verification) - repository_ref: "refs/tags/v1.0.0" # Git tag/branch/commit - - # Attestation information (optional - documents package provenance) - attestations: - available: true # Whether the package has provenance attestations - verified: true # Whether attestations have been cryptographically verified - publisher: - kind: "GitHub" # Publisher type (e.g., GitHub, GitLab) - repository: "user/repo" # Publisher repository - workflow: ".github/workflows/release.yml" # Publishing workflow -``` - -### Step 3: Protocol-Specific Examples - -#### NPX (Node.js) Example - -Directory structure: -``` -npx/ -└── my-node-server/ - └── spec.yaml -``` - -Content of `npx/my-node-server/spec.yaml`: -```yaml -# NPM package: https://www.npmjs.com/package/@your-org/mcp-server -metadata: - name: my-node-server - description: "My awesome Node.js MCP server" - version: "2.1.0" - protocol: npx - -spec: - package: "@your-org/mcp-server" # NPM package name - version: "2.1.0" - args: # Optional: Add required CLI arguments - - "start" # For packages that need specific commands - -provenance: - repository_uri: "https://github.com/your-org/mcp-server" - repository_ref: "refs/tags/v2.1.0" -``` - -**Real-world example** (LaunchDarkly MCP server): -```yaml -# Some packages require specific CLI arguments to run -# These are baked into the container entrypoint -spec: - package: "@launchdarkly/mcp-server" - version: "0.4.2" - args: - - "start" # Required by LaunchDarkly's CLI -# Results in: ENTRYPOINT ["npx", "@launchdarkly/mcp-server", "start"] -``` - -#### UVX (Python) Example - -Directory structure: -``` -uvx/ -└── my-python-server/ - └── spec.yaml -``` - -Content of `uvx/my-python-server/spec.yaml`: -```yaml -# PyPI package: https://pypi.org/project/your-mcp-server/ -metadata: - name: my-python-server - description: "My awesome Python MCP server" - version: "1.5.2" - protocol: uvx - -spec: - package: "your-mcp-server" # PyPI package name - version: "1.5.2" - -provenance: - repository_uri: "https://github.com/your-org/python-mcp-server" - repository_ref: "refs/tags/v1.5.2" -``` - -#### Go Example - -Directory structure: -``` -go/ -└── my-go-server/ - └── spec.yaml -``` - -Content of `go/my-go-server/spec.yaml`: -```yaml -# Go module: go get github.com/your-org/go-mcp-server -metadata: - name: my-go-server - description: "My awesome Go MCP server" - version: "0.3.1" - protocol: go - -spec: - package: "github.com/your-org/go-mcp-server" # Go module path - version: "v0.3.1" # Go version tag - -provenance: - repository_uri: "https://github.com/your-org/go-mcp-server" - repository_ref: "refs/tags/v0.3.1" -``` - -### Step 4: Submit Your Pull Request - -1. Fork this repository -2. Create your server directory and `spec.yaml` file in the appropriate protocol directory -3. Submit a pull request with: - - Clear title: "Add [Your Server Name] MCP server" - - Description of what your server does - - Link to the package registry and source repository - -**Note**: Your MCP server will be automatically scanned for security vulnerabilities. The PR will only be mergeable if the security scan passes. - -### Step 5: Automated Building - -Once your PR passes security scanning and is merged: -- ✅ Security scan ensures no vulnerabilities -- 🤖 GitHub Actions automatically detects your new configuration -- đŸ—ī¸ Builds a container image using ToolHive -- đŸ“Ļ Publishes to `ghcr.io/stacklok/dockyard/{protocol}/{name}:{version}` -- 🔄 Renovate keeps your package version up-to-date automatically - -## 🔒 Security Scanning - -Dockyard automatically scans all MCP servers for security vulnerabilities before building containers using [Cisco AI Defense mcp-scanner](https://github.com/cisco-ai-defense/mcp-scanner). This ensures that only secure MCP servers are deployed. - -### What We Scan For - -- **Prompt Injection Risks**: Detects dangerous words or patterns in tool descriptions that could be exploited -- **Toxic Flows**: Identifies combinations of tools that could lead to destructive behaviors -- **Tool Poisoning**: Checks for malicious tool implementations -- **Cross-Origin Escalation**: Detects potential privilege escalation vulnerabilities -- **Rug Pull Attacks**: Identifies suspicious patterns that could indicate malicious intent - -### Security Requirements - -All MCP servers must pass security scanning before being merged. If vulnerabilities are detected: -- The CI pipeline will fail -- A detailed report will be posted as a PR comment -- The vulnerabilities must be addressed OR explicitly allowed before the PR can be merged - -### Allowing Known Issues - -Some security warnings may be false positives, especially for containerized deployments where additional sandboxing is provided. You can explicitly allow specific security issues by adding a `security` section to your YAML configuration: - -```yaml -security: - # Security allowlist for known issues that are acceptable in this context - allowed_issues: - - code: "AITech-1.1" - reason: "Tool description contains imperative instructions for AI agents which are necessary for proper operation" - - code: "AITech-9.1" - reason: "Destructive toxic flow is mitigated by container sandboxing - code execution is isolated from host system" -``` - -Each allowed issue must include: -- `code`: The issue code reported by mcp-scanner (e.g., AITech-1.1, AITech-8.2, AITech-9.1) -- `reason`: A clear explanation of why this issue is acceptable in your specific context - -### Security Report Example - -When vulnerabilities are found, you'll see a detailed report in your PR: - -``` -## 🔒 MCP Security Scan Results - -### ❌ your-mcp-server -- **Status**: Failed -- **Tools scanned**: 3 -- **Vulnerabilities found**: 2 - -**Security issues detected:** -- **[W001]** Tool description contains dangerous words that could be used for prompt injection -- **[TF002]** Destructive toxic flow detected -``` - -If issues are allowlisted, they won't fail the build: - -``` -â„šī¸ Allowed security issues found in your-mcp-server: - - [W001] Tool description contains dangerous words... - Reason: Tool description contains imperative instructions for AI agents which are necessary for proper operation -✅ All issues are allowlisted - build can proceed (3 tools scanned) -``` - -## 🔐 Container Security & Attestations - -All container images built by Dockyard are signed and attested using Sigstore for supply chain security. Each image includes: - -- **Container Signatures**: Images are signed with Sigstore/Cosign -- **SBOM Attestation**: Software Bill of Materials (SPDX format) for dependency tracking -- **Build Provenance**: Build provenance attestation for build integrity -- **Security Scan Attestation**: MCP security scan results are attested - -### Verifying Container Signatures - -To verify that an image was built and signed by Dockyard: +## Quick Start ```bash -# Install cosign if you haven't already -brew install cosign # or see https://docs.sigstore.dev/cosign/installation/ +# Pull a container +docker pull ghcr.io/stacklok/dockyard/npx/context7:2.1.0 -# Verify image signature +# Verify its signature cosign verify \ --certificate-identity-regexp "https://github.com/stacklok/dockyard/.github/workflows/build-containers.yml@refs/heads/.*" \ --certificate-oidc-issuer https://token.actions.githubusercontent.com \ - ghcr.io/stacklok/dockyard/npx/context7:1.0.14 -``` - -### Verifying Attestations - -#### Build Provenance & SBOM Attestations (OCI Artifacts) - -Docker buildx automatically creates and pushes SBOM (SPDX format) and provenance attestations as OCI artifacts. These are stored alongside the image and can be inspected using Docker buildx: - -```bash -# View SBOM attestation for all platforms -docker buildx imagetools inspect \ - ghcr.io/stacklok/dockyard/npx/context7:1.0.14 \ - --format "{{ json .SBOM }}" - -# View Provenance attestation for all platforms -docker buildx imagetools inspect \ - ghcr.io/stacklok/dockyard/npx/context7:1.0.14 \ - --format "{{ json .Provenance }}" - -# Get the raw SBOM for a specific platform -docker buildx imagetools inspect \ - ghcr.io/stacklok/dockyard/npx/context7:1.0.14 \ - --format '{{ range .SBOM }}{{ if eq .Platform "linux/amd64" }}{{ .Data }}{{ end }}{{ end }}' | base64 -d | jq - -# Get the raw Provenance for a specific platform -docker buildx imagetools inspect \ - ghcr.io/stacklok/dockyard/npx/context7:1.0.14 \ - --format '{{ range .Provenance }}{{ if eq .Platform "linux/amd64" }}{{ .Data }}{{ end }}{{ end }}' | base64 -d | jq -``` - -Note: These attestations are stored as OCI artifacts in the registry, not as Sigstore attestations. They provide supply chain transparency but are verified differently than cosign attestations. - -#### Security Scan Attestation (SCAI) - -MCP security scan results are attested using the [SCAI (Software Supply Chain Attribute Integrity)](https://github.com/in-toto/attestation/blob/main/spec/predicates/scai.md) predicate type, an official in-toto format recognized by policy engines like Kyverno, OPA, and Gatekeeper. - -```bash -# Verify and retrieve security scan attestation (if available) -cosign verify-attestation \ - --type https://in-toto.io/attestation/scai/v0.3 \ - --certificate-identity-regexp "https://github.com/stacklok/dockyard/.github/workflows/build-containers.yml@refs/heads/.*" \ - --certificate-oidc-issuer https://token.actions.githubusercontent.com \ - ghcr.io/stacklok/dockyard/npx/context7:1.0.14 + ghcr.io/stacklok/dockyard/npx/context7:2.1.0 -# Extract scan conditions from attestation -cosign download attestation ghcr.io/stacklok/dockyard/npx/context7:1.0.14 | \ - jq -r 'select(.payloadType == "application/vnd.in-toto+json") | .payload | @base64d | fromjson | .predicate.attributes[0].conditions' +# Run it +docker run -it ghcr.io/stacklok/dockyard/npx/context7:2.1.0 ``` -For detailed attestation schema, policy examples, and verification commands, see [docs/attestations.md](docs/attestations.md). - -Note: Security scan attestations are only created when the MCP security scan runs and produces results for that specific image build. - -### Container Vulnerability Scanning +## Documentation -All built container images are scanned for vulnerabilities using [Trivy](https://trivy.dev/), checking for: - -- **Vulnerabilities**: CVEs in OS packages and application dependencies (CRITICAL, HIGH, MEDIUM severity) -- **Secrets**: Exposed API keys, tokens, credentials -- **Misconfigurations**: Security issues in container configuration - -Scan results are: -- Uploaded to the **GitHub Security** tab for each repository -- Available in the **Security** → **Code scanning** section -- Non-blocking for PRs (informational only) -- Automatically run on every build and weekly via periodic scans - -To view scan results: -```bash -# Navigate to: https://github.com/stacklok/dockyard/security/code-scanning -# Filter by "trivy-{server-name}" to see specific results -``` +| I want to... | Go here | +|--------------|---------| +| **Use Dockyard containers** | [Getting Started](docs/getting-started.md) | +| **Add my MCP server** | [Adding MCP Servers](docs/adding-servers.md) | +| **Understand the security model** | [Security Overview](docs/security.md) | +| **Verify attestations** | [Container Attestations](docs/attestations.md) | +| **Check package provenance** | [Package Provenance](docs/provenance.md) | -Trivy scans run: -1. **On every PR**: Provides immediate feedback on new/changed containers -2. **On main branch**: Scans all published images after build -3. **Weekly (Monday 2am UTC)**: Comprehensive periodic scans to catch newly disclosed CVEs -4. **Manual trigger**: Run periodic scans on-demand via GitHub Actions +## Supported Protocols -### Security Guarantees +| Protocol | Registry | Example | +|----------|----------|---------| +| `npx://` | npm | `ghcr.io/stacklok/dockyard/npx/context7:2.1.0` | +| `uvx://` | PyPI | `ghcr.io/stacklok/dockyard/uvx/aws-documentation-mcp-server:1.1.16` | +| `go://` | Go modules | `ghcr.io/stacklok/dockyard/go/netbird:0.1.0` | -When you use a Dockyard container image, you can be confident that: +Browse available servers: [npx/](npx/) | [uvx/](uvx/) | [go/](go/) -1. **Source Integrity**: The image was built from the exact source code in this repository -2. **Build Transparency**: Full build provenance is available and verifiable -3. **MCP Security Scanning**: The MCP server was scanned for security vulnerabilities before packaging -4. **Container Vulnerability Scanning**: Container images are scanned with Trivy for CVEs, secrets, and misconfigurations -5. **Dependency Tracking**: Complete SBOM is available for vulnerability management -6. **Non-repudiation**: Signatures prove the image came from our CI/CD pipeline -7. **Continuous Monitoring**: Weekly scans catch newly disclosed vulnerabilities in published images +## Add Your MCP Server -## đŸ—ī¸ How It Works +Create a `spec.yaml` in the appropriate directory and submit a PR: -1. **Detection**: GitHub Actions detects changes to YAML files -2. **Provenance Verification**: Verifies package provenance using `dockhand verify-provenance` (informational) -3. **MCP Security Scan**: Runs Cisco AI Defense mcp-scanner to check for MCP-specific vulnerabilities (blocking) -4. **Validation**: Validates YAML structure and required fields -5. **Protocol Scheme**: Constructs protocol scheme (e.g., `npx://@upstash/context7-mcp@1.0.14`) -6. **Container Build**: Uses ToolHive's `BuildFromProtocolSchemeWithName` function (only if security scan passes) -7. **Container Vulnerability Scan**: Scans built images with Trivy for CVEs, secrets, and misconfigurations (non-blocking) -8. **Attestation**: Creates and signs SBOM, provenance, and security scan attestations -9. **Publishing**: Pushes to GitHub Container Registry with automatic tagging -10. **Updates**: Renovate automatically creates PRs for new package versions - -### CI/CD Pipeline - -The CI/CD pipeline runs in this order: - -```mermaid -graph TD - A[Discover Configs] --> B[Verify Provenance] - B --> C[MCP Security Scan] - C --> D{MCP Scan Passed?} - D -->|Yes| E[Build Containers] - D -->|No| F[Fail Build] - E --> G[Trivy Vulnerability Scan] - G --> H[Sign with Cosign] - H --> I[Create Attestations] - I --> J[Push to Registry] - J --> K[Upload Trivy Results to Security Tab] -``` - -**Provenance verification** is informational and does not block builds - it helps track which packages have cryptographic verification available. - -## 📋 Container Image Naming - -All containers follow this naming pattern: -``` -ghcr.io/stacklok/dockyard/{protocol}/{name}:{version} -``` - -Examples: -- `ghcr.io/stacklok/dockyard/npx/context7:1.0.14` -- `ghcr.io/stacklok/dockyard/uvx/aws-documentation-mcp-server:1.1.2` -- `ghcr.io/stacklok/dockyard/go/my-mcp-server:latest` - -## 🔍 Package Provenance Verification - -Dockyard includes built-in support for verifying package provenance using cryptographic attestations. This helps ensure supply chain security by verifying the authenticity and origin of packages. - -### Checking Provenance - -Use the `verify-provenance` command to check if a package has provenance information: - -```bash -# Verify npm package provenance -./build/dockhand verify-provenance -c npx/context7/spec.yaml - -# Verify PyPI package provenance -./build/dockhand verify-provenance -c uvx/mcp-clickhouse/spec.yaml - -# Verbose output with details -./build/dockhand verify-provenance -c uvx/aws-documentation/spec.yaml -v -``` - -### Provenance Coverage - -Current provenance coverage for packaged MCP servers: - -**npm packages (npx/) - 17 total:** -- 16 packages (94%) have **legacy npm signatures** - detected but not cryptographically verified -- 1 package (6%) has **modern attestations** - @jetbrains/mcp-proxy with SLSA provenance - -**PyPI packages (uvx/) - 12 total:** -- 3 packages (25%) have **PEP 740 attestations** with cryptographic verification - - AWS Labs packages (aws-documentation, aws-diagram) - - ClickHouse (mcp-clickhouse) -- 9 packages (75%) have no provenance - -### What Gets Verified - -**For npm:** -- **Legacy signatures** (16 packages): Detection only - confirms they exist -- **Modern attestations** (1 package): Downloads Sigstore bundles, verifies cryptographically - -**For PyPI with attestations (3 packages):** -1. **Cryptographic signatures** using Sigstore -2. **Publisher identity** (GitHub Actions from the expected repository) -3. **Transparency logs** (Rekor entries) -4. **Certificate validity** via Sigstore trust roots -5. **Artifact integrity** (SHA256 hashes match) - -### Measuring Provenance - -Scripts are available in `scripts/` to measure provenance coverage: - -```bash -# Check npm provenance for all packages -python3 scripts/check-npm-provenance.py +```yaml +metadata: + name: your-server + description: "What your server does" + protocol: npx # or uvx, go -# Check PyPI provenance for all packages -python3 scripts/check-pypi-provenance.py +spec: + package: "your-package-name" + version: "1.0.0" ``` -Results are saved to JSON files for tracking over time. +Our CI/CD pipeline will automatically: +1. Scan for security vulnerabilities (blocking) +2. Verify package provenance (informational) +3. Build multi-arch containers +4. Sign and attest with Sigstore +5. Publish to `ghcr.io/stacklok/dockyard` -## đŸ› ī¸ Local Development +See [Adding MCP Servers](docs/adding-servers.md) for the full guide. -### Prerequisites -- Go 1.21+ -- Docker or Podman -- ToolHive library +## Security -### Build and install dockhand: +Every container includes: +- **MCP Security Scan** - Scanned with [mcp-scanner](https://github.com/cisco-ai-defense/mcp-scanner) before build +- **Container Scan** - Trivy vulnerability scanning +- **Signed Images** - Sigstore/Cosign keyless signatures +- **Attestations** - SBOM, build provenance, and security scan results -```bash -go build -o dockhand ./cmd/dockhand -# Or install globally -go install ./cmd/dockhand -``` +See [Security Overview](docs/security.md) for details. -### Generate a Dockerfile: +## Contributing -```bash -# Generate Dockerfile to stdout -./dockhand build -c npx/context7/spec.yaml +We welcome contributions! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. -# Save Dockerfile to file -./dockhand build -c npx/context7/spec.yaml -o Dockerfile -``` +To add an MCP server, see [Adding MCP Servers](docs/adding-servers.md). -### Build with custom tag: +## License -```bash -./dockhand build -c npx/context7/spec.yaml -t my-custom-tag:latest -``` +Apache 2.0 - see [LICENSE](LICENSE) for details. -## 🔧 Dependencies +## Links -- **[ToolHive](https://github.com/stacklok/toolhive)** - Container building from protocol schemes -- **[gopkg.in/yaml.v3](https://gopkg.in/yaml.v3)** - YAML configuration parsing -- **[Renovate](https://renovatebot.com/)** - Automated dependency updates -- **[Cisco AI Defense mcp-scanner](https://github.com/cisco-ai-defense/mcp-scanner)** - Security vulnerability scanning for MCP servers +- [ToolHive](https://docs.stacklok.com/toolhive) - Container building technology +- [MCP Documentation](https://modelcontextprotocol.io/) - Model Context Protocol +- [Sigstore](https://docs.sigstore.dev/) - Container signing diff --git a/docs/adding-servers.md b/docs/adding-servers.md new file mode 100644 index 0000000..cfc99b0 --- /dev/null +++ b/docs/adding-servers.md @@ -0,0 +1,292 @@ +# Adding MCP Servers to Dockyard + +This guide walks you through packaging and contributing your MCP server to Dockyard. + +## Overview + +Adding your MCP server is simple: +1. Create a `spec.yaml` configuration file +2. Submit a pull request +3. CI/CD automatically builds, scans, and publishes your container + +## Directory Structure + +``` +{protocol}/{server-name}/spec.yaml +``` + +Choose the protocol directory based on your package type: +- `npx/` - Node.js packages from npm +- `uvx/` - Python packages from PyPI +- `go/` - Go modules + +## spec.yaml Reference + +```yaml +# {Server Name} MCP Server Configuration +# Package: {package-registry-url} +# Repository: {source-repository-url} +# Will build as: ghcr.io/stacklok/dockyard/{protocol}/{name}:{version} + +metadata: + name: your-server-name # Required: Unique server name + description: "Brief description" # Optional: What does your server do? + version: "1.0.0" # Optional: Server version + protocol: npx # Required: npx, uvx, or go + +spec: + package: "your-package-name" # Required: Package name from registry + version: "1.0.0" # Required: Specific version to build + args: # Optional: CLI arguments for the package + - "arg1" # Passed to the entrypoint command + - "arg2" + +provenance: # Optional but recommended + repository_uri: "https://github.com/user/repo" + repository_ref: "refs/tags/v1.0.0" + + # Attestation information (if available) + attestations: + available: true # Whether the package has provenance attestations + verified: true # Whether you've verified the attestations + publisher: + kind: "GitHub" # Publisher type (e.g., GitHub, GitLab) + repository: "user/repo" # Publisher repository + workflow: "release.yml" # Publishing workflow (optional) + +# Optional: Security scan allowlist +security: + allowed_issues: + - code: "AITech-1.1" + reason: "Explanation of why this issue is acceptable" +``` + +## Protocol-Specific Examples + +### Node.js (npx) + +```yaml +# NPM package: https://www.npmjs.com/package/@your-org/mcp-server +metadata: + name: my-node-server + description: "My awesome Node.js MCP server" + version: "2.1.0" + protocol: npx + +spec: + package: "@your-org/mcp-server" # NPM package name + version: "2.1.0" + +provenance: + repository_uri: "https://github.com/your-org/mcp-server" + repository_ref: "refs/tags/v2.1.0" +``` + +Some packages require specific CLI arguments: + +```yaml +# LaunchDarkly requires the "start" command +spec: + package: "@launchdarkly/mcp-server" + version: "0.4.2" + args: + - "start" +# Results in: ENTRYPOINT ["npx", "@launchdarkly/mcp-server", "start"] +``` + +### Python (uvx) + +```yaml +# PyPI package: https://pypi.org/project/your-mcp-server/ +metadata: + name: my-python-server + description: "My awesome Python MCP server" + version: "1.5.2" + protocol: uvx + +spec: + package: "your-mcp-server" # PyPI package name + version: "1.5.2" + +provenance: + repository_uri: "https://github.com/your-org/python-mcp-server" + repository_ref: "refs/tags/v1.5.2" +``` + +### Go + +```yaml +# Go module: go get github.com/your-org/go-mcp-server +metadata: + name: my-go-server + description: "My awesome Go MCP server" + version: "0.3.1" + protocol: go + +spec: + package: "github.com/your-org/go-mcp-server" # Go module path + version: "v0.3.1" # Go version tag + +provenance: + repository_uri: "https://github.com/your-org/go-mcp-server" + repository_ref: "refs/tags/v0.3.1" +``` + +## Step-by-Step Process + +### 1. Find Package Information + +```bash +# Python +curl -s https://pypi.org/pypi/{package}/json | jq -r '.info.version' + +# Node.js +npm view {package} version +``` + +### 2. Create Directory Structure + +```bash +mkdir -p {protocol}/{server-name} +``` + +### 3. Create spec.yaml + +Use the template above, filling in your package details. + +### 4. Verify Provenance (Recommended) + +Check if your package has provenance attestations: + +```bash +# Build dockhand first +go build -o build/dockhand ./cmd/dockhand + +# Verify provenance +./build/dockhand verify-provenance -c {protocol}/{server-name}/spec.yaml -v +``` + +Document any provenance information in your spec.yaml. See [Package Provenance](provenance.md) for details. + +### 5. Test Locally + +```bash +# Validate spec and generate Dockerfile +task build -- {protocol}/{server-name} + +# Run security scan +task scan -- {protocol}/{server-name} + +# Optional: Build and test container image +task test-build -- {protocol}/{server-name} +``` + +### 6. Submit Pull Request + +1. Fork the repository +2. Create your server directory and spec.yaml +3. Submit a PR with: + - Clear title: "Add [Your Server Name] MCP server" + - Description of what your server does + - Link to the package registry and source repository + +## CI/CD Pipeline + +When you submit a PR, the following happens automatically: + +```mermaid +graph TD + A[Discover Configs] --> B[Verify Provenance] + B --> C[MCP Security Scan] + C --> D{Scan Passed?} + D -->|Yes| E[Build Containers] + D -->|No| F[Fail Build] + E --> G[Trivy Vulnerability Scan] + G --> H[Sign with Cosign] + H --> I[Create Attestations] + I --> J[Push to Registry] +``` + +### Security Scanning + +All MCP servers are scanned for security vulnerabilities using [mcp-scanner](https://github.com/cisco-ai-defense/mcp-scanner). The scan is **blocking** - your PR cannot merge if it fails. + +If your scan finds issues that are false positives or acceptable in your context, add them to the security allowlist: + +```yaml +security: + allowed_issues: + - code: "AITech-1.1" + reason: "Tool description contains imperative instructions necessary for proper operation" + - code: "AITech-9.1" + reason: "Destructive flow mitigated by container sandboxing" +``` + +See [Security Overview](security.md) for more details on what we scan for. + +### After Merge + +Once merged: +- Container published to `ghcr.io/stacklok/dockyard/{protocol}/{name}:{version}` +- Renovate automatically creates PRs for version updates +- Trivy scans run weekly to catch new CVEs + +## Local Development + +### Build dockhand CLI + +```bash +go build -o build/dockhand ./cmd/dockhand +``` + +### Generate Dockerfile + +```bash +# Generate to stdout +./build/dockhand build -c npx/context7/spec.yaml + +# Save to file +./build/dockhand build -c npx/context7/spec.yaml -o Dockerfile +``` + +### Build with Custom Tag + +```bash +./build/dockhand build -c npx/context7/spec.yaml -t my-custom-tag:latest +``` + +### CLI Flags + +| Flag | Description | +|------|-------------| +| `-c, --config` | YAML spec file (required) | +| `-o, --output` | Output file (default: stdout) | +| `-t, --tag` | Custom image tag | +| `-v, --verbose` | Verbose output | +| `--check-provenance` | Require provenance verification | +| `--warn-no-provenance` | Warn if no provenance (default: true) | + +## Troubleshooting + +| Issue | Solution | +|-------|----------| +| Package not found | Verify exact package name in registry | +| Build fails | Check Dockerfile syntax with `dockhand build -c spec.yaml` | +| Version error | Ensure version exists in package registry | +| Wrong protocol | Verify package type matches directory (uvx/npx/go) | +| Security scan fails | Review issues, allowlist false positives with explanation | + +## Key Rules + +1. **Always use exact versions** - no ranges or "latest" tags +2. **Test locally before committing** +3. **Include all metadata fields** +4. **Use correct protocol directory** (uvx/npx/go) +5. **Reference official package registries** in comments +6. **Verify provenance** when available + +## What's Next? + +- [Package Provenance](provenance.md) - Understanding provenance verification +- [Security Overview](security.md) - What we scan for and why +- [Container Attestations](attestations.md) - Build attestations and policy enforcement diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 0000000..69f5305 --- /dev/null +++ b/docs/getting-started.md @@ -0,0 +1,90 @@ +# Getting Started with Dockyard Containers + +This guide shows you how to pull, run, and verify MCP server containers from Dockyard. + +## Quick Start + +Pull and run an MCP server container: + +```bash +# Pull a container +docker pull ghcr.io/stacklok/dockyard/npx/context7:2.1.0 + +# Run it +docker run -it ghcr.io/stacklok/dockyard/npx/context7:2.1.0 +``` + +## Available Containers + +All containers follow this naming pattern: + +``` +ghcr.io/stacklok/dockyard/{protocol}/{name}:{version} +``` + +Where: +- `protocol` is `npx` (Node.js), `uvx` (Python), or `go` +- `name` is the server name +- `version` is the specific package version + +### Example Containers + +| Server | Image | Description | +|--------|-------|-------------| +| Context7 | `ghcr.io/stacklok/dockyard/npx/context7:2.1.0` | Upstash vector search | +| AWS Docs | `ghcr.io/stacklok/dockyard/uvx/aws-documentation-mcp-server:1.1.16` | AWS documentation server | +| ClickHouse | `ghcr.io/stacklok/dockyard/uvx/mcp-clickhouse:0.1.13` | ClickHouse database operations | + +Browse all available containers in the [npx/](https://github.com/stacklok/dockyard/tree/main/npx), [uvx/](https://github.com/stacklok/dockyard/tree/main/uvx), and [go/](https://github.com/stacklok/dockyard/tree/main/go) directories. + +## Verifying Container Signatures + +All Dockyard containers are signed with Sigstore/Cosign. Verify a container before running: + +```bash +# Install cosign +brew install cosign # or see https://docs.sigstore.dev/cosign/installation/ + +# Verify the signature +cosign verify \ + --certificate-identity-regexp "https://github.com/stacklok/dockyard/.github/workflows/build-containers.yml@refs/heads/.*" \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com \ + ghcr.io/stacklok/dockyard/npx/context7:2.1.0 +``` + +For detailed verification options including attestations, see [Container Attestations](attestations.md). + +## Using with ToolHive + +[ToolHive](https://docs.stacklok.com/toolhive) can run Dockyard containers directly: + +```bash +# Install ToolHive +brew install stacklok/tap/toolhive + +# Run an MCP server +thv run ghcr.io/stacklok/dockyard/npx/context7:2.1.0 +``` + +## Multi-Architecture Support + +All containers are built for both `linux/amd64` and `linux/arm64` architectures. Docker automatically pulls the correct architecture for your system. + +## Environment Variables + +MCP servers may require environment variables for API keys or configuration. Pass them when running: + +```bash +docker run -it \ + -e API_KEY=your-key \ + -e CONFIG_PATH=/app/config \ + ghcr.io/stacklok/dockyard/npx/your-server:version +``` + +Check the original MCP server's documentation for required environment variables. + +## What's Next? + +- [Security Overview](security.md) - Understand the security guarantees +- [Container Attestations](attestations.md) - Verify build provenance and security scans +- [Add Your Own Server](adding-servers.md) - Contribute an MCP server to Dockyard diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..1cbeba0 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,41 @@ +# Dockyard Documentation + +Welcome to the Dockyard documentation. This guide will help you find the information you need based on what you're trying to do. + +## Quick Links by Use Case + +### I want to use Dockyard containers + +You're a developer who wants to pull and run pre-built MCP server containers. + +- [Getting Started](getting-started.md) - Pull, run, and verify containers + +### I want to add my MCP server + +You're an MCP server author who wants to package and distribute your server via Dockyard. + +- [Adding MCP Servers](adding-servers.md) - Step-by-step contribution guide + +### I want to understand the security model + +You're evaluating Dockyard for security compliance or want to verify container integrity. + +- [Security Overview](security.md) - Security scanning, guarantees, and verification +- [Container Attestations](attestations.md) - SCAI attestation schema and policy enforcement +- [Package Provenance](provenance.md) - Supply chain verification for npm/PyPI packages + +## Documentation Overview + +| Document | Description | +|----------|-------------| +| [Getting Started](getting-started.md) | How to use Dockyard containers | +| [Adding MCP Servers](adding-servers.md) | Contributing your MCP server | +| [Security Overview](security.md) | Security model and scanning | +| [Attestations](attestations.md) | Container attestation details | +| [Provenance](provenance.md) | Package provenance verification | + +## Additional Resources + +- [Main Repository](https://github.com/stacklok/dockyard) - Source code and issues +- [ToolHive](https://docs.stacklok.com/toolhive) - Container building technology +- [MCP Documentation](https://modelcontextprotocol.io/) - Model Context Protocol specification diff --git a/docs/packaging.md b/docs/packaging.md deleted file mode 100644 index 1afc44f..0000000 --- a/docs/packaging.md +++ /dev/null @@ -1,239 +0,0 @@ -# Packaging MCP Servers for Dockyard - -Quick guide for packaging MCP servers as container images using the dockhand CLI. - -## Directory Structure - -``` -{protocol}/{server-name}/spec.yaml -``` - -Protocols: `uvx` (Python/PyPI), `npx` (Node.js/npm), `go` (Go modules) - -## spec.yaml Template - -```yaml -# {Server Name} MCP Server Configuration -# {Brief description} -# Package: {package-registry-url} -# Repository: {source-repository-url} -# Will build as: ghcr.io/stacklok/dockyard/{protocol}/{name}:{version} - -metadata: - name: {package-name} - description: "{one-line description}" - version: "{semantic-version}" - protocol: {uvx|npx|go} - -spec: - package: "{package-identifier}" # PyPI/npm name or Go module - version: "{exact-version}" - args: # Optional: CLI arguments for the package - - "{arg1}" # Passed to the entrypoint command - - "{arg2}" - -provenance: - repository_uri: "{github-url}" - repository_ref: "{git-ref}" # refs/heads/main or refs/tags/v1.0.0 - - # Attestation information (if available) - # Document package provenance for supply chain security - attestations: - available: true # Whether the package has provenance attestations - verified: true # Whether you've verified the attestations - publisher: - kind: "{GitHub|GitLab}" # Publisher type - repository: "{owner/repo}" # Publisher repository - workflow: "{workflow.yml}" # Publishing workflow (optional) - -# Optional: Security allowlist -security: - allowed_issues: - - code: "{code}" - reason: "{explanation}" -``` - -## Real Examples - -### Python (uvx) -```yaml -metadata: - name: mcp-clickhouse - description: "MCP server for ClickHouse database operations" - version: "0.1.11" - protocol: uvx - -spec: - package: "mcp-clickhouse" - version: "0.1.11" - -provenance: - repository_uri: "https://github.com/ClickHouse/mcp-clickhouse" - repository_ref: "refs/heads/main" -``` - -### Node.js (npx) -```yaml -metadata: - name: context7 - description: "MCP server for context management" - version: "1.0.0" - protocol: npx - -spec: - package: "@context7/mcp-server" - version: "1.0.0" - -provenance: - repository_uri: "https://github.com/context7/mcp-server" - repository_ref: "refs/tags/v1.0.0" -``` - -## Using dockhand CLI - -```bash -# Generate Dockerfile to stdout -dockhand build -c uvx/mcp-clickhouse/spec.yaml - -# Save Dockerfile -dockhand build -c uvx/mcp-clickhouse/spec.yaml -o Dockerfile - -# Custom tag -dockhand build -c uvx/mcp-clickhouse/spec.yaml -t myregistry/image:v1.0.0 -``` - -Flags: -- `-c, --config`: YAML spec file (required) -- `-o, --output`: Output file (default: stdout) -- `-t, --tag`: Custom image tag -- `-v, --verbose`: Verbose output - -## Adding a New MCP Server - -1. Find package info: -```bash -# Python -curl -s https://pypi.org/pypi/{package}/json | jq -r '.info.version' - -# Node.js -npm view {package} version -``` - -2. Create structure: -```bash -mkdir -p {protocol}/{server-name} -``` - -3. Create `spec.yaml` using template above - -4. Test: -```bash -# Validate spec and generate Dockerfile -task build -- {protocol}/{server-name} - -# Run security scan -task scan -- {protocol}/{server-name} - -# Optional: Build and test container image -task test-build -- {protocol}/{server-name} -``` - -5. Commit with descriptive message: -```bash -git add {protocol}/{server-name}/spec.yaml -git commit -m "feat: add {server-name} MCP server package - -Add packaging for {server-name} v{version}. -Package: {package-url} -Repository: {repo-url}" -``` - -## Key Rules - -1. **Always use exact versions** - no ranges or latest tags -2. **Test locally before committing** -3. **Include all metadata fields** -4. **Use correct protocol directory** (uvx/npx/go) -5. **Reference official package registries** in comments - -## CI/CD - -- Pushes to main trigger automatic builds -- Images published to `ghcr.io/stacklok/dockyard/{protocol}/{name}:{version}` -- Multi-architecture builds (amd64, arm64) -- Automated security scanning - -### Verifying CI Builds - -After pushing changes: -1. Check workflow runs: `https://github.com/stacklok/dockyard/actions` -2. Look for your package in the build jobs (e.g., `build-containers (uvx/mcp-clickhouse/spec.yaml)`) -3. Verify security scan passed: `mcp-security-scan (uvx/mcp-clickhouse/spec.yaml)` -4. Manual trigger if needed: Actions → Build MCP Server Containers → Run workflow - -Note: Only spec.yaml changes trigger automatic builds. Manual triggers build all packages. - -## Quick Debugging - -| Issue | Solution | -|-------|----------| -| Package not found | Verify exact package name in registry | -| Build fails | Check Dockerfile syntax with `dockhand build -c spec.yaml` | -| Version error | Ensure version exists in package registry | -| Wrong protocol | Verify package type matches directory (uvx/npx/go) | - -## Verifying Package Provenance - -Before adding a new MCP server, verify its provenance: - -```bash -# After creating the spec.yaml, verify the package -dockhand verify-provenance -c {protocol}/{server-name}/spec.yaml - -# With verbose output to see details -dockhand verify-provenance -c {protocol}/{server-name}/spec.yaml -v -``` - -### Understanding Provenance Status - -- **VERIFIED**: Package has attestations that were cryptographically verified -- **ATTESTATIONS**: Package has attestations (npm) or PEP 740 attestations (PyPI) -- **SIGNATURES**: Package has signatures (older npm format) -- **TRUSTED_PUBLISHER**: Package uses PyPI Trusted Publishers -- **NONE**: No provenance information available - -### Documenting Provenance in spec.yaml - -If provenance is available, document it in your spec.yaml: - -```yaml -provenance: - repository_uri: "https://github.com/owner/repo" - repository_ref: "refs/tags/v1.0.0" - - attestations: - available: true - verified: true - publisher: - kind: "GitHub" - repository: "owner/repo" - workflow: ".github/workflows/release.yml" -``` - -This helps future maintainers verify that attestations haven't been removed and establishes the expected publisher identity. - -### Provenance Best Practices - -1. **Always check provenance** before adding new packages -2. **Prefer packages with attestations** when multiple options exist -3. **Document attestation info** in spec.yaml for verification -4. **Re-verify** when updating package versions - -## Resources - -- [MCP Documentation](https://modelcontextprotocol.io/) -- [Dockyard Repository](https://github.com/stacklok/dockyard) -- [Example MCP Servers](https://github.com/modelcontextprotocol/servers) -- [npm Provenance](https://docs.npmjs.com/generating-provenance-statements) -- [PyPI Attestations (PEP 740)](https://peps.python.org/pep-0740/) -- [Sigstore Documentation](https://docs.sigstore.dev/) \ No newline at end of file diff --git a/docs/security.md b/docs/security.md new file mode 100644 index 0000000..9e2c6c4 --- /dev/null +++ b/docs/security.md @@ -0,0 +1,163 @@ +# Dockyard Security Overview + +Dockyard provides multiple layers of security to ensure safe distribution of MCP server containers. + +## Security Guarantees + +When you use a Dockyard container, you can be confident that: + +1. **Source Integrity** - The image was built from the exact source code in this repository +2. **Build Transparency** - Full build provenance is available and verifiable +3. **MCP Security Scanning** - The MCP server was scanned for vulnerabilities before packaging +4. **Container Vulnerability Scanning** - Images are scanned with Trivy for CVEs, secrets, and misconfigurations +5. **Dependency Tracking** - Complete SBOM is available for vulnerability management +6. **Non-repudiation** - Signatures prove the image came from our CI/CD pipeline +7. **Continuous Monitoring** - Weekly scans catch newly disclosed vulnerabilities + +## MCP Security Scanning + +All MCP servers are scanned using [Cisco AI Defense mcp-scanner](https://github.com/cisco-ai-defense/mcp-scanner) before building containers. This scan is **blocking** - servers that fail cannot be packaged. + +### What We Scan For + +| Category | Description | +|----------|-------------| +| **Prompt Injection** | Dangerous patterns in tool descriptions that could be exploited | +| **Toxic Flows** | Tool combinations that could lead to destructive behaviors | +| **Tool Poisoning** | Malicious tool implementations | +| **Cross-Origin Escalation** | Potential privilege escalation vulnerabilities | +| **Rug Pull Attacks** | Suspicious patterns indicating malicious intent | + +### Scan Results + +When vulnerabilities are found in a PR, you'll see a detailed report: + +``` +## MCP Security Scan Results + +### your-mcp-server +- **Status**: Failed +- **Tools scanned**: 3 +- **Vulnerabilities found**: 2 + +**Security issues detected:** +- **[W001]** Tool description contains dangerous words +- **[TF002]** Destructive toxic flow detected +``` + +### Allowing Known Issues + +Some warnings may be false positives for containerized deployments. Add them to the allowlist in your spec.yaml: + +```yaml +security: + allowed_issues: + - code: "AITech-1.1" + reason: "Imperative instructions required for proper AI agent operation" + - code: "AITech-9.1" + reason: "Destructive flow mitigated by container sandboxing" +``` + +Each allowed issue must include: +- `code` - The issue code from mcp-scanner +- `reason` - Clear explanation of why it's acceptable + +## Container Vulnerability Scanning + +Built containers are scanned with [Trivy](https://trivy.dev/) for: + +| Category | Description | +|----------|-------------| +| **Vulnerabilities** | CVEs in OS packages and dependencies (CRITICAL, HIGH, MEDIUM) | +| **Secrets** | Exposed API keys, tokens, credentials | +| **Misconfigurations** | Security issues in container configuration | + +### Scan Schedule + +- **Every PR** - Immediate feedback on new/changed containers +- **On main branch** - Scans all published images after build +- **Weekly (Monday 2am UTC)** - Comprehensive scans to catch new CVEs +- **Manual trigger** - On-demand via GitHub Actions + +### Viewing Results + +Trivy results are uploaded to the GitHub Security tab: + +``` +https://github.com/stacklok/dockyard/security/code-scanning +``` + +Filter by `trivy-{server-name}` to see specific results. + +## Container Signing + +All images are signed with [Sigstore/Cosign](https://docs.sigstore.dev/cosign/) using keyless OIDC via GitHub Actions. + +### Verify Image Signature + +```bash +cosign verify \ + --certificate-identity-regexp "https://github.com/stacklok/dockyard/.github/workflows/build-containers.yml@refs/heads/.*" \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com \ + ghcr.io/stacklok/dockyard/npx/context7:2.1.0 +``` + +## Container Attestations + +Each image includes multiple attestations: + +| Type | Format | Description | +|------|--------|-------------| +| SBOM | SPDX | Software Bill of Materials | +| Build Provenance | SLSA | Build integrity attestation | +| MCP Security Scan | SCAI v0.3 | Security scan results | +| Signature | Sigstore | Keyless OIDC signature | + +### View Attestations + +```bash +# View SBOM +docker buildx imagetools inspect \ + ghcr.io/stacklok/dockyard/npx/context7:2.1.0 \ + --format "{{ json .SBOM }}" + +# View Provenance +docker buildx imagetools inspect \ + ghcr.io/stacklok/dockyard/npx/context7:2.1.0 \ + --format "{{ json .Provenance }}" + +# View Security Scan Attestation +cosign verify-attestation \ + --type https://in-toto.io/attestation/scai/v0.3 \ + --certificate-identity-regexp "https://github.com/stacklok/dockyard/.github/workflows/build-containers.yml@refs/heads/.*" \ + --certificate-oidc-issuer https://token.actions.githubusercontent.com \ + ghcr.io/stacklok/dockyard/npx/context7:2.1.0 +``` + +For detailed attestation schemas and policy examples, see [Container Attestations](attestations.md). + +## Package Provenance + +Dockyard verifies package provenance for npm and PyPI packages before building: + +- **npm** - Checks for signatures and modern Sigstore attestations +- **PyPI** - Verifies PEP 740 attestations and Trusted Publishers + +For details on provenance verification, see [Package Provenance](provenance.md). + +## Policy Enforcement + +SCAI attestations integrate with policy engines for Kubernetes: + +- **Kyverno** - Verify attestations before pod deployment +- **OPA/Gatekeeper** - Custom policies based on scan results + +Example policies are provided in [Container Attestations](attestations.md). + +## Reporting Security Issues + +If you discover a security vulnerability: + +1. **Do NOT** disclose publicly until we've had a chance to fix it +2. **Do NOT** use GitHub issues for security reports +3. Follow the process in [SECURITY.MD](../SECURITY.MD)