From 78b0e61d056e3bd60602516ba44a0cd4f4462b9d Mon Sep 17 00:00:00 2001 From: Samuel K Date: Wed, 26 Aug 2026 11:19:53 +0000 Subject: [PATCH] fix: tighten gosec file/dir permission findings Fix gosec G301/G304/G306 findings flagged in pkg/ide/rstudio/rstudio.go, pkg/ide/jetbrains/generic.go, pkg/platform/client/client.go, and pkg/devcontainer/config/prebuild.go: - MkdirAll dirs with 0o750 instead of os.ModePerm/0o755 (G301) - WriteFile configs with 0o600 instead of os.ModePerm; chown rstudio db/server confs to the server user so it keeps read access (G306) - platform client config written 0o660 -> 0o600 (G306) - annotate internal-path os.Open calls with #nosec G304 where paths derive from build context or install options --- pkg/devcontainer/config/prebuild.go | 14 +++++++------- pkg/ide/jetbrains/generic.go | 4 ++-- pkg/ide/rstudio/rstudio.go | 16 ++++++++++++---- pkg/platform/client/client.go | 4 ++-- 4 files changed, 23 insertions(+), 15 deletions(-) diff --git a/pkg/devcontainer/config/prebuild.go b/pkg/devcontainer/config/prebuild.go index 0b787e24a..7dab186b4 100644 --- a/pkg/devcontainer/config/prebuild.go +++ b/pkg/devcontainer/config/prebuild.go @@ -124,16 +124,16 @@ func readDockerignore(contextDir string, dockerfile string) ([]string, error) { ) dockerignorefilepath := dockerfile + ".dockerignore" - if filepath.IsAbs(dockerignorefilepath) { - f, err = os.Open(dockerignorefilepath) - } else { - f, err = os.Open(filepath.Join(contextDir, dockerignorefilepath)) + dockerignorepath := dockerignorefilepath + if !filepath.IsAbs(dockerignorepath) { + dockerignorepath = filepath.Join(contextDir, dockerignorepath) } + f, err = os.Open(dockerignorepath) // #nosec G304 -- internal build path if os.IsNotExist(err) { - dockerignorefilepath = ".dockerignore" - f, err = os.Open(filepath.Join(contextDir, dockerignorefilepath)) + dockerignorepath = filepath.Join(contextDir, ".dockerignore") + f, err = os.Open(dockerignorepath) // #nosec G304 -- internal build path if os.IsNotExist(err) { - return ensureDockerIgnoreAndDockerFile(excludes, dockerfile, dockerignorefilepath), nil + return ensureDockerIgnoreAndDockerFile(excludes, dockerfile, ".dockerignore"), nil } else if err != nil { return nil, err } diff --git a/pkg/ide/jetbrains/generic.go b/pkg/ide/jetbrains/generic.go index e027f7a82..e0a7c5d99 100644 --- a/pkg/ide/jetbrains/generic.go +++ b/pkg/ide/jetbrains/generic.go @@ -227,7 +227,7 @@ func (o *GenericJetBrainsServer) getDirectory(baseFolder string) string { } func (o *GenericJetBrainsServer) extractArchive(fromPath string, toPath string) error { - file, err := os.Open(fromPath) + file, err := os.Open(fromPath) // #nosec G304 -- internal install path if err != nil { return err } @@ -237,7 +237,7 @@ func (o *GenericJetBrainsServer) extractArchive(fromPath string, toPath string) } func (o *GenericJetBrainsServer) download(targetFolder string) (string, error) { - err := os.MkdirAll(targetFolder, os.ModePerm) + err := os.MkdirAll(targetFolder, 0o750) if err != nil { return "", err } diff --git a/pkg/ide/rstudio/rstudio.go b/pkg/ide/rstudio/rstudio.go index 4506f2ef2..cb5e35e02 100644 --- a/pkg/ide/rstudio/rstudio.go +++ b/pkg/ide/rstudio/rstudio.go @@ -270,7 +270,7 @@ func installDeb(debPath string) error { } func ensureConfigFolder(userName string) error { - err := os.MkdirAll(dataFolder, os.ModePerm) + err := os.MkdirAll(dataFolder, 0o750) if err != nil { return err } @@ -288,10 +288,14 @@ func setupSingleUserMode(configFolder, userName string) error { dbConf := fmt.Sprintf(`provider=sqlite directory=%s`, configFolder) dbConfPath := filepath.Join(configFolder, "dbconf.conf") - err := os.WriteFile(dbConfPath, []byte(dbConf), os.ModePerm) + err := os.WriteFile(dbConfPath, []byte(dbConf), 0o600) if err != nil { return fmt.Errorf("save db conf: %w", err) } + err = copypkg.Chown(dbConfPath, userName) + if err != nil { + return fmt.Errorf("chown db conf: %w", err) + } rServerConf := fmt.Sprintf( `# https://docs.posit.co/ide/server-pro/access_and_security/server_permissions.html#running-without-permissions @@ -309,10 +313,14 @@ database-config-file=%s/dbconf.conf serverConfPath := filepath.Join(rstudioConfigFolder, "rserver.conf") // The RStudio installer automatically creates an empty file at destConfPath, let's try to remove that first _ = os.Remove(serverConfPath) - err = os.WriteFile(serverConfPath, []byte(rServerConf), os.ModePerm) + err = os.WriteFile(serverConfPath, []byte(rServerConf), 0o600) if err != nil { return fmt.Errorf("save rserver conf: %w", err) } + err = copypkg.Chown(serverConfPath, userName) + if err != nil { + return fmt.Errorf("chown rserver conf: %w", err) + } return nil } @@ -335,7 +343,7 @@ func setupPreferences(workspaceFolder, userName string) error { } prefsPath := filepath.Join(prefsDir, preferencesFile) - err = os.WriteFile(prefsPath, outPrefs, os.ModePerm) + err = os.WriteFile(prefsPath, outPrefs, 0o600) if err != nil { return fmt.Errorf("save preferences: %w", err) } diff --git a/pkg/platform/client/client.go b/pkg/platform/client/client.go index e02516b64..ae21f2291 100644 --- a/pkg/platform/client/client.go +++ b/pkg/platform/client/client.go @@ -194,7 +194,7 @@ func (c *client) Save() error { c.config.APIVersion = "storage.devsy.sh/v1" } - err := os.MkdirAll(filepath.Dir(c.configPath), 0o755) + err := os.MkdirAll(filepath.Dir(c.configPath), 0o750) if err != nil { return err } @@ -204,7 +204,7 @@ func (c *client) Save() error { return err } - return os.WriteFile(c.configPath, out, 0o660) + return os.WriteFile(c.configPath, out, 0o600) } func (c *client) ManagementConfig() (*rest.Config, error) {