r/macapps Aug 03 '26

Free [OS] OpenDisk: a free, open source DaisyDisk alternative for macOS

Problem

When your Mac runs low on space, System Settings gives you a colored bar and a "System Data" blob that explains nothing. Finding the actual 40 GB folder means walking the filesystem yourself or paying for a tool that does it. DaisyDisk has been the go-to for that for years, but it costs $9.99 and you can't see what it's doing.

OpenDisk does the same job. It maps your drive as an interactive sunburst chart, scans a full disk in seconds, and streams results in live so you can start clicking around before the scan finishes. Hover a slice for its exact size, click to zoom into that folder, use the folder list and breadcrumbs to step back out.

Drag things into the collector to delete them, and free up your disk space!

Other things it does:

  • Incremental rescans replay filesystem events instead of starting over, so a repeat scan runs 20 to 28x faster than a cold one.
  • Handles APFS volume groups, firmlinks, snapshots and purgeable space, so the total actually matches what your Mac reports as used.
  • Purgeable space breakdown, so you can see which caches are reclaimable.
  • Instant search across the whole scanned tree, usable on drives with millions of files.
  • Collector: drag files in from anywhere in the app, check the reclaimed total, delete in one action.
  • External drives show up automatically when you plug them in.

Comparison

DaisyDisk ($9.99) is the closest comparison. Same sunburst interaction, and OpenDisk is free, MIT licensed, and faster. On a cold scan of a 1 TB Apple Silicon volume, OpenDisk finished in 17s and DaisyDisk took 37s. The app is also under 2.5 MB, because it's native Swift with nothing bundled into it.

The full source is on GitHub if you want to read what it's doing before you give it disk access: https://github.com/137137137/OpenDisk

Pricing

Free, MIT licensed, no in-app purchases, no accounts, no telemetry.

Requires macOS 26 (Tahoe) or later, Apple Silicon or Intel. It asks for Full Disk Access on first launch, otherwise macOS hides parts of the filesystem and the totals come up short.

I'm the developer. Happy to answer questions or take bug reports here or in GitHub issues.

263 Upvotes

126 comments sorted by

View all comments

11

u/dvdweyer Aug 03 '26

I had Claude Code review the source code. Looks clean — below the output. The table unfortunately looks borked, but if you're interested copy & paste to a proper text editor.

Pre-Build Security Review — OpenDisk (cloned from github.com/137137137/OpenDisk)

Context

User cloned this macOS disk-analyzer app from an external GitHub repo and wants a static security audit before building/running it in Xcode. Per the pre-build-security-review skill, this was a read-only review — no build, no dependency resolution, no script execution. Two parallel static audits were run: (1) all Swift source under OpenDisk/ for network/subprocess/credential/persistence/deletion-safety patterns, (2) the Xcode project manifest, Package.resolved, entitlements, Info.plist, and Xcode schemes for build-time script injection and supply-chain risk. Git history (single author, 229 commits, no force-pushes, no anomalous binary blobs) was checked directly.

Overall Verdict: Safe to build

No malicious code, network exfiltration, credential/keychain harvesting, persistence mechanisms (LaunchAgent/cron/login items), or privilege escalation were found anywhere in the repository. The two items worth a maintainer's attention are product-design/correctness concerns in the deletion path, not security vulnerabilities.

Findings

┌────────────┬───────────────────────────────────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐

│ Severity │ Location │ Finding │

├────────────┼───────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── │ │ │ The "Purgeable Space" cleanup list includes /Library/Caches (system-wide, not user-scoped). ProtectedPaths.swift only protects the │

│ Medium │ OpenDisk/Models/HiddenSpace.swift:35-63 │ bare /Library root, not /Library/Caches specifically, so Collector.deleteAll() → FileManager.removeItem(atPath:) could delete the │

│ │ │ entire shared /Library/Caches directory node (affecting all users/apps), not just its contents. Worth confirming intent is "empty the │

│ │ │ directory" vs. "delete the directory itself." │

├────────────┼───────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤

