JuliusBrussee/caveman · error

native session key chmod: %w

Error message

native session key chmod: %w

What it means

After reading an existing 32-byte session.key, LoadOrCreateSessionKey Chmods it to 0600 to guarantee user-only access even if it was provisioned with looser modes. Failure indicates the running user does not own the file or the filesystem rejects chmod — the key would potentially be readable by others, so the operation refuses to continue with it.

Source

Thrown at proxy/internal/nativeruntime/marker.go:64

			return nil, fmt.Errorf("native session key sync: %w", syncErr)
		}
		if closeErr := file.Close(); closeErr != nil {
			return nil, fmt.Errorf("native session key close: %w", closeErr)
		}
		return key, nil
	}
	if !errors.Is(err, os.ErrExist) {
		return nil, fmt.Errorf("native session key create: %w", err)
	}
	key, err = os.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("native session key read: %w", err)
	}
	if len(key) != sessionKeyBytes {
		return nil, fmt.Errorf("native session key length = %d, want %d", len(key), sessionKeyBytes)
	}
	if err := os.Chmod(path, 0o600); err != nil {
		return nil, fmt.Errorf("native session key chmod: %w", err)
	}
	return key, nil
}

// SessionMarker builds model-temporary correlation context. Local proxy removes
// valid markers byte-surgically before provider inspection or forwarding.
func SessionMarker(key []byte, sessionID string) (string, error) {
	if len(key) != sessionKeyBytes || sessionID == "" || len(sessionID) > 256 {
		return "", errors.New("native session marker: invalid key or session id")
	}
	encoded := base64.RawURLEncoding.EncodeToString([]byte(sessionID))
	sig := markerMAC(key, encoded)
	return fmt.Sprintf(`[[caveman-session-v1 sid="%s" sig="%s"]]`, encoded, sig), nil
}

// StripSessionMarkers removes only valid HMAC-signed markers. Invalid marker-
// shaped user text remains byte-identical. Conflicting valid session IDs are
// stripped but return no correlation identity.

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. chown the key (and runtime dir) to the running user, then retry
  2. Remove the immutable flag if set: sudo chattr -i <home>/runtime/session.key
  3. Store home on a POSIX-permission filesystem

Example fix

# before
session.key owned by root -> Error[1075]

# after
sudo chown $(id -un):$(id -gn) ~/.caveman/runtime/session.key && chmod 600 ~/.caveman/runtime/session.key
Defensive patterns

Strategy: validation

Validate before calling

func keyOwnedAndTight(path string) bool {
    fi, err := os.Stat(path)
    return err == nil && fi.Mode().Perm() == 0o600 &&
        int(fi.Sys().(*syscall.Stat_t).Uid) == os.Geteuid()
}

Prevention

When it happens

Trigger: Key file created by root or another user; key on a chmod-ignoring filesystem (FAT, some CIFS mounts); immutable attribute set (chattr +i).

Common situations: Mixed sudo/user operation; keys copied between machines preserving foreign ownership; provisioning pipelines running as root.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/2fa252f174668cd6. Report an issue: GitHub.