66 "encoding/hex"
77 "fmt"
88 "os"
9+ "regexp"
910 "sort"
1011
1112 "go.uber.org/multierr"
@@ -23,9 +24,14 @@ import (
2324)
2425
2526const (
26- defaultTransportAdapterContainerImage = "ghcr.io/agentgateway/agentgateway:0.9.0-musl"
27+ transportAdapterRepository = "ghcr.io/agentgateway/agentgateway"
28+ defaultTransportAdapterVersion = "0.9.0"
2729)
2830
31+ // versionRegex validates that version strings contain only allowed characters
32+ // (alphanumeric, dots, hyphens) to prevent potential image injection attacks
33+ var versionRegex = regexp .MustCompile (`^[a-zA-Z0-9.\-]+$` )
34+
2935// Translator is the interface for translating MCPServer objects to TransportAdapter objects.
3036type Translator interface {
3137 TranslateTransportAdapterOutputs (
@@ -103,10 +109,19 @@ func (t *transportAdapterTranslator) translateTransportAdapterDeployment(
103109 // Create volume mounts from the MCPServer spec
104110 volumeMounts := t .createVolumeMounts (server .Spec .Deployment )
105111
106- transportAdapterContainerImage := defaultTransportAdapterContainerImage
107- transportAdapterVersion := os .Getenv ("TRANSPORT_ADAPTER_VERSION" )
108- if transportAdapterVersion != "" {
109- transportAdapterContainerImage = fmt .Sprintf ("ghcr.io/agentgateway/agentgateway:%s-musl" , transportAdapterVersion )
112+ // Determine the init container image and pull policy to use
113+ // Start with the default transport adapter image
114+ transportAdapterContainerImage := getTransportAdapterImage ()
115+
116+ initContainerPullPolicy := corev1 .PullIfNotPresent
117+
118+ // Override with custom image if specified in the MCPServer spec
119+ if server .Spec .Deployment .InitContainer != nil && server .Spec .Deployment .InitContainer .Image != "" {
120+ transportAdapterContainerImage = server .Spec .Deployment .InitContainer .Image
121+ initContainerPullPolicy = server .Spec .Deployment .InitContainer .ImagePullPolicy
122+ if initContainerPullPolicy == "" {
123+ initContainerPullPolicy = corev1 .PullIfNotPresent
124+ }
110125 }
111126
112127 var template corev1.PodSpec
@@ -118,7 +133,7 @@ func (t *transportAdapterTranslator) translateTransportAdapterDeployment(
118133 InitContainers : []corev1.Container {{
119134 Name : "copy-binary" ,
120135 Image : transportAdapterContainerImage ,
121- ImagePullPolicy : corev1 . PullIfNotPresent ,
136+ ImagePullPolicy : initContainerPullPolicy ,
122137 Command : []string {},
123138 Args : []string {
124139 "--copy-self" ,
@@ -544,3 +559,28 @@ func (t *transportAdapterTranslator) runPlugins(
544559
545560 return objects , errs
546561}
562+
563+ // validateVersion validates that a version string contains only allowed characters
564+ // to prevent potential image injection attacks
565+ func validateVersion (version string ) error {
566+ if ! versionRegex .MatchString (version ) {
567+ return fmt .Errorf ("invalid version format: %s (only alphanumeric characters, dots, and hyphens are allowed)" , version )
568+ }
569+ return nil
570+ }
571+
572+ // getTransportAdapterImage returns the transport adapter container image,
573+ // using the environment variable if provided and valid, otherwise using the default
574+ func getTransportAdapterImage () string {
575+ transportAdapterVersion := os .Getenv ("TRANSPORT_ADAPTER_VERSION" )
576+ if transportAdapterVersion == "" {
577+ return fmt .Sprintf ("%s:%s-musl" , transportAdapterRepository , defaultTransportAdapterVersion )
578+ }
579+
580+ if err := validateVersion (transportAdapterVersion ); err != nil {
581+ klog .Warningf ("Invalid TRANSPORT_ADAPTER_VERSION: %v, fallback to %s" , err , defaultTransportAdapterVersion )
582+ return fmt .Sprintf ("%s:%s-musl" , transportAdapterRepository , defaultTransportAdapterVersion )
583+ }
584+
585+ return fmt .Sprintf ("%s:%s-musl" , transportAdapterRepository , transportAdapterVersion )
586+ }
0 commit comments