ruborg 0.7.4 → 0.7.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -0
- data/README.md +19 -0
- data/SECURITY.md +23 -1
- data/lib/ruborg/backup.rb +63 -0
- data/lib/ruborg/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6bf325414affb3c4e36149069cf2e07958d43bef4766765a32aa9e2d97dbda02
|
|
4
|
+
data.tar.gz: 17dc1a6fabbf9571c9b5568cd098e272de0292f593c8ca6bc2e650d6756dca44
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 46ccdff766a5d7b3b6d2e19fbc1dd4c2b57202a799a14d66683299b9f2d162ce8f7889c6ebe8f8e925fc358c22ad6a4e0253a95b07d40635fe98a71f74bab5a1
|
|
7
|
+
data.tar.gz: e1663b45f75858b0197ce89e8803f95da4d104a8b7e4b7398baeaecd9033e469aeec8f2d74c6f21eb72e16ba77d848a2e651b6e58590f7a0a0de1fb5f553998e
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,39 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.7.6] - 2025-10-09
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- **Filesystem Compatibility**: Gracefully handle filesystems that don't support chattr operations
|
|
14
|
+
- Network filesystems (NFS, CIFS/SMB) and non-Linux filesystems (NTFS, FAT, exFAT) often don't support Linux file attributes
|
|
15
|
+
- When chattr fails with "Operation not supported", log warning and continue with deletion
|
|
16
|
+
- Allows `--remove-source` to work on network shares and external drives
|
|
17
|
+
- Fixes error: "Cannot remove immutable file: ... Error: chattr: Operation not supported"
|
|
18
|
+
|
|
19
|
+
### Technical Details
|
|
20
|
+
- Detects "Operation not supported" error from chattr command (lib/ruborg/backup.rb:394)
|
|
21
|
+
- Logs informative warning about filesystem limitations
|
|
22
|
+
- Continues with file deletion (no longer raises error)
|
|
23
|
+
- Test coverage: Added comprehensive test for unsupported filesystem scenario
|
|
24
|
+
|
|
25
|
+
## [0.7.5] - 2025-10-09
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
- **Automatic Immutable Attribute Removal**: Ruborg now automatically detects and removes Linux immutable flags (`chattr +i`) when deleting files with `--remove-source`
|
|
29
|
+
- Checks files with `lsattr` before deletion
|
|
30
|
+
- Removes immutable flag with `chattr -i` if present
|
|
31
|
+
- Works for both single files (per-file mode) and directories (standard mode)
|
|
32
|
+
- Gracefully handles systems without lsattr/chattr (macOS, etc.)
|
|
33
|
+
- Logs all immutable attribute operations for audit trail
|
|
34
|
+
|
|
35
|
+
### Technical Details
|
|
36
|
+
- Per-file mode: Checks each file individually before deletion (lib/ruborg/backup.rb:365)
|
|
37
|
+
- Standard mode: Recursively removes immutable from all files in directory (lib/ruborg/backup.rb:400-414)
|
|
38
|
+
- Linux-only feature - silently skips on other platforms
|
|
39
|
+
- Raises error if chattr command fails with proper error context
|
|
40
|
+
- Immutable flag detection uses precise parsing of lsattr flags field (lib/ruborg/backup.rb:386-387)
|
|
41
|
+
- Test coverage: 6 comprehensive specs covering all immutable file scenarios
|
|
42
|
+
|
|
10
43
|
## [0.7.4] - 2025-10-09
|
|
11
44
|
|
|
12
45
|
### Fixed
|
data/README.md
CHANGED
|
@@ -398,6 +398,25 @@ Error: Cannot use --remove-source: 'allow_remove_source' must be true (boolean).
|
|
|
398
398
|
Current value: "true" (String). Set 'allow_remove_source: true' in configuration.
|
|
399
399
|
```
|
|
400
400
|
|
|
401
|
+
**📌 Immutable File Handling (Linux)**
|
|
402
|
+
|
|
403
|
+
Ruborg automatically detects and removes Linux immutable attributes (`chattr +i`) when deleting files with `--remove-source`:
|
|
404
|
+
|
|
405
|
+
- **Automatic Detection**: Checks files with `lsattr` before deletion
|
|
406
|
+
- **Automatic Removal**: Removes immutable flag with `chattr -i` if present
|
|
407
|
+
- **Platform-Aware**: Gracefully skips on non-Linux systems (macOS, BSD, etc.)
|
|
408
|
+
- **Comprehensive**: Works for both single files and directories (recursive)
|
|
409
|
+
- **Logged**: All immutable attribute operations are logged for audit trail
|
|
410
|
+
|
|
411
|
+
**Root Privileges**: If your files have immutable attributes, you'll need root privileges to remove them. Configure sudoers for ruborg:
|
|
412
|
+
|
|
413
|
+
```bash
|
|
414
|
+
# /etc/sudoers.d/ruborg
|
|
415
|
+
michail ALL=(root) NOPASSWD: /usr/local/bin/ruborg
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
This allows running ruborg with sudo for file deletion without password prompts.
|
|
419
|
+
|
|
401
420
|
### List Archives
|
|
402
421
|
|
|
403
422
|
```bash
|
data/SECURITY.md
CHANGED
|
@@ -19,7 +19,15 @@ Ruborg implements several security measures to protect your backup operations:
|
|
|
19
19
|
- Refuses to delete system directories even when targeted via symlinks
|
|
20
20
|
- Uses `FileUtils.rm_rf` with `secure: true` option
|
|
21
21
|
|
|
22
|
-
### 4.
|
|
22
|
+
### 4. Immutable File Handling (Linux)
|
|
23
|
+
- **Automatic Detection**: Checks for Linux immutable attributes (`lsattr`) before file deletion
|
|
24
|
+
- **Safe Removal**: Removes immutable flag (`chattr -i`) only when necessary for deletion
|
|
25
|
+
- **Platform-Aware**: Feature only active on Linux systems with lsattr/chattr commands available
|
|
26
|
+
- **Error Handling**: Raises informative errors if immutable flag cannot be removed
|
|
27
|
+
- **Audit Trail**: All immutable attribute operations are logged for security auditing
|
|
28
|
+
- **Root Required**: Removing immutable attributes requires root privileges (use sudo with appropriate sudoers configuration)
|
|
29
|
+
|
|
30
|
+
### 5. Safe YAML Loading
|
|
23
31
|
- Uses `YAML.safe_load_file` to prevent arbitrary code execution
|
|
24
32
|
- Rejects YAML files containing Ruby objects or other dangerous constructs
|
|
25
33
|
- Only permits basic data types and Symbol class
|
|
@@ -229,6 +237,20 @@ We will respond within 48 hours and work with you to address the issue.
|
|
|
229
237
|
|
|
230
238
|
## Security Audit History
|
|
231
239
|
|
|
240
|
+
- **v0.7.5** (2025-10-09): Immutable file handling - security review passed
|
|
241
|
+
- **NEW FEATURE**: Automatic detection and removal of Linux immutable attributes (`chattr +i`) when deleting files with `--remove-source`
|
|
242
|
+
- **PLATFORM-AWARE**: Feature only active on Linux systems with lsattr/chattr commands available
|
|
243
|
+
- **SAFE OPERATION**: Checks files with `lsattr` before deletion, removes immutable flag with `chattr -i` only when necessary
|
|
244
|
+
- **ERROR HANDLING**: Raises informative errors if immutable flag cannot be removed (operation not permitted)
|
|
245
|
+
- **AUDIT TRAIL**: All immutable attribute operations logged for security monitoring
|
|
246
|
+
- **ROOT REQUIRED**: Removing immutable attributes requires root privileges (documented sudoers configuration)
|
|
247
|
+
- **SECURITY REVIEW**: No new security vulnerabilities introduced
|
|
248
|
+
- Uses Open3.capture3 for safe command execution (no shell injection)
|
|
249
|
+
- Precise flag parsing prevents false positives from filenames containing 'i'
|
|
250
|
+
- Works for both single files (per-file mode) and directories (recursive, standard mode)
|
|
251
|
+
- Gracefully handles systems without lsattr/chattr (macOS, BSD, etc.)
|
|
252
|
+
- Test coverage: 6 comprehensive specs covering all scenarios
|
|
253
|
+
|
|
232
254
|
- **v0.7.1** (2025-10-08): Paranoid mode duplicate detection - security review passed
|
|
233
255
|
- **NEW FEATURE**: SHA256 content hashing for detecting file changes even when mtime/size are identical
|
|
234
256
|
- **NEW FEATURE**: Smart skip statistics showing backed-up and skipped file counts
|
data/lib/ruborg/backup.rb
CHANGED
|
@@ -361,10 +361,69 @@ module Ruborg
|
|
|
361
361
|
raise BorgError, "Refusing to delete system path: #{real_path}"
|
|
362
362
|
end
|
|
363
363
|
|
|
364
|
+
# Check for immutable attribute and remove it if present
|
|
365
|
+
remove_immutable_attribute(real_path)
|
|
366
|
+
|
|
364
367
|
@logger&.info("Removing file: #{real_path}")
|
|
365
368
|
FileUtils.rm(real_path)
|
|
366
369
|
end
|
|
367
370
|
|
|
371
|
+
def remove_immutable_attribute(file_path)
|
|
372
|
+
# Check if lsattr command is available (Linux only)
|
|
373
|
+
return unless system("which lsattr > /dev/null 2>&1")
|
|
374
|
+
|
|
375
|
+
# Get file attributes
|
|
376
|
+
require "open3"
|
|
377
|
+
stdout, stderr, status = Open3.capture3("lsattr", file_path)
|
|
378
|
+
|
|
379
|
+
unless status.success?
|
|
380
|
+
@logger&.warn("Could not check attributes for #{file_path}: #{stderr.strip}")
|
|
381
|
+
return
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
# Check if immutable flag is set (format: "----i--------e----- /path/to/file")
|
|
385
|
+
# Extract the flags portion (everything before the file path)
|
|
386
|
+
flags = stdout.split.first || ""
|
|
387
|
+
return unless flags.include?("i")
|
|
388
|
+
|
|
389
|
+
@logger&.info("Removing immutable attribute from: #{file_path}")
|
|
390
|
+
_chattr_stdout, chattr_stderr, chattr_status = Open3.capture3("chattr", "-i", file_path)
|
|
391
|
+
|
|
392
|
+
unless chattr_status.success?
|
|
393
|
+
# Check if filesystem doesn't support chattr (common with NFS, CIFS, NTFS, etc.)
|
|
394
|
+
if chattr_stderr.include?("Operation not supported")
|
|
395
|
+
@logger&.warn(
|
|
396
|
+
"Filesystem does not support chattr operations for #{file_path}. " \
|
|
397
|
+
"This is normal for network filesystems (NFS, CIFS) or non-Linux filesystems. " \
|
|
398
|
+
"Attempting deletion anyway."
|
|
399
|
+
)
|
|
400
|
+
return
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
# Other errors (like permission denied) should still raise
|
|
404
|
+
@logger&.error("Failed to remove immutable attribute from #{file_path}: #{chattr_stderr.strip}")
|
|
405
|
+
raise BorgError, "Cannot remove immutable file: #{file_path}. Error: #{chattr_stderr.strip}"
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
@logger&.info("Successfully removed immutable attribute from: #{file_path}")
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
def remove_immutable_from_directory(dir_path)
|
|
412
|
+
# Check if lsattr command is available (Linux only)
|
|
413
|
+
return unless system("which lsattr > /dev/null 2>&1")
|
|
414
|
+
|
|
415
|
+
require "find"
|
|
416
|
+
require "open3"
|
|
417
|
+
|
|
418
|
+
# Remove immutable from directory itself
|
|
419
|
+
remove_immutable_attribute(dir_path)
|
|
420
|
+
|
|
421
|
+
# Recursively remove immutable from all files in directory
|
|
422
|
+
Find.find(dir_path) do |path|
|
|
423
|
+
remove_immutable_attribute(path) if File.file?(path)
|
|
424
|
+
end
|
|
425
|
+
end
|
|
426
|
+
|
|
368
427
|
def remove_source_files
|
|
369
428
|
require "fileutils"
|
|
370
429
|
|
|
@@ -398,8 +457,12 @@ module Ruborg
|
|
|
398
457
|
@logger&.info("Removing #{file_type}: #{real_path}")
|
|
399
458
|
|
|
400
459
|
if File.directory?(real_path)
|
|
460
|
+
# Remove immutable attributes from all files in directory
|
|
461
|
+
remove_immutable_from_directory(real_path)
|
|
401
462
|
FileUtils.rm_rf(real_path, secure: true)
|
|
402
463
|
elsif File.file?(real_path)
|
|
464
|
+
# Remove immutable attribute from single file
|
|
465
|
+
remove_immutable_attribute(real_path)
|
|
403
466
|
FileUtils.rm(real_path)
|
|
404
467
|
end
|
|
405
468
|
|
data/lib/ruborg/version.rb
CHANGED