diff --git a/pkg/api/avatar/avatar.go b/pkg/api/avatar/avatar.go index 9eb99db8b3b..95b6cea3efc 100644 --- a/pkg/api/avatar/avatar.go +++ b/pkg/api/avatar/avatar.go @@ -132,6 +132,9 @@ func newNotFound() *Avatar { avatar := &Avatar{notFound: true} // load user_profile png into buffer + // It's safe to ignore gosec warning G304 since the variable part of the file path comes from a configuration + // variable. + // nolint:gosec path := filepath.Join(setting.StaticRootPath, "img", "user_profile.png") if data, err := ioutil.ReadFile(path); err != nil { diff --git a/pkg/api/dashboard.go b/pkg/api/dashboard.go index d4643773409..51d38bb0a77 100644 --- a/pkg/api/dashboard.go +++ b/pkg/api/dashboard.go @@ -341,6 +341,9 @@ func (hs *HTTPServer) GetHomeDashboard(c *models.ReqContext) Response { filePath = filepath.Join(hs.Cfg.StaticRootPath, "dashboards/home.json") } + // It's safe to ignore gosec warning G304 since the variable part of the file path comes from a configuration + // variable + // nolint:gosec file, err := os.Open(filePath) if err != nil { return Error(500, "Failed to load home dashboard", err) diff --git a/pkg/cmd/grafana-cli/commands/install_command.go b/pkg/cmd/grafana-cli/commands/install_command.go index 558ca9b3da4..311b686165e 100644 --- a/pkg/cmd/grafana-cli/commands/install_command.go +++ b/pkg/cmd/grafana-cli/commands/install_command.go @@ -291,6 +291,10 @@ func extractFile(file *zip.File, filePath string) (err error) { fileMode = os.FileMode(0755) } + // We can ignore the gosec G304 warning on this one, since the variable part of the file path stems + // from command line flag "pluginsDir", and the only possible damage would be writing to the wrong directory. + // If the user shouldn't be writing to this directory, they shouldn't have the permission in the file system. + // nolint:gosec dst, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, fileMode) if err != nil { if os.IsPermission(err) { diff --git a/pkg/cmd/grafana-cli/services/api_client.go b/pkg/cmd/grafana-cli/services/api_client.go index 2aa40a2a2de..1ac8cbf6458 100644 --- a/pkg/cmd/grafana-cli/services/api_client.go +++ b/pkg/cmd/grafana-cli/services/api_client.go @@ -44,8 +44,11 @@ func (client *GrafanaComClient) GetPlugin(pluginId, repoUrl string) (models.Plug } func (client *GrafanaComClient) DownloadFile(pluginName string, tmpFile *os.File, url string, checksum string) (err error) { - // Try handling url like local file path first + // Try handling URL as a local file path first if _, err := os.Stat(url); err == nil { + // We can ignore this gosec G304 warning since `url` stems from command line flag "pluginUrl". If the + // user shouldn't be able to read the file, it should be handled through filesystem permissions. + // nolint:gosec f, err := os.Open(url) if err != nil { return errutil.Wrap("Failed to read plugin archive", err) diff --git a/pkg/cmd/grafana-cli/services/io_util.go b/pkg/cmd/grafana-cli/services/io_util.go index b1f1c140e2c..38aa81d94f7 100644 --- a/pkg/cmd/grafana-cli/services/io_util.go +++ b/pkg/cmd/grafana-cli/services/io_util.go @@ -21,5 +21,9 @@ func (i IoUtilImp) ReadDir(path string) ([]os.FileInfo, error) { } func (i IoUtilImp) ReadFile(filename string) ([]byte, error) { + // We can ignore the gosec G304 warning on this one, since the variable part of the file path stems + // from command line flag "pluginsDir". If the user shouldn't be reading from this directory, they shouldn't have + // the permission in the file system. + // nolint:gosec return ioutil.ReadFile(filename) } diff --git a/pkg/cmd/grafana-cli/utils/grafana_path.go b/pkg/cmd/grafana-cli/utils/grafana_path.go index aba5e1b8d48..51f953d26cd 100644 --- a/pkg/cmd/grafana-cli/utils/grafana_path.go +++ b/pkg/cmd/grafana-cli/utils/grafana_path.go @@ -16,8 +16,8 @@ func GetGrafanaPluginDir(currentOS string) string { return returnOsDefault(currentOS) } -// getGrafanaRoot tries to get root of directory when developing grafana ie repo root. It is not perfect it just -// checks what is the binary path and tries to guess based on that but if it is not running in dev env you get a bogus +// getGrafanaRoot tries to get root of directory when developing grafana, ie. repo root. It is not perfect, it just +// checks what is the binary path and tries to guess based on that, but if it is not running in dev env you get a bogus // path back. func getGrafanaRoot() (string, error) { ex, err := os.Executable() diff --git a/pkg/components/imguploader/azureblobuploader.go b/pkg/components/imguploader/azureblobuploader.go index 160e2b5119a..80023b8c30c 100644 --- a/pkg/components/imguploader/azureblobuploader.go +++ b/pkg/components/imguploader/azureblobuploader.go @@ -45,6 +45,9 @@ func (az *AzureBlobUploader) Upload(ctx context.Context, imageDiskPath string) ( // setup client blob := NewStorageClient(az.account_name, az.account_key) + // We can ignore the gosec G304 warning on this one because `imageDiskPath` comes + // from alert notifiers and is only used to upload images generated by alerting. + // nolint:gosec file, err := os.Open(imageDiskPath) if err != nil { return "", err diff --git a/pkg/components/imguploader/gcs/gcsuploader.go b/pkg/components/imguploader/gcs/gcsuploader.go index e869623cb45..391e5b78ece 100644 --- a/pkg/components/imguploader/gcs/gcsuploader.go +++ b/pkg/components/imguploader/gcs/gcsuploader.go @@ -149,6 +149,10 @@ func (u *Uploader) uploadFile( key string, ) error { u.log.Debug("Opening image file", "path", imageDiskPath) + + // We can ignore the gosec G304 warning on this one because `imageDiskPath` comes + // from alert notifiers and is only used to upload images generated by alerting. + // nolint:gosec fileReader, err := os.Open(imageDiskPath) if err != nil { return err diff --git a/pkg/components/imguploader/s3uploader.go b/pkg/components/imguploader/s3uploader.go index 59ee5a11098..d0b8b251740 100644 --- a/pkg/components/imguploader/s3uploader.go +++ b/pkg/components/imguploader/s3uploader.go @@ -76,6 +76,9 @@ func (u *S3Uploader) Upload(ctx context.Context, imageDiskPath string) (string, key := u.path + rand + pngExt log.Debugf("Uploading image to s3. bucket = %s, path = %s", u.bucket, key) + // We can ignore the gosec G304 warning on this one because `imageDiskPath` comes + // from alert notifiers and is only used to upload images generated by alerting. + // nolint:gosec file, err := os.Open(imageDiskPath) if err != nil { return "", err diff --git a/pkg/components/imguploader/webdavuploader.go b/pkg/components/imguploader/webdavuploader.go index f0a157a8291..3fd9894a8cf 100644 --- a/pkg/components/imguploader/webdavuploader.go +++ b/pkg/components/imguploader/webdavuploader.go @@ -45,7 +45,7 @@ func (u *WebdavUploader) PublicURL(filename string) string { return publicURL.String() } -func (u *WebdavUploader) Upload(ctx context.Context, pa string) (string, error) { +func (u *WebdavUploader) Upload(ctx context.Context, imgToUpload string) (string, error) { url, _ := url.Parse(u.url) filename, err := util.GetRandomString(20) if err != nil { @@ -55,7 +55,10 @@ func (u *WebdavUploader) Upload(ctx context.Context, pa string) (string, error) filename += pngExt url.Path = path.Join(url.Path, filename) - imgData, err := ioutil.ReadFile(pa) + // We can ignore the gosec G304 warning on this one because `imgToUpload` comes + // from alert notifiers and is only used to upload images generated by alerting. + // nolint:gosec + imgData, err := ioutil.ReadFile(imgToUpload) if err != nil { return "", err } diff --git a/pkg/middleware/recovery.go b/pkg/middleware/recovery.go index c238ecbfeee..8048cc6f53b 100644 --- a/pkg/middleware/recovery.go +++ b/pkg/middleware/recovery.go @@ -52,6 +52,9 @@ func stack(skip int) []byte { // Print this much at least. If we can't find the source, it won't show. fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc) if file != lastFile { + // We can ignore the gosec G304 warning on this one because `file` + // comes from the runtime.Caller() function. + // nolint:gosec data, err := ioutil.ReadFile(file) if err != nil { continue diff --git a/pkg/plugins/dashboards.go b/pkg/plugins/dashboards.go index f2d533b1de1..6cd9f827449 100644 --- a/pkg/plugins/dashboards.go +++ b/pkg/plugins/dashboards.go @@ -95,6 +95,10 @@ func loadPluginDashboard(pluginId, path string) (*models.Dashboard, error) { return nil, PluginNotFoundError{pluginId} } + // nolint:gosec + // We can ignore the gosec G304 warning on this one because `plugin.PluginDir` is based + // on plugin folder structure on disk and not user input. `path` comes from the + // `plugin.json` configuration file for the loaded plugin dashboardFilePath := filepath.Join(plugin.PluginDir, path) reader, err := os.Open(dashboardFilePath) if err != nil { diff --git a/pkg/plugins/manifest.go b/pkg/plugins/manifest.go index b082dedf2d2..4eaf721bad6 100644 --- a/pkg/plugins/manifest.go +++ b/pkg/plugins/manifest.go @@ -87,6 +87,9 @@ func getPluginSignatureState(log log.Logger, plugin *PluginBase) PluginSignature log.Debug("Getting signature state of plugin", "plugin", plugin.Id, "isBackend", plugin.Backend) manifestPath := filepath.Join(plugin.PluginDir, "MANIFEST.txt") + // nolint:gosec + // We can ignore the gosec G304 warning on this one because `manifestPath` is based + // on plugin the folder structure on disk and not user input. byteValue, err := ioutil.ReadFile(manifestPath) if err != nil || len(byteValue) < 10 { log.Debug("Plugin is unsigned", "id", plugin.Id) @@ -109,6 +112,10 @@ func getPluginSignatureState(log log.Logger, plugin *PluginBase) PluginSignature for p, hash := range manifest.Files { // Open the file fp := filepath.Join(plugin.PluginDir, p) + + // nolint:gosec + // We can ignore the gosec G304 warning on this one because `fp` is based + // on the manifest file for a plugin and not user input. f, err := os.Open(fp) if err != nil { return PluginSignatureModified diff --git a/pkg/plugins/plugins.go b/pkg/plugins/plugins.go index 77a73f71a3f..754a5eab16e 100644 --- a/pkg/plugins/plugins.go +++ b/pkg/plugins/plugins.go @@ -269,6 +269,9 @@ func (pm *PluginManager) scan(pluginDir string, requireSigned bool) error { } } + // nolint:gosec + // We can ignore the gosec G304 warning on this one because `jsonFPath` is based + // on plugin the folder structure on disk and not user input. reader, err := os.Open(jsonFPath) if err != nil { return err @@ -332,6 +335,9 @@ func (s *PluginScanner) walker(currentPath string, f os.FileInfo, err error) err return nil } + // nolint:gosec + // We can ignore the gosec G304 warning on this one because `currentPath` is based + // on plugin the folder structure on disk and not user input. if err := s.loadPlugin(currentPath); err != nil { s.log.Error("Failed to load plugin", "error", err, "pluginPath", filepath.Dir(currentPath)) s.errors = append(s.errors, err) @@ -471,6 +477,9 @@ func GetPluginMarkdown(pluginId string, name string) ([]byte, error) { return nil, PluginNotFoundError{pluginId} } + // nolint:gosec + // We can ignore the gosec G304 warning on this one because `plug.PluginDir` is based + // on plugin the folder structure on disk and not user input. path := filepath.Join(plug.PluginDir, fmt.Sprintf("%s.md", strings.ToUpper(name))) exists, err := fs.Exists(path) if err != nil { @@ -488,6 +497,9 @@ func GetPluginMarkdown(pluginId string, name string) ([]byte, error) { return make([]byte, 0), nil } + // nolint:gosec + // We can ignore the gosec G304 warning on this one because `plug.PluginDir` is based + // on plugin the folder structure on disk and not user input. data, err := ioutil.ReadFile(path) if err != nil { return nil, err diff --git a/pkg/services/alerting/notifiers/discord.go b/pkg/services/alerting/notifiers/discord.go index a80d6ad429e..5bbc5039b93 100644 --- a/pkg/services/alerting/notifiers/discord.go +++ b/pkg/services/alerting/notifiers/discord.go @@ -159,6 +159,9 @@ func (dn *DiscordNotifier) Notify(evalContext *alerting.EvalContext) error { } func (dn *DiscordNotifier) embedImage(cmd *models.SendWebhookSync, imagePath string, existingJSONBody []byte) error { + // nolint:gosec + // We can ignore the gosec G304 warning on this one because `imagePath` comes + // from the alert `evalContext` that generates the images. f, err := os.Open(imagePath) if err != nil { if os.IsNotExist(err) { diff --git a/pkg/services/alerting/notifiers/slack.go b/pkg/services/alerting/notifiers/slack.go index e7f7e4c804b..cfd4c053cc6 100644 --- a/pkg/services/alerting/notifiers/slack.go +++ b/pkg/services/alerting/notifiers/slack.go @@ -331,6 +331,8 @@ func (sn *SlackNotifier) Notify(evalContext *alerting.EvalContext) error { func (sn *SlackNotifier) slackFileUpload(evalContext *alerting.EvalContext, log log.Logger, url string, recipient string, token string) error { if evalContext.ImageOnDiskPath == "" { + // nolint:gosec + // We can ignore the gosec G304 warning on this one because `setting.HomePath` comes from Grafana's configuration file. evalContext.ImageOnDiskPath = filepath.Join(setting.HomePath, "public/img/mixed_styles.png") } log.Info("Uploading to slack via file.upload API") @@ -360,6 +362,10 @@ func (sn *SlackNotifier) generateSlackBody(path string, token string, recipient }() // Add the generated image file + // We can ignore the gosec G304 warning on this one because `imagePath` comes + // from the alert `evalContext` that generates the images. `evalContext` in turn derives the root of the file + // path from configuration variables. + // nolint:gosec f, err := os.Open(path) if err != nil { return nil, b, err diff --git a/pkg/services/ldap/ldap.go b/pkg/services/ldap/ldap.go index 1d9b02d786e..c7084839b04 100644 --- a/pkg/services/ldap/ldap.go +++ b/pkg/services/ldap/ldap.go @@ -95,6 +95,8 @@ func (server *Server) Dial() error { if server.Config.RootCACert != "" { certPool = x509.NewCertPool() for _, caCertFile := range strings.Split(server.Config.RootCACert, " ") { + // nolint:gosec + // We can ignore the gosec G304 warning on this one because `caCertFile` comes from ldap config. pem, err := ioutil.ReadFile(caCertFile) if err != nil { return err diff --git a/pkg/services/ldap/settings.go b/pkg/services/ldap/settings.go index fa4248108e3..93e94f3e016 100644 --- a/pkg/services/ldap/settings.go +++ b/pkg/services/ldap/settings.go @@ -115,6 +115,8 @@ func readConfig(configFile string) (*Config, error) { logger.Info("LDAP enabled, reading config file", "file", configFile) + // nolint:gosec + // We can ignore the gosec G304 warning on this one because `filename` comes from grafana configuration file fileBytes, err := ioutil.ReadFile(configFile) if err != nil { return nil, errutil.Wrap("Failed to load LDAP config file", err) diff --git a/pkg/services/provisioning/dashboards/config_reader.go b/pkg/services/provisioning/dashboards/config_reader.go index df2d6c7bb39..92eb9a10eae 100644 --- a/pkg/services/provisioning/dashboards/config_reader.go +++ b/pkg/services/provisioning/dashboards/config_reader.go @@ -19,6 +19,9 @@ type configReader struct { func (cr *configReader) parseConfigs(file os.FileInfo) ([]*config, error) { filename, _ := filepath.Abs(filepath.Join(cr.path, file.Name())) + + // nolint:gosec + // We can ignore the gosec G304 warning on this one because `filename` comes from ps.Cfg.ProvisioningPath yamlFile, err := ioutil.ReadFile(filename) if err != nil { return nil, err diff --git a/pkg/services/provisioning/dashboards/file_reader.go b/pkg/services/provisioning/dashboards/file_reader.go index bbf4c0d7739..576b62d4cf0 100644 --- a/pkg/services/provisioning/dashboards/file_reader.go +++ b/pkg/services/provisioning/dashboards/file_reader.go @@ -343,6 +343,8 @@ type dashboardJSONFile struct { } func (fr *FileReader) readDashboardFromFile(path string, lastModified time.Time, folderID int64) (*dashboardJSONFile, error) { + // nolint:gosec + // We can ignore the gosec G304 warning on this one because `path` comes from the provisioning configuration file. reader, err := os.Open(path) if err != nil { return nil, err diff --git a/pkg/services/provisioning/datasources/config_reader.go b/pkg/services/provisioning/datasources/config_reader.go index 52a5aa430b8..191ab962342 100644 --- a/pkg/services/provisioning/datasources/config_reader.go +++ b/pkg/services/provisioning/datasources/config_reader.go @@ -49,6 +49,9 @@ func (cr *configReader) readConfig(path string) ([]*configs, error) { func (cr *configReader) parseDatasourceConfig(path string, file os.FileInfo) (*configs, error) { filename, _ := filepath.Abs(filepath.Join(path, file.Name())) + + // nolint:gosec + // We can ignore the gosec G304 warning on this one because `filename` comes from ps.Cfg.ProvisioningPath yamlFile, err := ioutil.ReadFile(filename) if err != nil { return nil, err diff --git a/pkg/services/provisioning/notifiers/config_reader.go b/pkg/services/provisioning/notifiers/config_reader.go index c2d40270bb4..17886adba36 100644 --- a/pkg/services/provisioning/notifiers/config_reader.go +++ b/pkg/services/provisioning/notifiers/config_reader.go @@ -61,6 +61,9 @@ func (cr *configReader) readConfig(path string) ([]*notificationsAsConfig, error func (cr *configReader) parseNotificationConfig(path string, file os.FileInfo) (*notificationsAsConfig, error) { filename, _ := filepath.Abs(filepath.Join(path, file.Name())) + + // nolint:gosec + // We can ignore the gosec G304 warning on this one because `filename` comes from ps.Cfg.ProvisioningPath yamlFile, err := ioutil.ReadFile(filename) if err != nil { return nil, err diff --git a/pkg/services/provisioning/plugins/config_reader.go b/pkg/services/provisioning/plugins/config_reader.go index ec95c40cf78..fe5175cf066 100644 --- a/pkg/services/provisioning/plugins/config_reader.go +++ b/pkg/services/provisioning/plugins/config_reader.go @@ -69,6 +69,8 @@ func (cr *configReaderImpl) parsePluginConfig(path string, file os.FileInfo) (*p return nil, err } + // nolint:gosec + // We can ignore the gosec G304 warning on this one because `filename` comes from ps.Cfg.ProvisioningPath yamlFile, err := ioutil.ReadFile(filename) if err != nil { return nil, err diff --git a/pkg/setting/expanders.go b/pkg/setting/expanders.go index 021722ba998..c6f9a61f582 100644 --- a/pkg/setting/expanders.go +++ b/pkg/setting/expanders.go @@ -138,6 +138,8 @@ func (e fileExpander) Expand(s string) (string, error) { return "", err } + // nolint:gosec + // We can ignore the gosec G304 warning on this one because `s` comes from configuration section keys f, err := ioutil.ReadFile(s) if err != nil { return "", err