Skip to content

Conversation

@tembo
Copy link
Contributor

@tembo tembo bot commented Jan 7, 2026

Summary

Implement encryption-aware secure file deletion system with cross-platform encryption detection and optimized deletion strategies.

Key Changes

  • Added VolumeEncryption type to track volume encryption status
  • Implemented platform-specific encryption detection for:
    • macOS FileVault
    • Linux LUKS
    • Windows BitLocker
  • Enhanced DeleteMode with configurable secure delete options
  • Added TRIM/hole punching support for secure deletion
  • Created encryption query API for frontend integration

Motivation

Improve file deletion security by:

  • Detecting volume encryption status
  • Optimizing deletion strategy based on encryption and disk type
  • Providing more granular control over secure delete operations

Testing

  • Added unit tests for encryption detection
  • Implemented platform-specific test cases
  • Verified secure delete behavior on different volume types

Future Work

  • Enhance hardware encryption detection
  • Add more granular encryption reporting
  • Implement compliance-focused deletion features

Want tembo to make any changes? Add a review or comment with @tembo and i'll get back to work!

tembo.io app.tembo.io

This comprehensive refactoring introduces encryption-aware secure deletion, adding infrastructure to detect, track, and optimize file deletion based on volume encryption status across macOS, Linux, and Windows platforms. Key changes include:

- Added VolumeEncryption type to domain model with encryption type detection
- Implemented platform-specific encryption detection for FileVault, BitLocker, LUKS
- Updated SecureDeleteOptions to support configurable, encryption-aware deletion
- Added TRIM/hole punching support for secure file deletion on different platforms
- Created new volume encryption query API for frontend integration
- Enhanced volume listing to include encryption metadata

The implementation follows NIST SP 800-88 guidance, recognizing that encrypted volumes require different secure deletion strategies compared to unencrypted media.
@tembo tembo bot added the tembo Pull request created by Tembo label Jan 7, 2026
@tembo
Copy link
Contributor Author

tembo bot commented Jan 7, 2026

Requesting review from @jamiepine who has experience with the following files modified in this PR:

  • core/Cargo.toml
  • core/src/volume/speed.rs
  • core/src/volume/types.rs
  • core/src/domain/volume.rs
  • core/src/volume/fs/apfs.rs
  • core/src/volume/manager.rs
  • core/src/ops/volumes/mod.rs
  • core/src/ops/files/delete/job.rs
  • core/src/ops/files/delete/mod.rs
  • core/src/ops/volumes/list/mod.rs
  • core/src/volume/platform/linux.rs
  • core/src/volume/platform/macos.rs
  • core/src/ops/volumes/list/query.rs
  • core/src/ops/volumes/list/output.rs
  • core/src/volume/platform/windows.rs
  • core/src/ops/files/delete/strategy.rs
  • core/src/ops/volumes/add_cloud/action.rs

@tembo tembo bot requested a review from jamiepine January 7, 2026 23:44
// Alternative: use lsblk to detect crypto devices
// lsblk -o NAME,FSTYPE,TYPE -J shows TYPE=crypt for encrypted devices
if let Ok(output) = Command::new("lsblk")
.args(["-o", "NAME,TYPE", "-J", device])
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This lsblk call runs synchronously inside detect_luks_encryption, which is called from async contexts. Since this blocks the async runtime during I/O, consider either making this function async with spawn_blocking, or caching the encryption detection results during initial volume scanning to avoid repeated blocking calls.

&format!(
"$vol = Get-BitLockerVolume -MountPoint '{}' -ErrorAction SilentlyContinue; \
if ($vol) {{ $vol.ProtectionStatus.ToString() }} else {{ 'NotFound' }}",
drive
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PowerShell command constructs a string with drive interpolated directly. While the input comes from internal drive letter parsing, consider validating that drive contains only expected characters (letters and colon) to prevent any potential command injection if this code path is ever exposed to external input.

};

