CVE-2026-48790

CVE-2026-48790 is a medium-severity incorrect permission assignment for critical resource vulnerability in github.com/tursodatabase/turso-cli (go), affecting versions <= 1.0.25. It is fixed in 1.0.26.

Does this CVE actually affect you?

Kodem shows which CVEs are reachable and running in your applications, so you fix what's exploitable, not just what's listed.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Runtime intelligence, not another scanner.

Summary

turso-cli persists Turso platform JWT with world-readable (0o644) file permissions

turso-cli persists the user's Turso platform JWT to settings.json using Viper's default configPermissions of 0o644, leaving the credential file world-readable on standard Linux and macOS systems. Any other local UID on the host can read the file and recover the platform JWT, which grants full Turso platform access scoped to the user's organizations.

Details

The OAuth callback handler stores the platform JWT via the settings layer:

// internal/cmd/auth.go:205-214
jwt, err := callbackServer.Result()
...
settings.SetToken(jwt)

SetToken writes through Viper:

// internal/settings/settings.go:124-127
func (s *Settings) SetToken(token string) {
    viper.Set("token", token)
    s.changed = true
}

Persistence runs through viper.WriteConfig:

// internal/settings/settings.go:96-101
func TryToPersistChanges() error {
    if err := viper.WriteConfig(); err != nil {
        return fmt.Errorf("failed to persist turso settings file: %w", err)
    }
    return nil
}

Viper v1.21.0 (pinned in turso-cli go.mod) initializes configPermissions to os.FileMode(0o644) at viper.go:198 and passes that mode straight to os.OpenFile at viper.go:1688. Without a call to viper.SetConfigPermissions(0o600), the resulting settings.json is created at 0o644.

A grep over the auth-config write path under internal/ returns zero hits for Chmod, 0o600, or 0600, confirming there is no follow-up tightening of the file mode anywhere on the persistence path.

Proof of concept

Minimal reproducer using the same Viper version turso-cli pins (github.com/spf13/viper v1.21.0):

package main

import (
    "fmt"
    "os"
    "path/filepath"

    "github.com/spf13/viper"
)

func main() {
    dir, _ := os.MkdirTemp("", "viperpoc-*")
    defer os.RemoveAll(dir)

    viper.SetConfigName("settings")
    viper.SetConfigType("json")
    viper.AddConfigPath(dir)

    viper.Set("token", "FAKE_TURSO_JWT_xxxxxxxxxxxxxxxxxxxx")
    viper.Set("organization", "exampleorg")
    viper.SafeWriteConfig()

    st, _ := os.Stat(filepath.Join(dir, "settings.json"))
    fmt.Printf("mode: %o\n", st.Mode()&0o777)
}

$ go run main.go mode: 644

The same SafeWriteConfig / WriteConfig calls turso-cli uses produce the same 0o644 mode in a real turso auth login flow.

Workarounds

Until upgraded, users can tighten the existing files manually:

# Linux
chmod 600 ~/.config/turso/settings.json
chmod 700 ~/.config/turso

# macOS
chmod 600 "$HOME/Library/Application Support/turso/settings.json"
chmod 700 "$HOME/Library/Application Support/turso"

This must be repeated after any operation that recreates the file (e.g.
turso auth login) until the patched version is installed.

Resources

Impact

The token in settings.json grants the holder full Turso platform access, create or destroy databases, rotate credentials, exfiltrate data, change billing settings, for any organization the user belongs to.

Because the file is world-readable, the credential is reachable by:

  • Cron jobs or daemons running as a different system user on the same host
  • Sandboxed CI runners with a mounted home directory
  • Containers with a bind-mounted host home
  • Co-tenants on a shared multi-user developer or jumpbox host

The file path resolves through configdir.LocalConfig("turso"):

  • macOS: ~/Library/Application Support/turso/settings.json
  • Linux: ~/.config/turso/settings.json (or $XDG_CONFIG_HOME/turso/settings.json)

It contains the platform JWT in plaintext JSON alongside organization and username fields.

Comparable CLIs (gh, aws, docker, gcloud, plus close peers planetscale, neon, upstash) write credential files at 0o600 explicitly, so this is a deviation from the cross-vendor baseline rather than a deliberate trade-off.

A file, directory, or other resource is assigned permissions that allow broader access than intended. Typical impact: unauthorized read, modification, or execution of the resource.

CVE-2026-48790 has a CVSS score of 5.5 (Medium). The vector is requires local access, low privileges required, and no user interaction. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (1.0.26); upgrading removes the vulnerable code path.

Affected versions

github.com/tursodatabase/turso-cli (<= 1.0.25)

Security releases

github.com/tursodatabase/turso-cli → 1.0.26 (go)

Kodem intelligence

Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.

Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.

Already deployed Kodem?

See it in your environmentNew to Kodem? Get a demo →

Remediation advice

One-line fix at the existing Viper configuration site in internal/settings/settings.go (around lines 48-50):

viper.SetConfigName("settings")
viper.SetConfigType("json")
viper.AddConfigPath(configPath)
viper.SetConfigPermissions(0o600) // restrict settings.json to owner only

Defense in depth:

  • Add os.Chmod(configFile, 0o600) after TryToPersistChanges, or on read (as PlanetScale does in internal/config/config.go, they Stat the token file and self-heal if Mode() &^ 0o600 is nonzero). viper.SetConfigPermissions applies only on file creation, so an existing wider-mode file is not tightened otherwise.
  • Add os.Chmod(configPath, 0o700) after configdir.MakePath(configPath) (line 43) to close the equivalent gap on the enclosing directory, which is otherwise created under the default umask.

Patch: https://github.com/tursodatabase/turso-cli/commit/ffb914849216ef5a86353b3fa6cee66f33af3b66

Frequently Asked Questions

  1. What is CVE-2026-48790? CVE-2026-48790 is a medium-severity incorrect permission assignment for critical resource vulnerability in github.com/tursodatabase/turso-cli (go), affecting versions <= 1.0.25. It is fixed in 1.0.26. A file, directory, or other resource is assigned permissions that allow broader access than intended.
  2. How severe is CVE-2026-48790? CVE-2026-48790 has a CVSS score of 5.5 (Medium). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
  3. Which versions of github.com/tursodatabase/turso-cli are affected by CVE-2026-48790? github.com/tursodatabase/turso-cli (go) versions <= 1.0.25 is affected.
  4. Is there a fix for CVE-2026-48790? Yes. CVE-2026-48790 is fixed in 1.0.26. Upgrade to this version or later.
  5. Is CVE-2026-48790 exploitable, and should I be worried? Whether CVE-2026-48790 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
  6. What actually determines whether CVE-2026-48790 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
  7. How do I fix CVE-2026-48790? Upgrade github.com/tursodatabase/turso-cli to 1.0.26 or later.

Stop the waste.
Protect your environment with Kodem.