Skip to content

security: migrate provider tokens to Obsidian SecretStorage #102

Description

@ClaudiaFang

Priority

P0 — credential security

Problem

Provider tokens are currently stored as plaintext plugin settings and may appear in:

.obsidian/plugins/git-file-sync/data.json

Although the data remains local to the user's storage, plaintext credentials may be copied into vault sync, backups, filesystem indexes, accidental commits, or support bundles.

Obsidian SecretStorage is device-local. A vault synced through iCloud, Obsidian Sync, or another file-sync service can carry the credential reference in data.json, but it does not automatically carry the secret value to another device.

Example:

Mac
→ data.json contains credential reference
→ SecretStorage contains token

iPhone receives the synced vault
→ data.json contains the same credential reference
→ local SecretStorage does not contain the token

The plugin must therefore treat credentials as per-device state and must not automatically delete a legacy plaintext token immediately after one device migrates it.

Target model

  • Provider credentials are stored in per-device Obsidian SecretStorage.
  • Synced plugin settings contain only stable credential references and non-sensitive connection metadata.
  • A missing local secret is represented explicitly as Credential unavailable on this device, not as an invalid-token or generic connection failure.
  • Remote operations remain disabled until a credential is selected or entered on the current device.

Migration plan

Phase 1 — safe copy

  • Detect legacy plaintext GitHub, GitLab, and Gitea token fields.
  • Copy the token into SecretStorage on the current device.
  • Verify the secret can be read back before marking the local migration successful.
  • Keep the legacy plaintext token temporarily for other devices using the synced vault.
  • Do not overwrite or delete the original token if SecretStorage migration fails.

Phase 2 — explicit cleanup

  • Show that the vault still contains a legacy token for cross-device compatibility.
  • Explain that every device must configure or import its own local credential.
  • Provide an explicit action such as Remove legacy token from synced settings.
  • Require confirmation before removing the legacy token.
  • After cleanup, never reconstruct or resync the token through vault files.

Implementation plan

  • Store GitHub, GitLab, and Gitea credentials through Obsidian SecretStorage.
  • Keep only a credential reference and non-sensitive connection metadata in plugin settings.
  • Add one-time migration from existing plaintext token fields using the two-phase process above.
  • Handle missing, inaccessible, deleted, and replaced secrets with clear UI states.
  • Support provider switching without leaking credentials between providers or profiles.
  • Ensure logs, notices, test failures, and exported diagnostics redact credentials.
  • Document desktop/mobile and multi-device behavior, including iCloud and other synced-vault scenarios.

Suggested UI states

Credential unavailable on this device
Secrets are stored locally and are not synced with your vault.
Select or enter a credential on this device to continue.
Legacy credential still present
Your existing token remains in synced plugin settings so other devices can migrate safely.
After configuring every device, remove the legacy token permanently.

Acceptance criteria

  • New credentials are never persisted directly in data.json.
  • A synced vault may share credential references but never secret values.
  • Existing users migrate on each device without unexpectedly breaking other devices.
  • A failed migration does not modify or destroy the original credential.
  • Legacy plaintext credentials are removed only through an explicit confirmed cleanup action.
  • Missing local credentials produce a dedicated, actionable state.
  • Connection testing and provider switching continue to work on desktop and mobile.
  • Unit tests cover migration success, migration failure, missing local secret, token replacement, second-device startup, and legacy-token cleanup.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions