Skip to content

Commit 7196ef4

Browse files
Copilotlpcox
andauthored
Allow SHA-256 digests in container image references
Update containerPattern regex and JSON schema to accept optional @sha256:<64-hex-chars> suffix on container image references. This enables digest-pinned references like: - image:tag@sha256:abc123... - image@sha256:abc123... Add test cases for valid and invalid digest patterns. Agent-Logs-Url: https://github.com/github/gh-aw-mcpg/sessions/a36ac9ee-c2c2-4156-83d6-c836034383c3 Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
1 parent f189598 commit 7196ef4

4 files changed

Lines changed: 53 additions & 2 deletions

File tree

internal/config/schema/mcp-gateway-config.schema.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
"type": "string",
7777
"description": "Container image for the MCP server (e.g., 'ghcr.io/example/mcp-server:latest'). This field is required for stdio servers per MCP Gateway Specification section 4.1.2.",
7878
"minLength": 1,
79-
"pattern": "^[a-zA-Z0-9][a-zA-Z0-9./_-]*(:([a-zA-Z0-9._-]+|latest))?$"
79+
"pattern": "^[a-zA-Z0-9][a-zA-Z0-9./_-]*(:([a-zA-Z0-9._-]+|latest))?(@sha256:[a-fA-F0-9]{64})?$"
8080
},
8181
"entrypoint": {
8282
"type": "string",

internal/config/validation_schema.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func isTransientHTTPError(statusCode int) bool {
5959

6060
var (
6161
// Compile regex patterns from schema for additional validation
62-
containerPattern = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9./_-]*(:([a-zA-Z0-9._-]+|latest))?$`)
62+
containerPattern = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9./_-]*(:([a-zA-Z0-9._-]+|latest))?(@sha256:[a-fA-F0-9]{64})?$`)
6363
urlPattern = regexp.MustCompile(`^https?://.+`)
6464
mountPattern = regexp.MustCompile(`^[^:]+:[^:]+:(ro|rw)$`)
6565
domainVarPattern = regexp.MustCompile(`^\$\{[A-Z_][A-Z0-9_]*\}$`)

internal/config/validation_schema_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,30 @@ func TestValidateStringPatterns(t *testing.T) {
365365
},
366366
shouldErr: false,
367367
},
368+
{
369+
name: "valid container pattern - tag with sha256 digest",
370+
config: &StdinConfig{
371+
MCPServers: map[string]*StdinServerConfig{
372+
"test": {
373+
Type: "stdio",
374+
Container: "ghcr.io/owner/image:v1.2.3@sha256:2763823c67a0adca3fce6e3bdfee41a674e3bf22f0e6b2eee94ed3a72ebcd519",
375+
},
376+
},
377+
},
378+
shouldErr: false,
379+
},
380+
{
381+
name: "valid container pattern - sha256 digest only",
382+
config: &StdinConfig{
383+
MCPServers: map[string]*StdinServerConfig{
384+
"test": {
385+
Type: "stdio",
386+
Container: "ghcr.io/owner/image@sha256:2763823c67a0adca3fce6e3bdfee41a674e3bf22f0e6b2eee94ed3a72ebcd519",
387+
},
388+
},
389+
},
390+
shouldErr: false,
391+
},
368392
{
369393
name: "invalid container pattern - starts with special char",
370394
config: &StdinConfig{

internal/config/validation_string_patterns_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,19 @@ func TestValidateStringPatternsComprehensive(t *testing.T) {
6464
serverType: "",
6565
shouldError: false,
6666
},
67+
// Valid container patterns with SHA-256 digest
68+
{
69+
name: "valid container with tag and sha256 digest",
70+
container: "ghcr.io/github/github-mcp-server:v0.32.0@sha256:2763823c67a0adca3fce6e3bdfee41a674e3bf22f0e6b2eee94ed3a72ebcd519",
71+
serverType: "stdio",
72+
shouldError: false,
73+
},
74+
{
75+
name: "valid container with sha256 digest only",
76+
container: "ghcr.io/github/github-mcp-server@sha256:2763823c67a0adca3fce6e3bdfee41a674e3bf22f0e6b2eee94ed3a72ebcd519",
77+
serverType: "stdio",
78+
shouldError: false,
79+
},
6780
// Invalid container patterns
6881
{
6982
name: "invalid container starts with special char",
@@ -86,6 +99,20 @@ func TestValidateStringPatternsComprehensive(t *testing.T) {
8699
shouldError: true,
87100
errorField: "container",
88101
},
102+
{
103+
name: "invalid container sha256 digest too short",
104+
container: "ghcr.io/github/github-mcp-server@sha256:short",
105+
serverType: "stdio",
106+
shouldError: true,
107+
errorField: "container",
108+
},
109+
{
110+
name: "invalid container wrong digest algorithm",
111+
container: "ghcr.io/github/github-mcp-server@md5:2763823c67a0adca3fce6e3bdfee41a674e3bf22f0e6b2eee94ed3a72ebcd519",
112+
serverType: "stdio",
113+
shouldError: true,
114+
errorField: "container",
115+
},
89116
{
90117
name: "invalid container empty string accepted (empty is valid)",
91118
container: "",

0 commit comments

Comments
 (0)