Open-Source Wikis

/

Grafana

/

Background

/

Security

grafana/grafana

Security

Trust boundaries, authentication paths, and the security-sensitive surfaces in this codebase.

Trust boundaries

Grafana has roughly five trust zones:

  1. Anonymous browser — pre-login. Can hit /login, /api/health, public dashboards if enabled.
  2. Authenticated user — has an identity (SignedInUser); subject to RBAC.
  3. Server account / API token — same as authenticated user but typically machine-driven.
  4. Server itself — talking to plugins, datasources, the database, KMS.
  5. Plugins — running inside the same Grafana process (frontend) or as subprocesses (backend). Treated as semi-trusted; the sandbox restricts frontend plugins.

Authentication paths

See Backend / Authentication & access control for a full tour. The summary:

  • Session cookies for browsers (signed with [auth] login_cookie_name and [security] cookie_secure/cookie_samesite).
  • Bearer tokens for API consumers (service account tokens preferred over legacy API keys).
  • Per-provider OAuth callbacks (/login/<provider>).
  • LDAP, JWT, basic auth, anonymous as configured.

RBAC

pkg/services/accesscontrol/ enforces fine-grained permissions on every protected route. Custom roles can be created via the RBAC API. List endpoints filter results by permission rather than rejecting outright. See Authentication & access control.

Secrets

  • Datasource secrets (secureJsonData) are encrypted at rest using a per-instance key from [security] secret_key. The key can be wrapped by an external KMS via pkg/services/kmsproviders/.
  • The secret_key should be a long random value. Defaults to a placeholder in conf/defaults.ini — production deployments must override.
  • Password hashes use bcrypt (legacy: PBKDF2 stretching).
  • Session tokens are random strings stored as hashes; a leak of the database doesn't grant existing sessions to an attacker.

CSRF

POST/PUT/DELETE requests with cookie auth require an X-Grafana-Org-Id header (or another non-cookie token) to mitigate CSRF. The backendSrv adds these automatically. Bearer-token auth doesn't need CSRF protection since cookies aren't involved.

CORS

By default, CORS is restrictive — same-origin only. Configure [security] allow_embedding for iframe embedding.

XSS

Frontend treats all strings from datasources as untrusted. Helpers in @grafana/data's textUtil provide safe escaping. The plugin sandbox is the additional layer for untrusted plugin code.

The legacy text panel had a long history of HTML rendering issues — newer versions use a strict allow-list HTML parser.

SQL injection

All SQL goes through xorm parameterized queries. No string concatenation into SQL is allowed. Custom raw SQL helpers also use placeholders.

Plugin signing

Plugins are signed by their publishers; Grafana verifies the signature on load via pkg/plugins/manifestverifier/. Unsigned plugins are blocked unless [plugins] allow_loading_unsigned_plugins lists them. The plugin admin UI shows badges (Signed, Unsigned, Internal) so admins know the provenance.

Sandbox

Untrusted plugin frontend code runs in an iframe sandbox (public/app/features/plugins/sandbox/) when the pluginsFrontendSandbox feature toggle is on. The sandbox restricts DOM, network, and storage access.

Image rendering

The renderer fetches dashboards using a short-lived render token instead of the user's full session, narrowing what a compromised renderer can do.

Audit logs

Auditable actions are logged through the standard logger; Enterprise builds add a structured audit log sink. OSS administrators can grep data/log/grafana.log for level=info logger=accesscontrol and similar entries.

Reporting vulnerabilities

The security policy lives at github.com/grafana/grafana/security/policy. Don't open public issues for vulnerabilities; use the private disclosure path described there.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Security – Grafana wiki | Factory