Schroedinger Sync reads a Windows DPAPI-protected Claude Desktop cookie store and uses the recovered sessionKey to authenticate an export session against claude.ai. That is a credential-sensitive operation and deserves the same scrutiny as any software that reads browser/application authentication material.
The design below reduces specific risks. It does not turn credential access into a generally safe primitive, prove the absence of exfiltration paths, or protect against an attacker who already controls the same Windows user context.
The implementation resolves Claude Desktop data from the current process user's profile and uses Windows DPAPI to recover the corresponding key material. loadMasterKey() and readSessionKey() therefore operate on the profile selected by the current Windows environment and on the Claude Desktop account represented by that profile.
This is a useful same-user design constraint, not a claim that the program can never be repurposed or that DPAPI protects a user from malicious code already executing as that same user. Review main.go and the platform assumptions in this document before treating the boundary as stronger than it is.
The current CDP path launches Chrome with chromedp.Flag("headless", false). TestHeadlessIsHardcoded checks for that literal configuration and rejects the specific environment/CLI override patterns covered by the test.
A visible browser makes the normal export workflow observable to the interactive user and is part of the current design. It is not proof that every invocation must always be noticed, nor is it a general defense against an attacker who already controls the desktop/session.
The intended application traffic is limited to the authenticated claude.ai workflow. The current implementation uses literal chromedp.Navigate destinations and same-origin relative fetch paths; TestNetworkEgressIsClaudeOnly scans the production Go source for the call patterns it knows about and fails if the covered literals point outside claude.ai.
That test is a regression tripwire, not whole-program information-flow analysis. It does not prove that a future variable-built URL, new networking library, browser extension, proxy, compromised dependency, or surrounding OS/browser environment cannot send data elsewhere.
The project currently has no telemetry or intentional third-party upload path. Treat that as an implementation property to review, not as an unconditional guarantee about every runtime component around the process.
After readSessionKey() recovers the session key, the value is registered with the redaction layer in security.go. The program routes the output paths it controls through that redaction logic, including the stdout redactor and the documented daemon/probe logging paths.
TestRedactionScrubsRegisteredSecret and TestStdoutRedactorSurvivesSplitWrites exercise selected redaction behavior, including the split-write regression. These tests do not prove that the credential is unobservable everywhere: the session key must exist in process memory while it is in use, the browser receives it as an authentication cookie, and an attacker/debugger with sufficient same-user access can inspect process/browser state outside the redactor's scope.
Since v2.2.0, the mutable AES master-key buffer and raw decrypted plaintext buffer are passed to zeroBytes after their last intended use in readSessionKey(). The returned immutable Go string remains available for the active session and in the redactor registry as needed. Buffer zeroing narrows retention for those specific mutable slices; it is not a general process-memory erasure guarantee.
readSessionKey() queries and decrypts the sessionKey cookie row needed by the current CDP workflow rather than intentionally decrypting the full Claude cookie jar.
copyCookieDB() nevertheless copies the entire encrypted Chromium Cookies SQLite database (and available sidecars) into a temporary directory so it can be read without the live-file locking problem. That temporary copy can contain encrypted cookies for multiple domains. Cleanup is best-effort and can be interrupted by process termination or system failure.
So the precise claim is:
- the current code intentionally decrypts one cookie row for the export workflow;
- it may temporarily copy a broader encrypted cookie database on disk;
- process/browser state still contains the active session credential while the session is running.
The production Go files remain in package main. TestNoImportableCookiePackage checks that property. This keeps the current credential/browser implementation out of a normal importable Go library surface.
It does not prevent copying, forking, modification, or reuse of source code under the applicable license.
getWithRetry applies backoff when the application receives the rate-limit error patterns it recognizes. This is intended to make legitimate exports less aggressive during transient throttling.
Backoff is not an abuse-prevention security boundary and should not be described as one. Server-side controls remain the authority for service rate limits.
The security-focused tests are regression tripwires for selected properties of the current implementation.
Examples:
TestHeadlessIsHardcodedchecks for the currentheadless=falseliteral and the specific override patterns implemented by the test.TestNetworkEgressIsClaudeOnlychecks the literal navigation / covered helper-call patterns it scans; it is not a general static analyzer.- redaction tests exercise registered test values through specific output paths.
- zeroing tests check selected mutable buffers and source-level cleanup calls.
TestNoImportableCookiePackagechecks that production Go source remains inpackage main.
A passing suite means those tested properties passed under that test implementation. It does not certify the application, prove the absence of vulnerabilities, or prove every possible runtime information flow.
If a security assumption changes, update the implementation, tests, and this document together.
This project does not claim to defend against every condition in the surrounding environment. Important examples include:
- malware or an operator already executing with the same Windows user privileges;
- debugger/process-memory capture;
- a compromised browser, browser extension, dependency, proxy, DNS/network layer, or operating system;
- unauthorized publication of exported Markdown or copied temporary files after the tool writes them;
- modified forks or binaries that do not match this repository/release;
- future Claude Desktop or Chromium storage/authentication changes that invalidate the assumptions documented here.
The project does not rely on an ethical-use sentence as a technical security control. Licensing and threat modeling solve different problems. The useful controls here are the implementation constraints, tests, reviewable source, and explicit scope described above.
Users remain responsible for operating the tool only on accounts, machines, and data they are authorized to access.
The public project is licensed under AGPLv3. A separate commercial-license path is documented in COMMERCIAL-LICENSE.md for use cases that require different licensing terms.
Do not infer support levels, warranties, future enterprise features, or permanent pricing/availability promises from this threat model. Those are product/licensing decisions and should only be stated where they are actually offered and documented.
Claude/Anthropic is the currently implemented provider in this repository. Support for any additional provider should be treated as future work until code, tests, and documentation for that provider exist.
Each additional authentication/storage model would require its own threat-boundary review rather than inheriting the Claude assumptions automatically.
Use GitHub's private vulnerability-reporting / Security Advisory path for this repository when available. Do not place credentials, cookies, private exports, exploit details, addresses, machine identifiers, or unrelated personal data in a public issue.
If a minimal public issue is necessary to establish contact, keep it free of sensitive details and request a private channel.
| Version | Status |
|---|---|
| v2.x (CDP-based) | Current supported line |
| v1.x (tls-client impersonation) | Superseded / unsupported |