Grafana path traversal
Description
Grafana is an open-source platform for monitoring and observability. Grafana versions 8.0.0-beta1 through 8.3.0 (except for patched versions) iss vulnerable to directory traversal, allowing access to local files. The vulnerable URL path is: <grafana_host_url>/public/plugins//, where is the plugin ID for any installed plugin. At no time has Grafana Cloud been vulnerable. Users are advised to upgrade to patched versions 8.0.7, 8.1.8, 8.2.7, or 8.3.1. The GitHub Security Advisory contains more information about vulnerable URL paths, mitigation, and the disclosure timeline.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/grafana/grafanaGo | >= 8.3.0, < 8.3.1 | 8.3.1 |
github.com/grafana/grafanaGo | >= 8.2.0, < 8.2.7 | 8.2.7 |
github.com/grafana/grafanaGo | >= 8.1.0, < 8.1.8 | 8.1.8 |
github.com/grafana/grafanaGo | >= 8.0.0-beta1, < 8.0.7 | 8.0.7 |
Affected products
1Patches
1c798c0e958d1Security: Fix directory traversal issue (#42846)
2 files changed · +43 −3
pkg/api/plugins.go+16 −3 modified@@ -289,14 +289,27 @@ func (hs *HTTPServer) getPluginAssets(c *models.ReqContext) { return } - requestedFile := filepath.Clean(web.Params(c.Req)["*"]) - pluginFilePath := filepath.Join(plugin.PluginDir, requestedFile) + // prepend slash for cleaning relative paths + requestedFile := filepath.Clean(filepath.Join("/", web.Params(c.Req)["*"])) + rel, err := filepath.Rel("/", requestedFile) + if err != nil { + // slash is prepended above therefore this is not expected to fail + c.JsonApiErr(500, "Failed to get the relative path", err) + return + } - if !plugin.IncludedInSignature(requestedFile) { + if !plugin.IncludedInSignature(rel) { hs.log.Warn("Access to requested plugin file will be forbidden in upcoming Grafana versions as the file "+ "is not included in the plugin signature", "file", requestedFile) } + absPluginDir, err := filepath.Abs(plugin.PluginDir) + if err != nil { + c.JsonApiErr(500, "Failed to get plugin absolute path", nil) + return + } + + pluginFilePath := filepath.Join(absPluginDir, rel) // It's safe to ignore gosec warning G304 since we already clean the requested file path and subsequently // use this with a prefix of the plugin's directory, which is set during plugin loading // nolint:gosec
pkg/api/plugins_test.go+27 −0 modified@@ -23,9 +23,13 @@ func Test_GetPluginAssets(t *testing.T) { pluginDir := "." tmpFile, err := ioutil.TempFile(pluginDir, "") require.NoError(t, err) + tmpFileInParentDir, err := ioutil.TempFile("..", "") + require.NoError(t, err) t.Cleanup(func() { err := os.RemoveAll(tmpFile.Name()) assert.NoError(t, err) + err = os.RemoveAll(tmpFileInParentDir.Name()) + assert.NoError(t, err) }) expectedBody := "Plugin test" _, err = tmpFile.WriteString(expectedBody) @@ -61,6 +65,29 @@ func Test_GetPluginAssets(t *testing.T) { }) }) + t.Run("Given a request for a relative path", func(t *testing.T) { + p := plugins.PluginDTO{ + JSONData: plugins.JSONData{ + ID: pluginID, + }, + PluginDir: pluginDir, + } + service := &fakePluginStore{ + plugins: map[string]plugins.PluginDTO{ + pluginID: p, + }, + } + l := &logger{} + + url := fmt.Sprintf("/public/plugins/%s/%s", pluginID, tmpFileInParentDir.Name()) + pluginAssetScenario(t, "When calling GET on", url, "/public/plugins/:pluginId/*", service, l, + func(sc *scenarioContext) { + callGetPluginAsset(sc) + + require.Equal(t, 404, sc.resp.Code) + }) + }) + t.Run("Given a request for an existing plugin file that is not listed as a signature covered file", func(t *testing.T) { p := plugins.PluginDTO{ JSONData: plugins.JSONData{
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
13- github.com/advisories/GHSA-8pjx-jj86-j47pghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2021-43798ghsaADVISORY
- packetstormsecurity.com/files/165198/Grafana-Arbitrary-File-Reading.htmlghsax_refsource_MISCWEB
- packetstormsecurity.com/files/165221/Grafana-8.3.0-Directory-Traversal-Arbitrary-File-Read.htmlghsax_refsource_MISCWEB
- www.openwall.com/lists/oss-security/2021/12/09/2ghsamailing-listx_refsource_MLISTWEB
- www.openwall.com/lists/oss-security/2021/12/10/4ghsamailing-listx_refsource_MLISTWEB
- github.com/grafana/grafana/commit/c798c0e958d15d9cc7f27c72113d572fa58545ceghsax_refsource_MISCWEB
- github.com/grafana/grafana/security/advisories/GHSA-8pjx-jj86-j47pghsax_refsource_CONFIRMWEB
- grafana.com/blog/2021/12/08/an-update-on-0day-cve-2021-43798-grafana-directory-traversalghsaWEB
- grafana.com/blog/2021/12/08/an-update-on-0day-cve-2021-43798-grafana-directory-traversal/mitrex_refsource_CONFIRM
- security.netapp.com/advisory/ntap-20211229-0004ghsaWEB
- security.netapp.com/advisory/ntap-20211229-0004/mitrex_refsource_CONFIRM
- www.cisa.gov/known-exploited-vulnerabilities-catalogghsaWEB
News mentions
0No linked articles in our index yet.