Skip to content

feat(cloakserve): opt-in --persist-profile to keep user-data-dir on teardown - #568

Open
anvilsong wants to merge 1 commit into
CloakHQ:mainfrom
anvilsong:persist-profile
Open

anvilsong wants to merge 1 commit into
CloakHQ:mainfrom
anvilsong:persist-profile

Conversation

@anvilsong

Copy link
Copy Markdown

Defect

cloakserve owns each seed's Chrome user-data-dir and deletes it with _safe_rmtree in two places: after a failed launch (_get_or_create, bin/cloakserve ~L389) and on stop/teardown (_cleanup_process, ~L424). With --data-dir pointing at a persistent volume and a pinned fingerprint seed, the volume survives the container but the profile comes back empty, so there is no way to persist a profile through cloakserve.

Measured evidence

Observed downstream on 0.4.5 (same code paths still present in v0.5.11): 3.4 MB of profile written, cookie set, session deleted, volume intact, profile dir empty afterwards. Downstream currently carries a build-time patch making _safe_rmtree a no-op behind an env flag.

Fix

New opt-in --persist-profile flag / CLOAKSERVE_PERSIST_PROFILE=1 env var (flag accepts =true|false, overrides env). When on, a new ChromePool._discard_profile() skips deletion on both the failed-launch and teardown paths. When off (default), it calls _safe_rmtree exactly as before, so ephemeral behavior is unchanged. Also documented in README and CHANGELOG.

Security note

_safe_rmtree and its containment guard (refuse anything not strictly inside data_dir), the CVE-2026-45727 remediation, are untouched. Persist mode only skips the call; it never widens what can be deleted.

Testing

  • pytest tests/test_cloakserve.py: 108 passed (existing tests, including the _safe_rmtree containment tests, plus new tests for flag/env parsing, persist keeping the dir, and ephemeral mode still deleting and still refusing outside paths).
  • Not tested end-to-end against a real Chrome or a mounted volume; the two call-site changes were verified by code review only.

…eardown

Add --persist-profile / CLOAKSERVE_PERSIST_PROFILE. When set, the per-seed
user-data-dir is kept on stop and after a failed launch instead of being
deleted, so a profile on a --data-dir volume survives. Default is unchanged,
and the _safe_rmtree containment guard (CVE-2026-45727) is not modified.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@Cloak-HQ

Cloak-HQ commented Oct 7, 2026

Copy link
Copy Markdown
Member

Thanks for the PR, @anvilsong! The persist switch is a good addition, and routing both delete points through _discard_profile keeps the default path and the _safe_rmtree guard untouched.

One thing before we merge:

When a client connects without a fingerprint and cloakserve has no default --fingerprint, the profile dir is always data_dir/__default__, but the seed is re-rolled with random.randint on every launch.
With --persist-profile on, that one dir gets reused under a different fingerprint each time, so the saved cookies end up paired with a new identity.

Could you persist only seeded profiles and keep deleting the __default__ dir as before? Something like:

def _discard_profile(self, path: str) -> None:
    if self._persist_profile and Path(path).name != "__default__":
        logger.info("Keeping profile dir (persist mode): %s", path)
        return
    self._safe_rmtree(path)

A README note that --persist-profile only applies to seeded connections would help too.

The branch also needs a rebase, since CHANGELOG.md now conflicts with main.

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.

2 participants