if ret == 0 {
debug!("Successfully punched hole in file: {} bytes", size);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file descriptor fd is captured by the closure but the std_file that owns it is moved into the closure. After spawn_blocking completes, the file handle is dropped, which is correct. However, the fcntl call uses the raw fd without ensuring the file stays open - if the blocking task panics, this could leave resources in an inconsistent state. Consider using a guard pattern or ensuring proper cleanup on panic.

Comment on lines +167 to +177
use std::process::Command;

// Check if file is on an APFS or HFS+ volume with TRIM support
// Most SSDs on macOS support TRIM natively since macOS 10.10.4
let output = tokio::task::spawn_blocking(move || {
Command::new("diskutil")
.args(["info", "-plist", "/"])
.output()
})
.await;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function spawns a blocking task to check if the filesystem is APFS. The path parameter is unused in this implementation - the check always queries the root volume /. For accurate detection, this should check the actual path's mount point.


options
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After a successful TRIM operation, the code still proceeds to do overwrite passes. The comment says "we still do at least one overwrite pass for extra security" but if passes is 1 and TRIM succeeded, you're doing redundant work. Consider making this configurable or skipping the overwrite when TRIM succeeds on encrypted volumes.

enabled: true,
encryption_type,
is_unlocked,
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method always returns None, making it a no-op. If the intent is to provide a constructor for the unencrypted case, consider returning Self with enabled: false instead, or removing this method entirely since callers can just use None directly.

Co-authored-by: tembo[bot] <208362400+tembo[bot]@users.noreply.github.com>
@cursor
Copy link

cursor bot commented Jan 8, 2026

PR Summary

Implements encryption-aware deletion and surfaces encryption state throughout volumes and file operations.

  • Adds VolumeEncryption/EncryptionType to domain/volume.rs and wires into Volume with helpers (is_encrypted, recommended_secure_delete_passes, needs_multi_pass_secure_delete)
  • Detects encryption per-platform: APFS FileVault (macOS), LUKS/eCryptfs (Linux), BitLocker (Windows); propagates to runtime volumes and cloud volume placeholders remain None
  • Extends delete flow: DeleteMode::Secure(SecureDeleteOptions) with auto-tuned passes, optional TRIM/hole punching (ops/files/delete/trim.rs), and uses sd-crypto::erase for overwrites
  • Adds encryption-aware routing in LocalDeleteStrategy and logs; keeps confirmation gating for permanent/secure modes
  • Exposes APIs: volumes.encryption query returning per-path recommendations and augments volumes.list to include encryption info

Written by Cursor Bugbot for commit b329faf. Configure here.

&format!(
"$disk = Get-PhysicalDisk | Where-Object {{ $_.DeviceId -eq (Get-Partition -DriveLetter '{}' -ErrorAction SilentlyContinue).DiskNumber }}; if ($disk) {{ $disk.MediaType }} else {{ 'Unknown' }}",
drive.chars().next().unwrap_or('C')
),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Windows TRIM function has copy-paste error with wrong parameter

High Severity

The trim_file_windows function passes a PowerShell command format string as the dwFlagsAndAttributes parameter (6th argument) to CreateFileW, and references an undefined variable drive. This is clearly a copy-paste error from is_trim_supported_windows. The 6th parameter should be a u32 file attributes flag (like FILE_ATTRIBUTE_NORMAL), not a PowerShell script. This renders the Windows TRIM implementation non-functional.

Fix in Cursor Fix in Web

| EncryptionType::VeraCrypt
| EncryptionType::Hardware
)
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ECryptfs excluded from at-rest encryption protection check

Medium Severity

The provides_at_rest_protection method does not include EncryptionType::ECryptfs in its match arms, despite ECryptfs being a valid encryption type that's detected on Linux volumes. Since ECryptfs does provide at-rest encryption for files, volumes using it will incorrectly get 3-pass secure delete instead of the optimized 1-pass deletion, causing unnecessary I/O overhead and wear.

Fix in Cursor Fix in Web

true
}
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

macOS TRIM support check ignores the path parameter

Medium Severity

The is_trim_supported_macos function accepts a path parameter but completely ignores it. The diskutil info -plist / command always queries the root filesystem regardless of what path is provided. If a user has files on an external HDD mounted at a non-root location, this function would incorrectly report TRIM support based on the internal SSD's capabilities rather than the actual volume containing the file.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tembo Pull request created by Tembo

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants