uttrflow / uttrflow/uttrflow-swift
Clipboard history files and copied pictures are created 0644 in 0755 folders, unlike recordings, which are 0600
- Dominant language
- Swift
- Stars
- 4
- Forks
- 17
- Avg merge
- 3h 32m
- Merged PRs (30d)
- 277
Description
## What happens
- `ClipboardStore.persist` writes `clipboard.v1.json` and `saved.v1.json` with `JSONEncoder().encode(clips).write(to: url, options: .atomic)` after a plain `createDirectory(..., withIntermediateDirectories: true)` (`Sources/UttrflowClipboard/ClipboardStore.swift:483-485`).
- `ClipboardStore.keep` writes each picture with `data.write(to:)` into `Images/` created the same way (`:203-205`).
- No attributes are passed and nothing sets POSIX permissions afterwards. Under the default umask of 022, the files come out `-rw-r--r--` and the folders `drwxr-xr-x`, as seen on a real install.
Recordings are already handled: `RecordingWriter` opens with `0o600` (`Sources/UttrflowAudio/RecordingWriter.swift:77`), and so does the instance lock (`Sources/UttrflowCore/Support/SingleInstanceLock.swift:42`).
What protects the clipboard files today is only that `~/Library` and `~/Library/Application Support` are `drwx------` by default. A copy or archive that keeps the files' own modes (a migration, a `tar`/`rsync` of the folder, a shared external disk) has no such protection, and neither does a Mac where someone has loosened those folders.
## Why it matters
The clipboard file holds concealed password-manager copies in plain text (#483) and every copied screenshot. It is the most sensitive file the app writes, and it has the loosest permissions of any of them.
## Acceptance criteria
- `clipboard.v1.json`, `saved.v1.json` and each file in `Images/` are created with mode `0600`; the `Uttrflow/` and `Images/` folders with `0700`. Existing files are tightened on the next write.
- A test in `Tests/UttrflowClipboardTests/ClipboardStoreTests.swift` writes a clip and a picture in a temporary directory and asserts the modes via `FileManager.attributesOfItem(atPath:)[.posixPermissions]`.
- Optional follow-up: the same helper applied to the history, dictionary, snippets and predict stores. That can be one small issue each.
## Where to start
- Add a small helper (for example, in `Sources/UttrflowCore/Support/LocalStore.swift`) that creates a directory with `[.posixPermissions: 0o700]` and sets `0o600` on a file after an atomic write. An atomic write replaces the file, so set the mode after writing.
- Call it from `ClipboardStore.persist` and `ClipboardStore.keep`.
- Extend `Tests/UttrflowClipboardTests/ClipboardStoreTests.swift`.
- Run `make verify`. See `CONTRIBUTING.md`.
- Size: small, about 30 lines plus tests.
Contributor guide
Research direction
Start with Sources/UttrflowClipboard/ClipboardStore.swift at persist and keep, then inspect the existing permission handling in RecordingWriter.swift and SingleInstanceLock.swift. Extend Tests/UttrflowClipboardTests/ClipboardStoreTests.swift to write a clip and picture in a temporary directory and verify file and folder modes. Run make verify; done means the listed clipboard files use 0600 and Uttrflow/Images folders use 0700, including existing items on the next write.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- macos, swift
- Domain
- desktop, security
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 90/100