Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 760315278b | |||
| bd5b3f533c |
+5
-9
@@ -1,17 +1,13 @@
|
||||
<!-- 11.3.8 START -->
|
||||
<!-- 11.3.8+security-01 START -->
|
||||
|
||||
# 11.3.8 (2025-06-17)
|
||||
|
||||
### Features and enhancements
|
||||
|
||||
- **Dependencies:** Bump Go to v1.24.4 [#106571](https://github.com/grafana/grafana/pull/106571), [@macabu](https://github.com/macabu)
|
||||
- **Dependencies:** Bump github.com/openfga/openfga to v1.8.13 to address CVE-2025-48371 [#106120](https://github.com/grafana/grafana/pull/106120), [@macabu](https://github.com/macabu)
|
||||
# 11.3.8+security-01 (2025-07-17)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- **Security:** Fixes CVE-2025-3415
|
||||
- **Security:** Fixed CVE-2025-6023
|
||||
- **Security:** Fixed CVE-2025-6197
|
||||
|
||||
<!-- 11.3.8 END -->
|
||||
<!-- 11.3.8+security-01 END -->
|
||||
<!-- 11.3.7 START -->
|
||||
|
||||
# 11.3.7 (2025-05-22)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@test-plugins/extensions-test-app",
|
||||
"version": "11.3.9",
|
||||
"version": "11.3.8",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "webpack -c ./webpack.config.ts --env production",
|
||||
@@ -12,7 +12,7 @@
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@grafana/eslint-config": "7.0.0",
|
||||
"@grafana/plugin-configs": "11.3.9",
|
||||
"@grafana/plugin-configs": "workspace:*",
|
||||
"@types/lodash": "4.17.7",
|
||||
"@types/node": "20.14.14",
|
||||
"@types/prismjs": "1.26.4",
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
@@ -39,6 +41,9 @@ var getViewIndex = func() string {
|
||||
return viewIndex
|
||||
}
|
||||
|
||||
// Only allow redirects that start with an alphanumerical character, a dash or an underscore.
|
||||
var redirectRe = regexp.MustCompile(`^/[a-zA-Z0-9-_].*`)
|
||||
|
||||
var (
|
||||
errAbsoluteRedirectTo = errors.New("absolute URLs are not allowed for redirect_to cookie value")
|
||||
errInvalidRedirectTo = errors.New("invalid redirect_to cookie value")
|
||||
@@ -68,6 +73,15 @@ func (hs *HTTPServer) ValidateRedirectTo(redirectTo string) error {
|
||||
return errForbiddenRedirectTo
|
||||
}
|
||||
|
||||
cleanPath := path.Clean(to.Path)
|
||||
// "." is what path.Clean returns for empty paths
|
||||
if cleanPath == "." {
|
||||
return errForbiddenRedirectTo
|
||||
}
|
||||
if to.Path != "/" && !redirectRe.MatchString(cleanPath) {
|
||||
return errForbiddenRedirectTo
|
||||
}
|
||||
|
||||
// when using a subUrl, the redirect_to should start with the subUrl (which contains the leading slash), otherwise the redirect
|
||||
// will send the user to the wrong location
|
||||
if hs.Cfg.AppSubURL != "" && !strings.HasPrefix(to.Path, hs.Cfg.AppSubURL+"/") {
|
||||
|
||||
@@ -14,20 +14,16 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/authn/authntest"
|
||||
"github.com/grafana/grafana/pkg/services/secrets/fakes"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/web/webtest"
|
||||
)
|
||||
|
||||
func setClientWithoutRedirectFollow(t *testing.T) {
|
||||
func setClientWithoutRedirectFollow(t *testing.T, s *webtest.Server) {
|
||||
t.Helper()
|
||||
old := http.DefaultClient
|
||||
http.DefaultClient = &http.Client{
|
||||
s.HttpClient = &http.Client{
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
}
|
||||
|
||||
t.Cleanup(func() {
|
||||
http.DefaultClient = old
|
||||
})
|
||||
}
|
||||
|
||||
func TestOAuthLogin_Redirect(t *testing.T) {
|
||||
@@ -79,7 +75,7 @@ func TestOAuthLogin_Redirect(t *testing.T) {
|
||||
})
|
||||
|
||||
// we need to prevent the http.Client from following redirects
|
||||
setClientWithoutRedirectFollow(t)
|
||||
setClientWithoutRedirectFollow(t, server)
|
||||
|
||||
res, err := server.Send(server.NewGetRequest("/login/generic_oauth"))
|
||||
require.NoError(t, err)
|
||||
@@ -155,7 +151,7 @@ func TestOAuthLogin_AuthorizationCode(t *testing.T) {
|
||||
})
|
||||
|
||||
// we need to prevent the http.Client from following redirects
|
||||
setClientWithoutRedirectFollow(t)
|
||||
setClientWithoutRedirectFollow(t, server)
|
||||
|
||||
res, err := server.Send(server.NewGetRequest("/login/generic_oauth?code=code"))
|
||||
require.NoError(t, err)
|
||||
@@ -199,7 +195,7 @@ func TestOAuthLogin_Error(t *testing.T) {
|
||||
hs.SecretsService = fakes.NewFakeSecretsService()
|
||||
})
|
||||
|
||||
setClientWithoutRedirectFollow(t)
|
||||
setClientWithoutRedirectFollow(t, server)
|
||||
|
||||
res, err := server.Send(server.NewGetRequest("/login/azuread?error=someerror"))
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -20,6 +21,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/services/user/usertest"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/web/webtest"
|
||||
)
|
||||
|
||||
func TestUserTokenAPIEndpoint(t *testing.T) {
|
||||
@@ -150,6 +152,95 @@ func TestUserTokenAPIEndpoint(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestHTTPServer_RotateUserAuthTokenRedirect(t *testing.T) {
|
||||
redirectTestCases := []struct {
|
||||
name string
|
||||
redirectUrl string
|
||||
expectedUrl string
|
||||
}{
|
||||
// Valid redirects should be preserved
|
||||
{"valid root path", "/", "/"},
|
||||
{"valid simple path", "/hello", "/hello"},
|
||||
{"valid single char path", "/a", "/a"},
|
||||
{"valid nested path", "/asd/hello", "/asd/hello"},
|
||||
|
||||
// Invalid redirects should be converted to root
|
||||
{"backslash domain", `/\grafana.com`, "/"},
|
||||
{"traversal backslash domain", `/a/../\grafana.com`, "/"},
|
||||
{"double slash", "//grafana", "/"},
|
||||
{"missing initial slash", "missingInitialSlash", "/"},
|
||||
{"parent directory", "/../", "/"},
|
||||
}
|
||||
|
||||
sessionTestCases := []struct {
|
||||
name string
|
||||
useSessionStorageRedirect bool
|
||||
}{
|
||||
{"when useSessionStorageRedirect is enabled", true},
|
||||
{"when useSessionStorageRedirect is disabled", false},
|
||||
}
|
||||
|
||||
for _, sessionCase := range sessionTestCases {
|
||||
t.Run(sessionCase.name, func(t *testing.T) {
|
||||
for _, redirectCase := range redirectTestCases {
|
||||
t.Run(redirectCase.name, func(t *testing.T) {
|
||||
server := SetupAPITestServer(t, func(hs *HTTPServer) {
|
||||
cfg := setting.NewCfg()
|
||||
cfg.LoginCookieName = "grafana_session"
|
||||
cfg.LoginMaxLifetime = 10 * time.Hour
|
||||
hs.Cfg = cfg
|
||||
hs.log = log.New()
|
||||
hs.AuthTokenService = &authtest.FakeUserAuthTokenService{
|
||||
RotateTokenProvider: func(ctx context.Context, cmd auth.RotateCommand) (*auth.UserToken, error) {
|
||||
return &auth.UserToken{UnhashedToken: "new"}, nil
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
redirectToQuery := url.QueryEscape(redirectCase.redirectUrl)
|
||||
urlString := "/user/auth-tokens/rotate"
|
||||
|
||||
if sessionCase.useSessionStorageRedirect {
|
||||
urlString = urlString + "?redirectTo=" + redirectToQuery
|
||||
}
|
||||
|
||||
req := server.NewGetRequest(urlString)
|
||||
req.AddCookie(&http.Cookie{Name: "grafana_session", Value: "123", Path: "/"})
|
||||
|
||||
if sessionCase.useSessionStorageRedirect {
|
||||
req = webtest.RequestWithWebContext(req, &contextmodel.ReqContext{UseSessionStorageRedirect: true})
|
||||
} else {
|
||||
req.AddCookie(&http.Cookie{Name: "redirect_to", Value: redirectToQuery, Path: "/"})
|
||||
}
|
||||
|
||||
var redirectStatusCode int
|
||||
var redirectLocation string
|
||||
|
||||
server.HttpClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
|
||||
if len(via) > 1 {
|
||||
// Stop after first redirect
|
||||
return http.ErrUseLastResponse
|
||||
}
|
||||
|
||||
if req.Response == nil {
|
||||
return nil
|
||||
}
|
||||
redirectStatusCode = req.Response.StatusCode
|
||||
redirectLocation = req.Response.Header.Get("Location")
|
||||
return nil
|
||||
}
|
||||
res, err := server.Send(req)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 302, redirectStatusCode)
|
||||
assert.Equal(t, redirectCase.expectedUrl, redirectLocation)
|
||||
|
||||
require.NoError(t, res.Body.Close())
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPServer_RotateUserAuthToken(t *testing.T) {
|
||||
type testCase struct {
|
||||
desc string
|
||||
|
||||
@@ -3,6 +3,8 @@ package middleware
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"path"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -12,6 +14,9 @@ import (
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
// Only allow redirects that start with an alphanumerical character, a dash or an underscore.
|
||||
var redirectRe = regexp.MustCompile(`^/?[a-zA-Z0-9-_].*`)
|
||||
|
||||
// OrgRedirect changes org and redirects users if the
|
||||
// querystring `orgId` doesn't match the active org.
|
||||
func OrgRedirect(cfg *setting.Cfg, userSvc user.Service) web.Handler {
|
||||
@@ -32,6 +37,11 @@ func OrgRedirect(cfg *setting.Cfg, userSvc user.Service) web.Handler {
|
||||
return
|
||||
}
|
||||
|
||||
if !validRedirectPath(c.Req.URL.Path) {
|
||||
// Do not switch orgs or perform the redirect because the new path is not valid
|
||||
return
|
||||
}
|
||||
|
||||
if err := userSvc.Update(ctx.Req.Context(), &user.UpdateUserCommand{UserID: ctx.UserID, OrgID: &orgId}); err != nil {
|
||||
if ctx.IsApiRequest() {
|
||||
ctx.JsonApiErr(404, "Not found", nil)
|
||||
@@ -55,3 +65,8 @@ func OrgRedirect(cfg *setting.Cfg, userSvc user.Service) web.Handler {
|
||||
c.Redirect(newURL, 302)
|
||||
}
|
||||
}
|
||||
|
||||
func validRedirectPath(p string) bool {
|
||||
cleanPath := path.Clean(p)
|
||||
return cleanPath == "." || cleanPath == "/" || redirectRe.MatchString(cleanPath)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package middleware
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -22,6 +23,12 @@ func TestOrgRedirectMiddleware(t *testing.T) {
|
||||
expStatus: 302,
|
||||
expLocation: "/?orgId=3",
|
||||
},
|
||||
{
|
||||
desc: "when setting a correct org for the user with an empty path",
|
||||
input: "?orgId=3",
|
||||
expStatus: 302,
|
||||
expLocation: "/?orgId=3",
|
||||
},
|
||||
{
|
||||
desc: "when setting a correct org for the user with '&kiosk'",
|
||||
input: "/?orgId=3&kiosk",
|
||||
@@ -62,4 +69,14 @@ func TestOrgRedirectMiddleware(t *testing.T) {
|
||||
|
||||
require.Equal(t, 404, sc.resp.Code)
|
||||
})
|
||||
|
||||
middlewareScenario(t, "when redirecting to an invalid path", func(t *testing.T, sc *scenarioContext) {
|
||||
sc.withIdentity(&authn.Identity{})
|
||||
|
||||
path := url.QueryEscape(`/\example.com`)
|
||||
sc.m.Get(url.QueryEscape(path), sc.defaultHandler)
|
||||
sc.fakeReq("GET", fmt.Sprintf("%s?orgId=3", path)).exec()
|
||||
|
||||
require.Equal(t, 404, sc.resp.Code)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ type Server struct {
|
||||
Mux *web.Mux
|
||||
RouteRegister routing.RouteRegister
|
||||
TestServer *httptest.Server
|
||||
HttpClient *http.Client
|
||||
}
|
||||
|
||||
// NewServer starts and returns a new server.
|
||||
@@ -50,6 +51,7 @@ func NewServer(t testing.TB, routeRegister routing.RouteRegister) *Server {
|
||||
RouteRegister: routeRegister,
|
||||
Mux: m,
|
||||
TestServer: testServer,
|
||||
HttpClient: &http.Client{},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +83,7 @@ func (s *Server) NewRequest(method string, target string, body io.Reader) *http.
|
||||
|
||||
// Send sends a HTTP request to the test server and returns an HTTP response.
|
||||
func (s *Server) Send(req *http.Request) (*http.Response, error) {
|
||||
return http.DefaultClient.Do(req)
|
||||
return s.HttpClient.Do(req)
|
||||
}
|
||||
|
||||
// SendJSON sets the Content-Type header to application/json and sends
|
||||
@@ -144,6 +146,7 @@ func requestContextMiddleware() web.Middleware {
|
||||
c.RequestNonce = ctx.RequestNonce
|
||||
c.PerfmonTimer = ctx.PerfmonTimer
|
||||
c.LookupTokenErr = ctx.LookupTokenErr
|
||||
c.UseSessionStorageRedirect = ctx.UseSessionStorageRedirect
|
||||
}
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@grafana/e2e-selectors": "11.3.9",
|
||||
"@grafana/plugin-configs": "11.3.9",
|
||||
"@grafana/plugin-configs": "workspace:*",
|
||||
"@testing-library/dom": "10.0.0",
|
||||
"@testing-library/react": "15.0.2",
|
||||
"@testing-library/user-event": "14.5.2",
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@grafana/e2e-selectors": "11.3.9",
|
||||
"@grafana/plugin-configs": "11.3.9",
|
||||
"@grafana/plugin-configs": "workspace:*",
|
||||
"@testing-library/dom": "10.0.0",
|
||||
"@testing-library/react": "15.0.2",
|
||||
"@testing-library/user-event": "14.5.2",
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@grafana/e2e-selectors": "11.3.9",
|
||||
"@grafana/plugin-configs": "11.3.9",
|
||||
"@grafana/plugin-configs": "workspace:*",
|
||||
"@testing-library/react": "15.0.2",
|
||||
"@testing-library/user-event": "14.5.2",
|
||||
"@types/jest": "29.5.13",
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"tslib": "2.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@grafana/plugin-configs": "11.3.9",
|
||||
"@grafana/plugin-configs": "workspace:*",
|
||||
"@testing-library/dom": "10.0.0",
|
||||
"@testing-library/jest-dom": "6.4.2",
|
||||
"@testing-library/react": "15.0.2",
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@grafana/e2e-selectors": "11.3.9",
|
||||
"@grafana/plugin-configs": "11.3.9",
|
||||
"@grafana/plugin-configs": "workspace:*",
|
||||
"@testing-library/dom": "10.0.0",
|
||||
"@testing-library/react": "15.0.2",
|
||||
"@testing-library/user-event": "14.5.2",
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@grafana/e2e-selectors": "11.3.9",
|
||||
"@grafana/plugin-configs": "11.3.9",
|
||||
"@grafana/plugin-configs": "workspace:*",
|
||||
"@testing-library/react": "15.0.2",
|
||||
"@testing-library/user-event": "14.5.2",
|
||||
"@types/jest": "29.5.13",
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@grafana/e2e-selectors": "11.3.9",
|
||||
"@grafana/plugin-configs": "11.3.9",
|
||||
"@grafana/plugin-configs": "workspace:*",
|
||||
"@testing-library/react": "15.0.2",
|
||||
"@testing-library/user-event": "14.5.2",
|
||||
"@types/jest": "29.5.13",
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"tslib": "2.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@grafana/plugin-configs": "11.3.9",
|
||||
"@grafana/plugin-configs": "workspace:*",
|
||||
"@testing-library/dom": "10.0.0",
|
||||
"@testing-library/react": "15.0.2",
|
||||
"@testing-library/user-event": "14.5.2",
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
"uuid": "9.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@grafana/plugin-configs": "11.3.9",
|
||||
"@grafana/plugin-configs": "workspace:*",
|
||||
"@testing-library/dom": "10.0.0",
|
||||
"@testing-library/jest-dom": "6.4.2",
|
||||
"@testing-library/react": "15.0.2",
|
||||
|
||||
@@ -3136,7 +3136,7 @@ __metadata:
|
||||
"@grafana/data": "npm:11.3.9"
|
||||
"@grafana/e2e-selectors": "npm:11.3.9"
|
||||
"@grafana/experimental": "npm:2.1.1"
|
||||
"@grafana/plugin-configs": "npm:11.3.9"
|
||||
"@grafana/plugin-configs": "workspace:*"
|
||||
"@grafana/runtime": "npm:11.3.9"
|
||||
"@grafana/schema": "npm:11.3.9"
|
||||
"@grafana/ui": "npm:11.3.9"
|
||||
@@ -3180,7 +3180,7 @@ __metadata:
|
||||
"@grafana/data": "npm:11.3.9"
|
||||
"@grafana/e2e-selectors": "npm:11.3.9"
|
||||
"@grafana/experimental": "npm:2.1.1"
|
||||
"@grafana/plugin-configs": "npm:11.3.9"
|
||||
"@grafana/plugin-configs": "workspace:*"
|
||||
"@grafana/runtime": "npm:11.3.9"
|
||||
"@grafana/sql": "npm:11.3.9"
|
||||
"@grafana/ui": "npm:11.3.9"
|
||||
@@ -3209,7 +3209,7 @@ __metadata:
|
||||
dependencies:
|
||||
"@emotion/css": "npm:11.13.4"
|
||||
"@grafana/data": "npm:11.3.9"
|
||||
"@grafana/plugin-configs": "npm:11.3.9"
|
||||
"@grafana/plugin-configs": "workspace:*"
|
||||
"@grafana/runtime": "npm:11.3.9"
|
||||
"@grafana/schema": "npm:11.3.9"
|
||||
"@grafana/ui": "npm:11.3.9"
|
||||
@@ -3252,7 +3252,7 @@ __metadata:
|
||||
"@grafana/data": "npm:11.3.9"
|
||||
"@grafana/e2e-selectors": "npm:11.3.9"
|
||||
"@grafana/experimental": "npm:2.1.1"
|
||||
"@grafana/plugin-configs": "npm:11.3.9"
|
||||
"@grafana/plugin-configs": "workspace:*"
|
||||
"@grafana/runtime": "npm:11.3.9"
|
||||
"@grafana/schema": "npm:11.3.9"
|
||||
"@grafana/ui": "npm:11.3.9"
|
||||
@@ -3335,7 +3335,7 @@ __metadata:
|
||||
"@grafana/data": "npm:11.3.9"
|
||||
"@grafana/e2e-selectors": "npm:11.3.9"
|
||||
"@grafana/experimental": "npm:2.1.1"
|
||||
"@grafana/plugin-configs": "npm:11.3.9"
|
||||
"@grafana/plugin-configs": "workspace:*"
|
||||
"@grafana/runtime": "npm:11.3.9"
|
||||
"@grafana/sql": "npm:11.3.9"
|
||||
"@grafana/ui": "npm:11.3.9"
|
||||
@@ -3366,7 +3366,7 @@ __metadata:
|
||||
"@grafana/data": "npm:11.3.9"
|
||||
"@grafana/e2e-selectors": "npm:11.3.9"
|
||||
"@grafana/experimental": "npm:2.1.1"
|
||||
"@grafana/plugin-configs": "npm:11.3.9"
|
||||
"@grafana/plugin-configs": "workspace:*"
|
||||
"@grafana/runtime": "npm:11.3.9"
|
||||
"@grafana/sql": "npm:11.3.9"
|
||||
"@grafana/ui": "npm:11.3.9"
|
||||
@@ -3395,7 +3395,7 @@ __metadata:
|
||||
dependencies:
|
||||
"@emotion/css": "npm:11.13.4"
|
||||
"@grafana/data": "npm:11.3.9"
|
||||
"@grafana/plugin-configs": "npm:11.3.9"
|
||||
"@grafana/plugin-configs": "workspace:*"
|
||||
"@grafana/runtime": "npm:11.3.9"
|
||||
"@grafana/schema": "npm:11.3.9"
|
||||
"@grafana/ui": "npm:11.3.9"
|
||||
@@ -3430,7 +3430,7 @@ __metadata:
|
||||
"@grafana/e2e-selectors": "npm:11.3.9"
|
||||
"@grafana/experimental": "npm:2.1.1"
|
||||
"@grafana/google-sdk": "npm:0.1.2"
|
||||
"@grafana/plugin-configs": "npm:11.3.9"
|
||||
"@grafana/plugin-configs": "workspace:*"
|
||||
"@grafana/runtime": "npm:11.3.9"
|
||||
"@grafana/schema": "npm:11.3.9"
|
||||
"@grafana/ui": "npm:11.3.9"
|
||||
@@ -3481,7 +3481,7 @@ __metadata:
|
||||
"@grafana/lezer-traceql": "npm:0.0.19"
|
||||
"@grafana/monaco-logql": "npm:^0.0.7"
|
||||
"@grafana/o11y-ds-frontend": "workspace:*"
|
||||
"@grafana/plugin-configs": "npm:11.3.9"
|
||||
"@grafana/plugin-configs": "workspace:*"
|
||||
"@grafana/runtime": "workspace:*"
|
||||
"@grafana/schema": "workspace:*"
|
||||
"@grafana/ui": "workspace:*"
|
||||
@@ -3885,7 +3885,7 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@grafana/plugin-configs@npm:11.3.9, @grafana/plugin-configs@workspace:*, @grafana/plugin-configs@workspace:packages/grafana-plugin-configs":
|
||||
"@grafana/plugin-configs@workspace:*, @grafana/plugin-configs@workspace:packages/grafana-plugin-configs":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@grafana/plugin-configs@workspace:packages/grafana-plugin-configs"
|
||||
dependencies:
|
||||
@@ -9162,7 +9162,7 @@ __metadata:
|
||||
"@emotion/css": "npm:11.11.2"
|
||||
"@grafana/data": "workspace:*"
|
||||
"@grafana/eslint-config": "npm:7.0.0"
|
||||
"@grafana/plugin-configs": "npm:11.3.9"
|
||||
"@grafana/plugin-configs": "workspace:*"
|
||||
"@grafana/runtime": "workspace:*"
|
||||
"@grafana/schema": "workspace:*"
|
||||
"@grafana/ui": "workspace:*"
|
||||
|
||||
Reference in New Issue
Block a user