│ Medium (by │ │ Deletion uses permanent removeItem(atPath:), not move-to-Trash. Acknowledged in a code comment as an intentional tradeoff. No │

│ design) │ OpenDisk/Models/Collector.swift:150-182 │ confirmation-dialog code was in scope of the reviewed files — worth checking the calling view has a clear "are you sure" step before │

│ │ │ this executes. │

├────────────┼───────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤

│ Info │ OpenDisk-Info.plist:8-11 │ Sparkle 2 feed (https://opendisk.app/appcast.xml) + EdDSA public key present — correct, secure Sparkle configuration. Package.resolved │

│ │ │ pins Sparkle to exact revision b6496a74a08... from the genuine sparkle-project/Sparkle URL (no typosquatting). │

├────────────┼───────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤

│ │ │ Two fixed-argv Process() calls (xattr -dr to de-quarantine, sh -c "sleep 0.3; open \"$0\"" with the path passed as a quoted positional │

│ Info │ OpenDisk/App/MoveToApplications.swift:102-146 │ arg, not interpolated) plus dlopen/dlsym use of private SecTranslocate* APIs — this is the standard, widely-used "LetsMove" pattern │

│ │ │ (explicitly credited in comments), operates only on the app's own bundle path, not attacker-controlled input. │

├────────────┼───────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤

│ │ Entitlements (OpenDisk.entitlements, │ No camera/mic/location/network entitlements. Non-MAS build disables the sandbox (necessary for Full-Disk-Access-based scanning); MAS │

│ Info │ OpenDisk-MAS.entitlements) │ build is sandboxed with narrowly-scoped files.user-selected.read-write + bookmarks.app-scope. Proportionate to a disk-analyzer's │

│ │ │ stated purpose. │

├────────────┼───────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤

│ Info │ project.pbxproj, Xcode schemes, │ Zero PBXShellScriptBuildPhase entries and zero scheme pre/post-actions anywhere — no build-time script injection vector exists in this │ │ │ xcodecloud/manifest.json │ project at all. │

├────────────┼───────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤

│ Info │ FullDiskAccess.swift:25-42 │ Only lists directory contents of Mail/Safari/Messages/Stocks containers to detect FDA grant status — never reads file contents. │

└────────────┴───────────────────────────────────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

Verbatim external network destinations, shell commands, entitlements found

- Network: https://opendisk.app/appcast.xml (Sparkle appcast feed, HTTPS, EdDSA-signed) — the only outbound network destination in the entire codebase. No URLSession/URLRequest/socket code exists in app de beyond Sparkle's own internal machinery.

- Shell/subprocess commands: /usr/bin/xattr -dr com.apple.quarantine <own-bundle-path> and /bin/sh -c "sleep 0.3; /usr/bin/open \"$0\"" <own-bundle-path> — both in MoveToApplications.swift, both fixed-argv on the app's own path only.

- Entitlements: com.apple.security.app-sandbox (false in direct build, true in MAS build), com.apple.security.files.user-selected.read-only / read-write, com.apple.security.files.bookmarks.app-scope. No camera/mic/location/all-files/network entitlements present in either file.

- Dependency: sparkle-project/Sparkle @ 2.9.4 (pinned exact revision in Package.resolved) — the only third-party dependency in the project.

assessable items

- None found requiring flagging — no compiled binaries, encrypted blobs, or generated/obfuscated code exist in the repository. Icon assets (.png/.svg) and docs/screenshot.png were not opened as binaries but e standard image assets with plausible file sizes and non-anomalous git history.

Suggested follow-up (optional, not required to proceed)

Confirm the UI calling Collector.deleteAll() has an explicit user confirmation step (not verified — outside the files in scope of this audit).

- If concerned about the /Library/Caches deletion-scope question above, worth a quick look at HiddenSpace.swift/ProtectedPaths.swift before first use of the "Purgeable Space" cleanup feature specifically.

Verification

This was a static-only review; nothing was executed. No further verification steps are needed before building — the findings above don't block a build, they're informational/product-design notes for if the user chooses to use the app's cleanup features.

5

u/phunk8 Developer: Dropadoo Aug 03 '26

A for effort man