Skip to content

fix(perplexity): store account backups in credential-backups with owner-only permissions and 7-day retention - #76

Merged
devin-ai-integration[bot] merged 2 commits into
mainfrom
devin/1791029621-perplexity-backups
Oct 3, 2026
Merged

devin-ai-integration[bot] merged 2 commits into
mainfrom
devin/1791029621-perplexity-backups

Conversation

@Villoh

@Villoh Villoh commented Oct 3, 2026 •

Copy link
Copy Markdown
Member

Summary

Perplexity account backups were much weaker than the CLIProxyAPI ones. AccountService.Remove and AccountService.RemoveAll copied the session token into {perplexity-accounts}/.backup/{stamp}/. That folder used default permissions and was never pruned, so every removed token stayed there forever.

Both kinds of backup now go through one shared helper, CredentialBackups (in Infrastructure, extracted from ProviderCatalogService):

{LocalData}/credential-backups/{yyyyMMddHHmmss}/              <- CLIProxyAPI auth files (unchanged)
{LocalData}/credential-backups/{yyyyMMddHHmmss}/perplexity/   <- Perplexity {id}.json (new)
  • Permissions: folders are 0700 and files 0600.
  • No overwriting: a backup never replaces an earlier one (UniquePath).
  • Retention: backups are deleted after 7 days (CredentialBackups.Retention).
  • Legacy cleanup: the AccountService constructor locks the old .backup/ folder to 0700, then prunes it and the shared root with the same 7-day rule. It also removes .backup/ once it is empty.
  • Live files: Perplexity account files are created as 0600 from the start (CredentialBackups.WriteOwnerOnly, using FileStreamOptions.UnixCreateMode). They live inside a 0700 accounts folder, so there is no window where another user can read them.
  • Breaking constructor change: AccountService(string directory) becomes AccountService(string directory, string backupRoot), so tests never write into the real LocalData folder.

Backups stay plaintext on purpose. They are only a manual recovery path (copy the file back), and OS-keyring encryption is not worth it until there is an in-app restore.

Tests: new tests check where the backup lands, the permissions of the backup, the account file and the folders, and that expired legacy .backup/ folders are pruned. Existing prune/unique-path tests now target CredentialBackups. CHANGELOG has an entry under Unreleased → Security.

Link to Devin session: https://app.devin.ai/sessions/86d238e41c424258929c91b0e2ac8a33
Open in Devin Desktop: https://app.devin.ai/desktop/session/86d238e41c424258929c91b0e2ac8a33?variant=devin
Requested by: @Villoh


Devin Review

…er-only permissions and 7-day retention

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration devin-ai-integration Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin resolved all 2 findings on 19cd024

Fixed by Devin (2)

  • Recent legacy backups remain readable by other users
  • New session files expose tokens before permission change

View all findings in Devin Review

Devin Review

…folder to owner

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration
devin-ai-integration Bot merged commit e07aa05 into main Oct 3, 2026
4 checks passed
@Villoh Villoh mentioned this pull request Oct 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant