@@ -67,16 +67,22 @@ func Node1BeforeSuite(ctx context.Context, e2eCtx *E2EContext) []byte {
6767
6868 templates := []clusterctl.Files {}
6969
70+ // Open the templates directory as an os.Root to ensure that writes
71+ // cannot escape this directory, even via symlink manipulation.
72+ templatesDirRoot , err := os .OpenRoot (templatesDir )
73+ Expect (err ).NotTo (HaveOccurred ())
74+ defer templatesDirRoot .Close ()
75+
7076 // Cluster templates in this folder will get ci artifacts injected. It makes it possible to use generic cloud images
7177 // without kubernetes pre-installed.
72- err : = filepath .WalkDir (path .Join (e2eCtx .Settings .DataFolder , "infrastructure-openstack" ), func (f string , d fs.DirEntry , _ error ) error {
78+ err = filepath .WalkDir (path .Join (e2eCtx .Settings .DataFolder , "infrastructure-openstack" ), func (f string , d fs.DirEntry , _ error ) error {
7379 filename := filepath .Base (f )
7480 fileExtension := filepath .Ext (filename )
7581 if d .IsDir () || ! strings .HasPrefix (filename , "cluster-template" ) {
7682 return nil
7783 }
7884
79- sourceTemplate , err := os .ReadFile (f )
85+ sourceTemplate , err := os .ReadFile (f ) //nolint:gosec // G122: This is test code, symlink TOCTOU is not a concern
8086 Expect (err ).NotTo (HaveOccurred ())
8187
8288 platformKustomization , err := os .ReadFile (filepath .Join (e2eCtx .Settings .DataFolder , "ci-artifacts-platform-kustomization.yaml" ))
@@ -92,17 +98,16 @@ func Node1BeforeSuite(ctx context.Context, e2eCtx *E2EContext) []byte {
9298 Expect (err ).NotTo (HaveOccurred ())
9399
94100 targetName := fmt .Sprintf ("%s-ci-artifacts.yaml" , strings .TrimSuffix (filename , fileExtension ))
95- targetTemplate := path .Join (templatesDir , targetName )
96101
97102 // We have to copy the file from ciTemplate to targetTemplate. Otherwise it would be overwritten because
98103 // ciTemplate is the same for all templates
99104 ciTemplateBytes , err := os .ReadFile (ciTemplate )
100105 Expect (err ).NotTo (HaveOccurred ())
101- err = os .WriteFile (targetTemplate , ciTemplateBytes , 0o600 )
106+ err = templatesDirRoot .WriteFile (targetName , ciTemplateBytes , 0o600 )
102107 Expect (err ).NotTo (HaveOccurred ())
103108
104109 clusterctlCITemplate := clusterctl.Files {
105- SourcePath : targetTemplate ,
110+ SourcePath : path . Join ( templatesDir , targetName ) ,
106111 TargetName : targetName ,
107112 }
108113
@@ -119,16 +124,14 @@ func Node1BeforeSuite(ctx context.Context, e2eCtx *E2EContext) []byte {
119124 return nil
120125 }
121126
122- t , err := os .ReadFile (f )
127+ t , err := os .ReadFile (f ) //nolint:gosec // G122: This is test code, symlink TOCTOU is not a concern
123128 Expect (err ).NotTo (HaveOccurred ())
124129
125- targetTemplate := path .Join (templatesDir , filename )
126-
127- err = os .WriteFile (targetTemplate , t , 0o600 )
130+ err = templatesDirRoot .WriteFile (filename , t , 0o600 )
128131 Expect (err ).NotTo (HaveOccurred ())
129132
130133 clusterctlTemplate := clusterctl.Files {
131- SourcePath : targetTemplate ,
134+ SourcePath : path . Join ( templatesDir , filename ) ,
132135 TargetName : filename ,
133136 }
134137
0 commit comments