Skip to content

Symlink following in file deletion enables arbitrary file destruction #25

@0x-man

Description

@0x-man

Labels: bug, security

Summary

CleaningEngine.cleanItems() and ScanEngine.scanDirectory() do not resolve symlinks before deleting files. A symlink planted in any scanned directory (e.g. ~/Library/Caches/) can redirect deletion to arbitrary user-accessible paths like ~/.ssh/, ~/Documents/, or ~/.gnupg/.

Steps to reproduce

# 1. Create a symlink in a scanned cache directory
ln -s ~/.ssh ~/Library/Caches/fake-cache-entry
 
# 2. Run PureMac → Smart Scan
# 3. The symlink appears as a scannable cache item (auto-selected)
# 4. Click "Clean" → ~/.ssh is deleted

Impact

Any process running as the current user — malware, a rogue npm postinstall script, or even a cron job — can plant symlinks before a scheduled auto-clean runs. Combined with autoClean: true in SchedulerService, this becomes a zero-interaction attack that silently destroys targeted files.

Affected code

  • Services/CleaningEngine.swift:31removeItem(atPath:) follows symlinks
  • Services/ScanEngine.swift:302-347scanDirectory() doesn't check for symlinks

Suggested fix

Before any deletion, resolve the real path and verify it's still inside the expected scan root:

// Add to CleaningEngine, call before every removeItem
private func isSafeToDelete(path: String, allowedRoots: [String]) -> Bool {
    let resolved = URL(fileURLWithPath: path)
        .resolvingSymlinksInPath()
        .path
 
    // Reject if the resolved path escapes all allowed roots
    return allowedRoots.contains { root in
        resolved.hasPrefix(root)
    }
}

Each scan category already knows its root paths — pass them through to the cleaning engine and validate before deletion.

Additionally, in scanDirectory(), check FileManager.attributesOfItem(atPath:)[.type] for .typeSymbolicLink and either skip or flag symlinks to the user rather than treating them as normal cache entries.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingsecuritySecurity vulnerability or hardening

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions