ory/hydra · critical

global secret is too short

Error message

global secret is too short

What it means

GetGlobalSecret rejects a configured system secret shorter than 16 characters, because short secrets are brute-forceable for the AES-GCM encryption Hydra applies to cookies and stored secrets. The value is then hashed into a byte secret via x.HashStringSecret.

Source

Thrown at driver/config/provider_fosite.go:31

	"github.com/ory/hydra/v2/fosite"
	"github.com/ory/hydra/v2/fosite/token/jwt"
	"github.com/ory/hydra/v2/x"
)

var _ fosite.GlobalSecretProvider = (*DefaultProvider)(nil)

func (p *DefaultProvider) GetGlobalSecret(ctx context.Context) ([]byte, error) {
	secrets := p.getProvider(ctx).Strings(KeyGetSystemSecret)

	if len(secrets) == 0 {
		p.l.Error("The system secret is not configured. Please provide one in the configuration file or environment variables.")
		return nil, errors.New("global secret is not configured")
	}

	secret := secrets[0]
	if len(secret) < 16 {
		p.l.Errorf("System secret must be undefined or have at least 16 characters but only has %d characters.", len(secret))
		return nil, errors.New("global secret is too short")
	}

	return x.HashStringSecret(secret), nil
}

var _ fosite.RotatedGlobalSecretsProvider = (*DefaultProvider)(nil)

func (p *DefaultProvider) GetRotatedGlobalSecrets(ctx context.Context) ([][]byte, error) {
	secrets := p.getProvider(ctx).Strings(KeyGetSystemSecret)

	if len(secrets) < 2 {
		return nil, nil
	}

	rotated := make([][]byte, len(secrets)-1)
	for i, secret := range secrets[1:] {
		rotated[i] = x.HashStringSecret(secret)
	}

View on GitHub (pinned to 4174065ffb)

Solutions

  1. Replace the system secret with a value of at least 16 characters, e.g. `openssl rand -base64 32`
  2. Update ORY_HYDRA_SECRETS_SYSTEM with the longer secret
  3. Keep old secrets in the list as rotated values if existing encrypted data must remain readable

Example fix

// before
secrets:
  system: ["changeme"]
// after
secrets:
  system:
    - "bG9uZy1yYW5kb20tc2VjcmV0LXZhbHVlIQ=="
Defensive patterns

Strategy: validation

Validate before calling

secret := os.Getenv("ORY_HYDRA_SECRETS_SYSTEM")
if len(secret) > 0 && len(secret) < 16 {
    return errors.New("system secret must be at least 16 characters")
}

Prevention

When it happens

Trigger: Calling GetGlobalSecret when secrets.system[0] (first configured value) has fewer than 16 characters, e.g. `secrets.system: ["short"]`.

Common situations: Developer set a memorable short password like `changeme`; a placeholder value left in production config; a trimmed or truncated environment variable.

Related errors


AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03). Data as JSON: /api/errors/82141905e8c4294d. Report an issue: GitHub.