ruborg 0.5.0 → 0.6.1
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/.ruby-version +1 -0
 - data/CHANGELOG.md +67 -0
 - data/README.md +202 -30
 - data/SECURITY.md +110 -0
 - data/exe/ruborg +9 -1
 - data/lib/ruborg/backup.rb +33 -3
 - data/lib/ruborg/cli.rb +210 -25
 - data/lib/ruborg/config.rb +227 -2
 - data/lib/ruborg/passbolt.rb +9 -2
 - data/lib/ruborg/repository.rb +26 -4
 - data/lib/ruborg/version.rb +1 -1
 - data/ruborg.gemspec +46 -0
 - data/ruborg.yml.example +1 -0
 - metadata +4 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 53e7193db767d8d7c217f89a4af6e7b4b4e18cdcc38cf0a8dff138767b561c10
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 25c0232d3e86628d9ffb350f1d85e08f71ca032e72183e8d592108533ef2bc51
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 6149c0535369f3f3b8f9829985fe6fa47777d0e2a6bcaf87630044bb7d7d2426be02ab104c87b50bc309352f9bdb80cad123e1549fc7c941dfe60b052840c95e
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: c0b036527fe8a70f526eebf07173f740d45fb88cd1fec3cd67a70b7331d7f806346d42b51217eefe4db2e8a8a7257f378a902c7711de657d9ef1603a460aaf46
         
     | 
    
        data/.ruby-version
    ADDED
    
    | 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            3.2.9
         
     | 
    
        data/CHANGELOG.md
    CHANGED
    
    | 
         @@ -7,6 +7,73 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 
     | 
|
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
            ## [Unreleased]
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
      
 10 
     | 
    
         
            +
            ## [0.6.1] - 2025-10-08
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            ### Added
         
     | 
| 
      
 13 
     | 
    
         
            +
            - **Enhanced Configuration Validation**: Comprehensive validation system to catch configuration errors early
         
     | 
| 
      
 14 
     | 
    
         
            +
              - **Unknown Key Detection**: Detects typos and invalid configuration keys at all levels (global, repository, sources, retention, passbolt, borg_options)
         
     | 
| 
      
 15 
     | 
    
         
            +
              - **Retention Policy Validation**: Validates retention policy structure and values
         
     | 
| 
      
 16 
     | 
    
         
            +
                - Integer fields (keep_hourly, keep_daily, etc.) must be non-negative integers
         
     | 
| 
      
 17 
     | 
    
         
            +
                - Time-based fields (keep_within, keep_files_modified_within) must use correct format (e.g., "7d", "30d")
         
     | 
| 
      
 18 
     | 
    
         
            +
                - Validates time format with h/d/w/m/y suffixes
         
     | 
| 
      
 19 
     | 
    
         
            +
                - Rejects empty retention policies
         
     | 
| 
      
 20 
     | 
    
         
            +
                - Detects unknown retention keys
         
     | 
| 
      
 21 
     | 
    
         
            +
              - **Passbolt Configuration Validation**: Validates passbolt config structure
         
     | 
| 
      
 22 
     | 
    
         
            +
                - Requires non-empty `resource_id` string
         
     | 
| 
      
 23 
     | 
    
         
            +
                - Type validation for resource_id field
         
     | 
| 
      
 24 
     | 
    
         
            +
                - Detects unknown passbolt keys
         
     | 
| 
      
 25 
     | 
    
         
            +
              - **Retention Mode Validation**: Validates `retention_mode` values (must be "standard" or "per_file")
         
     | 
| 
      
 26 
     | 
    
         
            +
              - **Source Validation**: Validates source structure (name, paths, exclude fields)
         
     | 
| 
      
 27 
     | 
    
         
            +
            - **Comprehensive Logging**: Added logging throughout backup, restore, and deletion operations
         
     | 
| 
      
 28 
     | 
    
         
            +
              - Repository operations (initialization, pruning, archive management)
         
     | 
| 
      
 29 
     | 
    
         
            +
              - Backup operations (file counts, progress in per-file mode)
         
     | 
| 
      
 30 
     | 
    
         
            +
              - Restore operations (extraction start/completion)
         
     | 
| 
      
 31 
     | 
    
         
            +
              - Source file deletion tracking (with `--remove-source`)
         
     | 
| 
      
 32 
     | 
    
         
            +
              - Passbolt integration events (resource ID logged, never passwords)
         
     | 
| 
      
 33 
     | 
    
         
            +
              - All sensitive data (passwords, encryption keys) protected from logs
         
     | 
| 
      
 34 
     | 
    
         
            +
            - **Enhanced Test Suite**: Expanded test coverage to 220 examples (67 new tests added)
         
     | 
| 
      
 35 
     | 
    
         
            +
              - 23 new configuration validation tests
         
     | 
| 
      
 36 
     | 
    
         
            +
              - 28 new logging integration tests
         
     | 
| 
      
 37 
     | 
    
         
            +
              - 10 new CLI validation tests
         
     | 
| 
      
 38 
     | 
    
         
            +
              - 6 new type checking tests for boolean configurations
         
     | 
| 
      
 39 
     | 
    
         
            +
              - All tests passing with 0 failures
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
            ### Changed
         
     | 
| 
      
 42 
     | 
    
         
            +
            - `global_settings` now includes `borg_path` (previously was in whitelist but not propagated)
         
     | 
| 
      
 43 
     | 
    
         
            +
            - Validation errors are collected and reported together for better user experience
         
     | 
| 
      
 44 
     | 
    
         
            +
            - All validation runs automatically on configuration load
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            ### Fixed
         
     | 
| 
      
 47 
     | 
    
         
            +
            - **Configuration Consistency**: Fixed inconsistency where `borg_path` was allowed in VALID_GLOBAL_KEYS but not returned by `global_settings` method
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
            ## [0.6.0] - 2025-10-08
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            ### Added
         
     | 
| 
      
 52 
     | 
    
         
            +
            - **Configuration Validation Command**: New `ruborg validate` command to check configuration files for type errors
         
     | 
| 
      
 53 
     | 
    
         
            +
            - **Automatic Schema Validation**: All commands now validate configuration on startup to catch errors early
         
     | 
| 
      
 54 
     | 
    
         
            +
            - **Strict Boolean Type Checking**: All boolean config values (auto_init, auto_prune, allow_remove_source, etc.) now require actual boolean types
         
     | 
| 
      
 55 
     | 
    
         
            +
              - Prevents type confusion attacks where strings like `'true'` or `"false"` bypass security checks
         
     | 
| 
      
 56 
     | 
    
         
            +
              - Clear error messages show actual type vs expected type
         
     | 
| 
      
 57 
     | 
    
         
            +
              - Validation runs automatically on config load
         
     | 
| 
      
 58 
     | 
    
         
            +
            - Comprehensive validation test suite (10 new test cases)
         
     | 
| 
      
 59 
     | 
    
         
            +
            - Documentation for configuration validation in README
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
            ### Changed
         
     | 
| 
      
 62 
     | 
    
         
            +
            - Boolean configuration values now use strict type checking throughout the codebase
         
     | 
| 
      
 63 
     | 
    
         
            +
              - `auto_init`: only boolean `true` enables, everything else disables
         
     | 
| 
      
 64 
     | 
    
         
            +
              - `auto_prune`: only boolean `true` enables, everything else disables
         
     | 
| 
      
 65 
     | 
    
         
            +
              - `allow_remove_source`: strict checking - only `TrueClass` enables (security-critical)
         
     | 
| 
      
 66 
     | 
    
         
            +
              - `allow_relocated_repo`: permissive normalization - only `false` disables (backward compatible)
         
     | 
| 
      
 67 
     | 
    
         
            +
              - `allow_unencrypted_repo`: permissive normalization - only `false` disables (backward compatible)
         
     | 
| 
      
 68 
     | 
    
         
            +
            - Config class now validates schema by default (can be disabled with `validate_types: false`)
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
            ### Security
         
     | 
| 
      
 71 
     | 
    
         
            +
            - **Type Confusion Protection (CWE-843)**: Strict boolean type checking prevents configuration bypass attacks
         
     | 
| 
      
 72 
     | 
    
         
            +
              - Before: `allow_remove_source: 'false'` (string) would be truthy and enable deletion
         
     | 
| 
      
 73 
     | 
    
         
            +
              - After: Only `allow_remove_source: true` (boolean) enables the dangerous operation
         
     | 
| 
      
 74 
     | 
    
         
            +
            - Enhanced error messages guide users to fix type errors correctly
         
     | 
| 
      
 75 
     | 
    
         
            +
            - SECURITY.md updated with type confusion findings and mitigations
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
       10 
77 
     | 
    
         
             
            ## [0.5.0] - 2025-10-08
         
     | 
| 
       11 
78 
     | 
    
         | 
| 
       12 
79 
     | 
    
         
             
            ### Added
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -17,7 +17,7 @@ A friendly Ruby frontend for [Borg Backup](https://www.borgbackup.org/). Ruborg 
     | 
|
| 
       17 
17 
     | 
    
         
             
            - 📊 **Logging** - Comprehensive logging with daily rotation
         
     | 
| 
       18 
18 
     | 
    
         
             
            - 🗄️ **Multi-Repository** - Manage multiple backup repositories with different sources
         
     | 
| 
       19 
19 
     | 
    
         
             
            - 🔄 **Auto-initialization** - Automatically initialize repositories on first use
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
      
 20 
     | 
    
         
            +
            - ⏰ **Retention Policies** - Configure backup retention (hourly, daily, weekly, monthly, yearly)
         
     | 
| 
       21 
21 
     | 
    
         
             
            - 🗑️ **Automatic Pruning** - Automatically remove old backups based on retention policies
         
     | 
| 
       22 
22 
     | 
    
         
             
            - 📁 **Per-File Backup Mode** - NEW! Backup each file as a separate archive with metadata-based retention
         
     | 
| 
       23 
23 
     | 
    
         
             
            - 🕒 **File Metadata Retention** - NEW! Prune based on file modification time, works even after files are deleted
         
     | 
| 
         @@ -25,7 +25,7 @@ e- ⏰ **Retention Policies** - Configure backup retention (hourly, daily, weekl 
     | 
|
| 
       25 
25 
     | 
    
         
             
            - 📈 **Summary View** - Quick overview of all repositories and their configurations
         
     | 
| 
       26 
26 
     | 
    
         
             
            - 🔧 **Custom Borg Path** - Support for custom Borg executable paths per repository
         
     | 
| 
       27 
27 
     | 
    
         
             
            - 🏠 **Hostname Validation** - NEW! Restrict backups to specific hosts (global or per-repository)
         
     | 
| 
       28 
     | 
    
         
            -
            - ✅ **Well-tested** - Comprehensive test suite with RSpec ( 
     | 
| 
      
 28 
     | 
    
         
            +
            - ✅ **Well-tested** - Comprehensive test suite with RSpec (220 examples, 0 failures)
         
     | 
| 
       29 
29 
     | 
    
         
             
            - 🔒 **Security-focused** - Path validation, safe YAML loading, command injection protection
         
     | 
| 
       30 
30 
     | 
    
         | 
| 
       31 
31 
     | 
    
         
             
            ## Prerequisites
         
     | 
| 
         @@ -162,15 +162,173 @@ repositories: 
     | 
|
| 
       162 
162 
     | 
    
         
             
            ```
         
     | 
| 
       163 
163 
     | 
    
         | 
| 
       164 
164 
     | 
    
         
             
            **Configuration Features:**
         
     | 
| 
      
 165 
     | 
    
         
            +
            - **Automatic Type Validation**: Configuration is validated on startup to catch type errors early
         
     | 
| 
      
 166 
     | 
    
         
            +
            - **Validation Command**: Run `ruborg validate` to check configuration files for errors
         
     | 
| 
       165 
167 
     | 
    
         
             
            - **Descriptions**: Add `description` field to document each repository's purpose
         
     | 
| 
       166 
168 
     | 
    
         
             
            - **Hostname Validation**: Optional `hostname` field to restrict backups to specific hosts (global or per-repository)
         
     | 
| 
       167 
     | 
    
         
            -
            - ** 
     | 
| 
       168 
     | 
    
         
            -
            - ** 
     | 
| 
      
 169 
     | 
    
         
            +
            - **Source Deletion Safety**: `allow_remove_source` flag to explicitly enable `--remove-source` option (default: disabled)
         
     | 
| 
      
 170 
     | 
    
         
            +
            - **Type-Safe Booleans**: Strict boolean validation prevents configuration errors (must use `true`/`false`, not strings)
         
     | 
| 
      
 171 
     | 
    
         
            +
            - **Global Settings**: Hostname, compression, encryption, auto_init, allow_remove_source, log_file, borg_path, borg_options, and retention apply to all repositories
         
     | 
| 
      
 172 
     | 
    
         
            +
            - **Per-Repository Overrides**: Any global setting can be overridden at the repository level (including hostname, allow_remove_source, and custom borg_path)
         
     | 
| 
       169 
173 
     | 
    
         
             
            - **Custom Borg Path**: Specify a custom Borg executable path if borg is not in PATH or to use a specific version
         
     | 
| 
       170 
174 
     | 
    
         
             
            - **Retention Policies**: Define how many backups to keep (hourly, daily, weekly, monthly, yearly)
         
     | 
| 
       171 
175 
     | 
    
         
             
            - **Multiple Sources**: Each repository can have multiple backup sources with their own exclude patterns
         
     | 
| 
       172 
176 
     | 
    
         
             
            - **Flexible Organization**: Organize backups by type (documents, databases, media) with different policies
         
     | 
| 
       173 
177 
     | 
    
         | 
| 
      
 178 
     | 
    
         
            +
            ## Configuration Validation
         
     | 
| 
      
 179 
     | 
    
         
            +
             
     | 
| 
      
 180 
     | 
    
         
            +
            Ruborg automatically validates your configuration on startup. All commands check for type errors and structural issues before executing.
         
     | 
| 
      
 181 
     | 
    
         
            +
             
     | 
| 
      
 182 
     | 
    
         
            +
            ### Validate Configuration
         
     | 
| 
      
 183 
     | 
    
         
            +
             
     | 
| 
      
 184 
     | 
    
         
            +
            Check your configuration file for errors:
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
            ```bash
         
     | 
| 
      
 187 
     | 
    
         
            +
            ruborg validate --config ruborg.yml
         
     | 
| 
      
 188 
     | 
    
         
            +
            ```
         
     | 
| 
      
 189 
     | 
    
         
            +
             
     | 
| 
      
 190 
     | 
    
         
            +
            **Validation checks:**
         
     | 
| 
      
 191 
     | 
    
         
            +
            - **Unknown configuration keys**: Detects typos and invalid keys at all levels (catches `auto_prun` vs `auto_prune`)
         
     | 
| 
      
 192 
     | 
    
         
            +
            - **Boolean types**: Must be `true` or `false`, not strings like `'true'`
         
     | 
| 
      
 193 
     | 
    
         
            +
            - **Retention policies**: Validates structure and values
         
     | 
| 
      
 194 
     | 
    
         
            +
              - Integer fields (keep_hourly, keep_daily, etc.) must be non-negative integers
         
     | 
| 
      
 195 
     | 
    
         
            +
              - Time-based fields (keep_within, keep_files_modified_within) must use format like "7d", "30d"
         
     | 
| 
      
 196 
     | 
    
         
            +
              - Rejects empty retention policies
         
     | 
| 
      
 197 
     | 
    
         
            +
              - Detects unknown retention keys
         
     | 
| 
      
 198 
     | 
    
         
            +
            - **Passbolt configuration**: Validates resource_id is non-empty string
         
     | 
| 
      
 199 
     | 
    
         
            +
            - **Retention mode**: Must be "standard" or "per_file"
         
     | 
| 
      
 200 
     | 
    
         
            +
            - **Compression values**: Must be one of: lz4, zstd, zlib, lzma, none
         
     | 
| 
      
 201 
     | 
    
         
            +
            - **Encryption modes**: Must be valid Borg encryption mode
         
     | 
| 
      
 202 
     | 
    
         
            +
            - **Repository structure**: Required fields (name, path, sources)
         
     | 
| 
      
 203 
     | 
    
         
            +
            - **Source structure**: Required fields (name, paths), validates exclude arrays
         
     | 
| 
      
 204 
     | 
    
         
            +
            - **Borg options**: Validates allow_relocated_repo and allow_unencrypted_repo
         
     | 
| 
      
 205 
     | 
    
         
            +
             
     | 
| 
      
 206 
     | 
    
         
            +
            **Example validation output:**
         
     | 
| 
      
 207 
     | 
    
         
            +
             
     | 
| 
      
 208 
     | 
    
         
            +
            ```
         
     | 
| 
      
 209 
     | 
    
         
            +
            ✓ Configuration is valid
         
     | 
| 
      
 210 
     | 
    
         
            +
              No type errors or warnings found
         
     | 
| 
      
 211 
     | 
    
         
            +
            ```
         
     | 
| 
      
 212 
     | 
    
         
            +
             
     | 
| 
      
 213 
     | 
    
         
            +
            Or with errors:
         
     | 
| 
      
 214 
     | 
    
         
            +
             
     | 
| 
      
 215 
     | 
    
         
            +
            ```
         
     | 
| 
      
 216 
     | 
    
         
            +
            ❌ ERRORS FOUND (2):
         
     | 
| 
      
 217 
     | 
    
         
            +
              - global/auto_init: must be boolean (true or false), got String: "true"
         
     | 
| 
      
 218 
     | 
    
         
            +
              - test-repo/allow_remove_source: must be boolean (true or false), got Integer: 1
         
     | 
| 
      
 219 
     | 
    
         
            +
             
     | 
| 
      
 220 
     | 
    
         
            +
            Configuration has errors that must be fixed.
         
     | 
| 
      
 221 
     | 
    
         
            +
            ```
         
     | 
| 
      
 222 
     | 
    
         
            +
             
     | 
| 
      
 223 
     | 
    
         
            +
            ## Logging
         
     | 
| 
      
 224 
     | 
    
         
            +
             
     | 
| 
      
 225 
     | 
    
         
            +
            Ruborg v0.6.1 includes comprehensive logging to help you track backup operations, troubleshoot issues, and maintain audit trails. Logs are written to `~/.ruborg/logs/ruborg.log` by default, or to a custom location specified in your configuration.
         
     | 
| 
      
 226 
     | 
    
         
            +
             
     | 
| 
      
 227 
     | 
    
         
            +
            ### What Gets Logged
         
     | 
| 
      
 228 
     | 
    
         
            +
             
     | 
| 
      
 229 
     | 
    
         
            +
            Ruborg logs operational information at various levels to help you monitor and debug backup operations:
         
     | 
| 
      
 230 
     | 
    
         
            +
             
     | 
| 
      
 231 
     | 
    
         
            +
            #### Repository Operations
         
     | 
| 
      
 232 
     | 
    
         
            +
            - Repository creation and initialization
         
     | 
| 
      
 233 
     | 
    
         
            +
            - Repository path and encryption mode
         
     | 
| 
      
 234 
     | 
    
         
            +
            - Per-file pruning operations (archive counts, file modification times)
         
     | 
| 
      
 235 
     | 
    
         
            +
            - Archive deletion during pruning
         
     | 
| 
      
 236 
     | 
    
         
            +
             
     | 
| 
      
 237 
     | 
    
         
            +
            #### Backup Operations
         
     | 
| 
      
 238 
     | 
    
         
            +
            - Number of files found for backup (per-file mode)
         
     | 
| 
      
 239 
     | 
    
         
            +
            - Individual file backup progress (per-file mode)
         
     | 
| 
      
 240 
     | 
    
         
            +
            - Backup completion status
         
     | 
| 
      
 241 
     | 
    
         
            +
            - Archive names (user-provided or auto-generated)
         
     | 
| 
      
 242 
     | 
    
         
            +
             
     | 
| 
      
 243 
     | 
    
         
            +
            #### Restore Operations
         
     | 
| 
      
 244 
     | 
    
         
            +
            - Archive extraction start (archive name, destination path)
         
     | 
| 
      
 245 
     | 
    
         
            +
            - Specific paths being restored (if using `--path` option)
         
     | 
| 
      
 246 
     | 
    
         
            +
            - Extraction completion status
         
     | 
| 
      
 247 
     | 
    
         
            +
             
     | 
| 
      
 248 
     | 
    
         
            +
            #### Source File Deletion (when using `--remove-source`)
         
     | 
| 
      
 249 
     | 
    
         
            +
            - Start of source file removal process
         
     | 
| 
      
 250 
     | 
    
         
            +
            - Each file/directory being removed (with full resolved path)
         
     | 
| 
      
 251 
     | 
    
         
            +
            - Warnings for non-existent or missing paths
         
     | 
| 
      
 252 
     | 
    
         
            +
            - Errors when attempting to delete system directories (with path)
         
     | 
| 
      
 253 
     | 
    
         
            +
            - Count of items successfully removed
         
     | 
| 
      
 254 
     | 
    
         
            +
             
     | 
| 
      
 255 
     | 
    
         
            +
            #### Passbolt Integration
         
     | 
| 
      
 256 
     | 
    
         
            +
            - Password retrieval start (includes Passbolt resource UUID)
         
     | 
| 
      
 257 
     | 
    
         
            +
            - Password retrieval failures (includes resource UUID)
         
     | 
| 
      
 258 
     | 
    
         
            +
             
     | 
| 
      
 259 
     | 
    
         
            +
            ### What Is NOT Logged
         
     | 
| 
      
 260 
     | 
    
         
            +
             
     | 
| 
      
 261 
     | 
    
         
            +
            To protect sensitive information, the following are **never logged**:
         
     | 
| 
      
 262 
     | 
    
         
            +
             
     | 
| 
      
 263 
     | 
    
         
            +
            - ✅ **Passwords and passphrases** - Neither from command line nor from Passbolt
         
     | 
| 
      
 264 
     | 
    
         
            +
            - ✅ **File contents** - Only file paths and metadata
         
     | 
| 
      
 265 
     | 
    
         
            +
            - ✅ **Encryption keys** - Repository encryption passphrases are never written to logs
         
     | 
| 
      
 266 
     | 
    
         
            +
            - ✅ **Passbolt passwords** - Only resource IDs (UUIDs) are logged, never the actual passwords retrieved
         
     | 
| 
      
 267 
     | 
    
         
            +
             
     | 
| 
      
 268 
     | 
    
         
            +
            ### Log Levels
         
     | 
| 
      
 269 
     | 
    
         
            +
             
     | 
| 
      
 270 
     | 
    
         
            +
            - **INFO**: Normal operation events (backups, restores, deletions)
         
     | 
| 
      
 271 
     | 
    
         
            +
            - **WARN**: Non-critical issues (missing paths, skipped operations)
         
     | 
| 
      
 272 
     | 
    
         
            +
            - **ERROR**: Critical errors (system path deletion attempts, command failures)
         
     | 
| 
      
 273 
     | 
    
         
            +
            - **DEBUG**: Detailed information for troubleshooting (requires DEBUG level configuration)
         
     | 
| 
      
 274 
     | 
    
         
            +
             
     | 
| 
      
 275 
     | 
    
         
            +
            ### Configuring Logging
         
     | 
| 
      
 276 
     | 
    
         
            +
             
     | 
| 
      
 277 
     | 
    
         
            +
            ```yaml
         
     | 
| 
      
 278 
     | 
    
         
            +
            # Log to default location: ~/.ruborg/logs/ruborg.log
         
     | 
| 
      
 279 
     | 
    
         
            +
            log_file: default
         
     | 
| 
      
 280 
     | 
    
         
            +
             
     | 
| 
      
 281 
     | 
    
         
            +
            # OR custom log file path
         
     | 
| 
      
 282 
     | 
    
         
            +
            log_file: /var/log/ruborg/backup.log
         
     | 
| 
      
 283 
     | 
    
         
            +
             
     | 
| 
      
 284 
     | 
    
         
            +
            # OR disable file logging (stdout only)
         
     | 
| 
      
 285 
     | 
    
         
            +
            log_file: stdout
         
     | 
| 
      
 286 
     | 
    
         
            +
            ```
         
     | 
| 
      
 287 
     | 
    
         
            +
             
     | 
| 
      
 288 
     | 
    
         
            +
            You can also override the log file location using the `--log` command-line option:
         
     | 
| 
      
 289 
     | 
    
         
            +
             
     | 
| 
      
 290 
     | 
    
         
            +
            ```bash
         
     | 
| 
      
 291 
     | 
    
         
            +
            ruborg backup --repository documents --log /tmp/debug.log
         
     | 
| 
      
 292 
     | 
    
         
            +
            ```
         
     | 
| 
      
 293 
     | 
    
         
            +
             
     | 
| 
      
 294 
     | 
    
         
            +
            ### Log Security Considerations
         
     | 
| 
      
 295 
     | 
    
         
            +
             
     | 
| 
      
 296 
     | 
    
         
            +
            - **File Paths**: Logs contain file and directory paths being backed up. Secure your log files with appropriate permissions (recommended: `chmod 600` or `640`)
         
     | 
| 
      
 297 
     | 
    
         
            +
            - **Passbolt Resource IDs**: UUID identifiers for Passbolt resources are logged. These are safe to log as they are unguessable and don't expose credentials, but logs should still be protected
         
     | 
| 
      
 298 
     | 
    
         
            +
            - **Archive Names**: User-provided or auto-generated archive names are logged for audit purposes
         
     | 
| 
      
 299 
     | 
    
         
            +
            - **System Paths**: When `--remove-source` attempts to delete system directories, the full path is logged in error messages for security auditing
         
     | 
| 
      
 300 
     | 
    
         
            +
             
     | 
| 
      
 301 
     | 
    
         
            +
            ### Best Practices
         
     | 
| 
      
 302 
     | 
    
         
            +
             
     | 
| 
      
 303 
     | 
    
         
            +
            1. **Secure Log Files**: Set restrictive permissions on log files
         
     | 
| 
      
 304 
     | 
    
         
            +
               ```bash
         
     | 
| 
      
 305 
     | 
    
         
            +
               chmod 600 ~/.ruborg/logs/ruborg.log
         
     | 
| 
      
 306 
     | 
    
         
            +
               ```
         
     | 
| 
      
 307 
     | 
    
         
            +
             
     | 
| 
      
 308 
     | 
    
         
            +
            2. **Log Rotation**: Configure log rotation to prevent logs from consuming excessive disk space
         
     | 
| 
      
 309 
     | 
    
         
            +
               ```bash
         
     | 
| 
      
 310 
     | 
    
         
            +
               # Example logrotate configuration
         
     | 
| 
      
 311 
     | 
    
         
            +
               /home/user/.ruborg/logs/ruborg.log {
         
     | 
| 
      
 312 
     | 
    
         
            +
                   weekly
         
     | 
| 
      
 313 
     | 
    
         
            +
                   rotate 4
         
     | 
| 
      
 314 
     | 
    
         
            +
                   compress
         
     | 
| 
      
 315 
     | 
    
         
            +
                   missingok
         
     | 
| 
      
 316 
     | 
    
         
            +
                   notifempty
         
     | 
| 
      
 317 
     | 
    
         
            +
               }
         
     | 
| 
      
 318 
     | 
    
         
            +
               ```
         
     | 
| 
      
 319 
     | 
    
         
            +
             
     | 
| 
      
 320 
     | 
    
         
            +
            3. **Monitoring**: Review logs regularly to detect:
         
     | 
| 
      
 321 
     | 
    
         
            +
               - Failed backup operations
         
     | 
| 
      
 322 
     | 
    
         
            +
               - Unauthorized deletion attempts
         
     | 
| 
      
 323 
     | 
    
         
            +
               - Passbolt password retrieval failures
         
     | 
| 
      
 324 
     | 
    
         
            +
               - Unexpected file paths
         
     | 
| 
      
 325 
     | 
    
         
            +
             
     | 
| 
      
 326 
     | 
    
         
            +
            4. **Audit Trail**: Logs provide an audit trail for compliance purposes:
         
     | 
| 
      
 327 
     | 
    
         
            +
               - What was backed up and when
         
     | 
| 
      
 328 
     | 
    
         
            +
               - What was restored and where
         
     | 
| 
      
 329 
     | 
    
         
            +
               - What was deleted (with `--remove-source`)
         
     | 
| 
      
 330 
     | 
    
         
            +
               - Any errors or security-related events
         
     | 
| 
      
 331 
     | 
    
         
            +
             
     | 
| 
       174 
332 
     | 
    
         
             
            ## Usage
         
     | 
| 
       175 
333 
     | 
    
         | 
| 
       176 
334 
     | 
    
         
             
            ### Initialize a Repository
         
     | 
| 
         @@ -198,10 +356,48 @@ ruborg backup --repository databases --name "db-backup-2025-10-05" 
     | 
|
| 
       198 
356 
     | 
    
         
             
            # Using custom configuration file
         
     | 
| 
       199 
357 
     | 
    
         
             
            ruborg backup --config /path/to/config.yml --repository documents
         
     | 
| 
       200 
358 
     | 
    
         | 
| 
       201 
     | 
    
         
            -
            # Remove source files after successful backup
         
     | 
| 
      
 359 
     | 
    
         
            +
            # Remove source files after successful backup (requires allow_remove_source: true)
         
     | 
| 
       202 
360 
     | 
    
         
             
            ruborg backup --repository documents --remove-source
         
     | 
| 
       203 
361 
     | 
    
         
             
            ```
         
     | 
| 
       204 
362 
     | 
    
         | 
| 
      
 363 
     | 
    
         
            +
            **IMPORTANT: Source File Deletion Safety**
         
     | 
| 
      
 364 
     | 
    
         
            +
             
     | 
| 
      
 365 
     | 
    
         
            +
            The `--remove-source` option is disabled by default for safety. To use it, you must explicitly enable it in your configuration:
         
     | 
| 
      
 366 
     | 
    
         
            +
             
     | 
| 
      
 367 
     | 
    
         
            +
            ```yaml
         
     | 
| 
      
 368 
     | 
    
         
            +
            # Global setting - applies to all repositories
         
     | 
| 
      
 369 
     | 
    
         
            +
            allow_remove_source: true
         
     | 
| 
      
 370 
     | 
    
         
            +
             
     | 
| 
      
 371 
     | 
    
         
            +
            # OR per-repository setting
         
     | 
| 
      
 372 
     | 
    
         
            +
            repositories:
         
     | 
| 
      
 373 
     | 
    
         
            +
              - name: temp-backups
         
     | 
| 
      
 374 
     | 
    
         
            +
                allow_remove_source: true  # Only for this repository
         
     | 
| 
      
 375 
     | 
    
         
            +
                ...
         
     | 
| 
      
 376 
     | 
    
         
            +
            ```
         
     | 
| 
      
 377 
     | 
    
         
            +
             
     | 
| 
      
 378 
     | 
    
         
            +
            **⚠️ TYPE SAFETY WARNING:** The value MUST be a boolean `true`, not a string:
         
     | 
| 
      
 379 
     | 
    
         
            +
             
     | 
| 
      
 380 
     | 
    
         
            +
            ```yaml
         
     | 
| 
      
 381 
     | 
    
         
            +
            # ✅ CORRECT - Boolean true
         
     | 
| 
      
 382 
     | 
    
         
            +
            allow_remove_source: true
         
     | 
| 
      
 383 
     | 
    
         
            +
             
     | 
| 
      
 384 
     | 
    
         
            +
            # ❌ WRONG - String 'true' (will be rejected)
         
     | 
| 
      
 385 
     | 
    
         
            +
            allow_remove_source: 'true'
         
     | 
| 
      
 386 
     | 
    
         
            +
            allow_remove_source: "true"
         
     | 
| 
      
 387 
     | 
    
         
            +
             
     | 
| 
      
 388 
     | 
    
         
            +
            # ❌ WRONG - Other truthy values (will be rejected)
         
     | 
| 
      
 389 
     | 
    
         
            +
            allow_remove_source: 1
         
     | 
| 
      
 390 
     | 
    
         
            +
            allow_remove_source: yes
         
     | 
| 
      
 391 
     | 
    
         
            +
            ```
         
     | 
| 
      
 392 
     | 
    
         
            +
             
     | 
| 
      
 393 
     | 
    
         
            +
            Ruborg uses strict type checking to prevent configuration errors. Only the boolean value `true` (unquoted) will enable source deletion. Any other value, including string `'true'` or `"true"`, will be rejected with a detailed error message showing the actual type received.
         
     | 
| 
      
 394 
     | 
    
         
            +
             
     | 
| 
      
 395 
     | 
    
         
            +
            Without `allow_remove_source: true` configured, using `--remove-source` will result in an error:
         
     | 
| 
      
 396 
     | 
    
         
            +
            ```
         
     | 
| 
      
 397 
     | 
    
         
            +
            Error: Cannot use --remove-source: 'allow_remove_source' must be true (boolean).
         
     | 
| 
      
 398 
     | 
    
         
            +
            Current value: "true" (String). Set 'allow_remove_source: true' in configuration.
         
     | 
| 
      
 399 
     | 
    
         
            +
            ```
         
     | 
| 
      
 400 
     | 
    
         
            +
             
     | 
| 
       205 
401 
     | 
    
         
             
            ### List Archives
         
     | 
| 
       206 
402 
     | 
    
         | 
| 
       207 
403 
     | 
    
         
             
            ```bash
         
     | 
| 
         @@ -272,31 +468,6 @@ Borg version: 1.2.8 
     | 
|
| 
       272 
468 
     | 
    
         
             
                Please upgrade Borg or migrate the repository
         
     | 
| 
       273 
469 
     | 
    
         
             
            ```
         
     | 
| 
       274 
470 
     | 
    
         | 
| 
       275 
     | 
    
         
            -
            ## Logging
         
     | 
| 
       276 
     | 
    
         
            -
             
     | 
| 
       277 
     | 
    
         
            -
            Ruborg automatically logs all operations with daily rotation. Log file location priority:
         
     | 
| 
       278 
     | 
    
         
            -
             
     | 
| 
       279 
     | 
    
         
            -
            1. **CLI option** (highest priority): `--log /path/to/custom.log`
         
     | 
| 
       280 
     | 
    
         
            -
            2. **Config file**: `log_file: /path/to/log.log`
         
     | 
| 
       281 
     | 
    
         
            -
            3. **Default**: `~/.ruborg/logs/ruborg.log`
         
     | 
| 
       282 
     | 
    
         
            -
             
     | 
| 
       283 
     | 
    
         
            -
            **Examples:**
         
     | 
| 
       284 
     | 
    
         
            -
             
     | 
| 
       285 
     | 
    
         
            -
            ```bash
         
     | 
| 
       286 
     | 
    
         
            -
            # Use CLI option (overrides config)
         
     | 
| 
       287 
     | 
    
         
            -
            ruborg backup --log /var/log/ruborg.log
         
     | 
| 
       288 
     | 
    
         
            -
             
     | 
| 
       289 
     | 
    
         
            -
            # Or set in config file
         
     | 
| 
       290 
     | 
    
         
            -
            log_file: /var/log/ruborg.log
         
     | 
| 
       291 
     | 
    
         
            -
            ```
         
     | 
| 
       292 
     | 
    
         
            -
             
     | 
| 
       293 
     | 
    
         
            -
            **Logs include:**
         
     | 
| 
       294 
     | 
    
         
            -
            - Operation start/completion timestamps
         
     | 
| 
       295 
     | 
    
         
            -
            - Paths being backed up
         
     | 
| 
       296 
     | 
    
         
            -
            - Archive names created
         
     | 
| 
       297 
     | 
    
         
            -
            - Success and error messages
         
     | 
| 
       298 
     | 
    
         
            -
            - Source file removal actions
         
     | 
| 
       299 
     | 
    
         
            -
             
     | 
| 
       300 
471 
     | 
    
         
             
            ## Passbolt Integration
         
     | 
| 
       301 
472 
     | 
    
         | 
| 
       302 
473 
     | 
    
         
             
            Ruborg can retrieve encryption passphrases from Passbolt using the Passbolt CLI:
         
     | 
| 
         @@ -437,6 +608,7 @@ See [SECURITY.md](SECURITY.md) for detailed security information and best practi 
     | 
|
| 
       437 
608 
     | 
    
         
             
            | Command | Description | Options |
         
     | 
| 
       438 
609 
     | 
    
         
             
            |---------|-------------|---------|
         
     | 
| 
       439 
610 
     | 
    
         
             
            | `init REPOSITORY` | Initialize a new Borg repository | `--passphrase`, `--passbolt-id`, `--log` |
         
     | 
| 
      
 611 
     | 
    
         
            +
            | `validate` | Validate configuration file for type errors | `--config`, `--log` |
         
     | 
| 
       440 
612 
     | 
    
         
             
            | `backup` | Create a backup using config file | `--config`, `--repository`, `--all`, `--name`, `--remove-source`, `--log` |
         
     | 
| 
       441 
613 
     | 
    
         
             
            | `list` | List all archives in repository | `--config`, `--repository`, `--log` |
         
     | 
| 
       442 
614 
     | 
    
         
             
            | `restore ARCHIVE` | Restore files from archive | `--config`, `--repository`, `--destination`, `--path`, `--log` |
         
     | 
    
        data/SECURITY.md
    CHANGED
    
    | 
         @@ -66,6 +66,81 @@ Ruborg implements several security measures to protect your backup operations: 
     | 
|
| 
       66 
66 
     | 
    
         
             
            - Integrated into development workflow
         
     | 
| 
       67 
67 
     | 
    
         
             
            - Run: `bundle exec bundle-audit check`
         
     | 
| 
       68 
68 
     | 
    
         | 
| 
      
 69 
     | 
    
         
            +
            ### 13. Boolean Type Safety (Type Confusion Protection)
         
     | 
| 
      
 70 
     | 
    
         
            +
            - **Critical safety flag validation** for `allow_remove_source` configuration
         
     | 
| 
      
 71 
     | 
    
         
            +
            - Uses strict type checking (`is_a?(TrueClass)`) to prevent type confusion attacks
         
     | 
| 
      
 72 
     | 
    
         
            +
            - Rejects truthy values like strings `'true'`, `"false"`, integers `1`, or `"yes"`
         
     | 
| 
      
 73 
     | 
    
         
            +
            - Only boolean `true` enables dangerous operations like `--remove-source`
         
     | 
| 
      
 74 
     | 
    
         
            +
            - Provides detailed error messages showing actual type received vs expected
         
     | 
| 
      
 75 
     | 
    
         
            +
            - Prevents configuration errors that could lead to unintended data loss
         
     | 
| 
      
 76 
     | 
    
         
            +
            - **CWE-843 Mitigation**: Protects against type confusion vulnerabilities
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
            ### 14. Logging Security (v0.6.1+)
         
     | 
| 
      
 79 
     | 
    
         
            +
            - **Comprehensive logging** of backup operations for audit trails and troubleshooting
         
     | 
| 
      
 80 
     | 
    
         
            +
            - **Sensitive data protection**: Passwords and passphrases are NEVER logged
         
     | 
| 
      
 81 
     | 
    
         
            +
            - **Safe operational logging**: File paths, archive names, and operation status are logged
         
     | 
| 
      
 82 
     | 
    
         
            +
            - **Passbolt resource IDs** (UUIDs) are logged but actual passwords are not
         
     | 
| 
      
 83 
     | 
    
         
            +
            - **System path protection**: Failed deletion attempts are logged with full paths for security auditing
         
     | 
| 
      
 84 
     | 
    
         
            +
            - **Log level support**: INFO, WARN, ERROR, DEBUG levels for appropriate detail
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
            #### What Is Logged (Safe)
         
     | 
| 
      
 87 
     | 
    
         
            +
            - Repository creation and initialization events
         
     | 
| 
      
 88 
     | 
    
         
            +
            - Backup operation start/completion with file counts
         
     | 
| 
      
 89 
     | 
    
         
            +
            - Individual file paths being backed up (per-file mode)
         
     | 
| 
      
 90 
     | 
    
         
            +
            - Archive names (user-provided or auto-generated)
         
     | 
| 
      
 91 
     | 
    
         
            +
            - Restore operations with destination paths
         
     | 
| 
      
 92 
     | 
    
         
            +
            - Source file deletion events (when using `--remove-source`)
         
     | 
| 
      
 93 
     | 
    
         
            +
            - Passbolt resource IDs (UUIDs) for password retrieval attempts
         
     | 
| 
      
 94 
     | 
    
         
            +
            - System path deletion refusals with full path (security audit)
         
     | 
| 
      
 95 
     | 
    
         
            +
            - Pruning operations with archive counts
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
            #### What Is NEVER Logged (Protected)
         
     | 
| 
      
 98 
     | 
    
         
            +
            - ✅ **Passwords and passphrases** - Neither from CLI nor Passbolt
         
     | 
| 
      
 99 
     | 
    
         
            +
            - ✅ **Encryption keys** - Repository encryption keys never written to logs
         
     | 
| 
      
 100 
     | 
    
         
            +
            - ✅ **Passbolt passwords** - Only resource UUIDs logged, not actual retrieved passwords
         
     | 
| 
      
 101 
     | 
    
         
            +
            - ✅ **File contents** - Only paths and metadata, never file contents
         
     | 
| 
      
 102 
     | 
    
         
            +
            - ✅ **Environment variables** with sensitive data
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
            #### Log Security Recommendations
         
     | 
| 
      
 105 
     | 
    
         
            +
            1. **Protect log files** with restrictive permissions:
         
     | 
| 
      
 106 
     | 
    
         
            +
               ```bash
         
     | 
| 
      
 107 
     | 
    
         
            +
               chmod 600 ~/.ruborg/logs/ruborg.log
         
     | 
| 
      
 108 
     | 
    
         
            +
               # Or for shared access with backup group:
         
     | 
| 
      
 109 
     | 
    
         
            +
               chmod 640 ~/.ruborg/logs/ruborg.log
         
     | 
| 
      
 110 
     | 
    
         
            +
               chown user:backup ~/.ruborg/logs/ruborg.log
         
     | 
| 
      
 111 
     | 
    
         
            +
               ```
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
            2. **Configure log rotation** to prevent log files from growing indefinitely:
         
     | 
| 
      
 114 
     | 
    
         
            +
               ```bash
         
     | 
| 
      
 115 
     | 
    
         
            +
               # /etc/logrotate.d/ruborg
         
     | 
| 
      
 116 
     | 
    
         
            +
               /home/user/.ruborg/logs/ruborg.log {
         
     | 
| 
      
 117 
     | 
    
         
            +
                   weekly
         
     | 
| 
      
 118 
     | 
    
         
            +
                   rotate 4
         
     | 
| 
      
 119 
     | 
    
         
            +
                   compress
         
     | 
| 
      
 120 
     | 
    
         
            +
                   missingok
         
     | 
| 
      
 121 
     | 
    
         
            +
                   notifempty
         
     | 
| 
      
 122 
     | 
    
         
            +
                   create 0600 user user
         
     | 
| 
      
 123 
     | 
    
         
            +
               }
         
     | 
| 
      
 124 
     | 
    
         
            +
               ```
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
            3. **Review logs regularly** for:
         
     | 
| 
      
 127 
     | 
    
         
            +
               - Failed backup or restore operations
         
     | 
| 
      
 128 
     | 
    
         
            +
               - Unauthorized `--remove-source` attempts
         
     | 
| 
      
 129 
     | 
    
         
            +
               - Passbolt password retrieval failures
         
     | 
| 
      
 130 
     | 
    
         
            +
               - System path deletion attempts (potential security issues)
         
     | 
| 
      
 131 
     | 
    
         
            +
               - Unexpected file paths being backed up
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
            4. **Secure log storage locations**:
         
     | 
| 
      
 134 
     | 
    
         
            +
               - Use absolute paths in `log_file` configuration
         
     | 
| 
      
 135 
     | 
    
         
            +
               - Avoid logging to world-readable directories
         
     | 
| 
      
 136 
     | 
    
         
            +
               - Consider logging to `/var/log/ruborg/` with proper permissions
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
            5. **Passbolt Resource IDs in Logs**:
         
     | 
| 
      
 139 
     | 
    
         
            +
               - Resource IDs (UUIDs) are logged for operational debugging
         
     | 
| 
      
 140 
     | 
    
         
            +
               - These are identifiers, not credentials - safe to log
         
     | 
| 
      
 141 
     | 
    
         
            +
               - They cannot be used to access Passbolt without proper authentication
         
     | 
| 
      
 142 
     | 
    
         
            +
               - Still, protect logs as they reveal which Passbolt resources are used
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
       69 
144 
     | 
    
         
             
            ## Security Best Practices
         
     | 
| 
       70 
145 
     | 
    
         | 
| 
       71 
146 
     | 
    
         
             
            ### When Using `--remove-source`
         
     | 
| 
         @@ -76,6 +151,16 @@ Ruborg implements several security measures to protect your backup operations: 
     | 
|
| 
       76 
151 
     | 
    
         
             
            2. **Never use on symlinks** to critical system directories
         
     | 
| 
       77 
152 
     | 
    
         
             
            3. **Verify backups** before using this flag in production
         
     | 
| 
       78 
153 
     | 
    
         
             
            4. **Use absolute paths** in configuration to avoid ambiguity
         
     | 
| 
      
 154 
     | 
    
         
            +
            5. **Use boolean values** for `allow_remove_source` - NEVER use quoted strings:
         
     | 
| 
      
 155 
     | 
    
         
            +
               ```yaml
         
     | 
| 
      
 156 
     | 
    
         
            +
               # ✅ CORRECT
         
     | 
| 
      
 157 
     | 
    
         
            +
               allow_remove_source: true
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
               # ❌ WRONG - Will be rejected
         
     | 
| 
      
 160 
     | 
    
         
            +
               allow_remove_source: 'true'
         
     | 
| 
      
 161 
     | 
    
         
            +
               allow_remove_source: "true"
         
     | 
| 
      
 162 
     | 
    
         
            +
               allow_remove_source: 1
         
     | 
| 
      
 163 
     | 
    
         
            +
               ```
         
     | 
| 
       79 
164 
     | 
    
         | 
| 
       80 
165 
     | 
    
         
             
            ### Configuration File Security
         
     | 
| 
       81 
166 
     | 
    
         | 
| 
         @@ -144,6 +229,29 @@ We will respond within 48 hours and work with you to address the issue. 
     | 
|
| 
       144 
229 
     | 
    
         | 
| 
       145 
230 
     | 
    
         
             
            ## Security Audit History
         
     | 
| 
       146 
231 
     | 
    
         | 
| 
      
 232 
     | 
    
         
            +
            - **v0.6.1** (2025-10-08): Enhanced logging with sensitive data protection
         
     | 
| 
      
 233 
     | 
    
         
            +
              - **NEW FEATURE**: Comprehensive logging for backup operations, restoration, and deletion
         
     | 
| 
      
 234 
     | 
    
         
            +
              - Passwords and passphrases are NEVER logged (neither CLI nor Passbolt passwords)
         
     | 
| 
      
 235 
     | 
    
         
            +
              - Passbolt resource IDs (UUIDs) logged for debugging - identifiers only, not credentials
         
     | 
| 
      
 236 
     | 
    
         
            +
              - File paths and archive names logged for audit trails
         
     | 
| 
      
 237 
     | 
    
         
            +
              - System path deletion attempts logged with full paths for security monitoring
         
     | 
| 
      
 238 
     | 
    
         
            +
              - Log levels: INFO, WARN, ERROR, DEBUG for appropriate detail
         
     | 
| 
      
 239 
     | 
    
         
            +
              - Documentation added for logging security best practices
         
     | 
| 
      
 240 
     | 
    
         
            +
              - Enhanced configuration validation with unknown key detection across all levels
         
     | 
| 
      
 241 
     | 
    
         
            +
             
     | 
| 
      
 242 
     | 
    
         
            +
            - **v0.6.0** (2025-10-08): Configuration validation and type confusion protection
         
     | 
| 
      
 243 
     | 
    
         
            +
              - **SECURITY FIX**: Implemented strict boolean type checking for `allow_remove_source`
         
     | 
| 
      
 244 
     | 
    
         
            +
              - Prevents type confusion attacks (CWE-843) where string values bypass safety checks
         
     | 
| 
      
 245 
     | 
    
         
            +
              - Added configuration validation command (`ruborg validate`) for proactive error detection
         
     | 
| 
      
 246 
     | 
    
         
            +
              - Automatic schema validation on config load catches type errors early
         
     | 
| 
      
 247 
     | 
    
         
            +
              - Added 10 comprehensive test cases for validation and type confusion scenarios
         
     | 
| 
      
 248 
     | 
    
         
            +
              - Enhanced error messages to show actual type vs expected type
         
     | 
| 
      
 249 
     | 
    
         
            +
              - Updated documentation with type safety warnings and examples
         
     | 
| 
      
 250 
     | 
    
         
            +
             
     | 
| 
      
 251 
     | 
    
         
            +
            - **v0.5.0** (2025-10-08): Hostname validation
         
     | 
| 
      
 252 
     | 
    
         
            +
              - Added hostname validation feature (optional global or per-repository)
         
     | 
| 
      
 253 
     | 
    
         
            +
              - Prevents accidental execution of backups on wrong machines
         
     | 
| 
      
 254 
     | 
    
         
            +
             
     | 
| 
       147 
255 
     | 
    
         
             
            - **v0.4.0** (2025-10-06): Complete command injection elimination
         
     | 
| 
       148 
256 
     | 
    
         
             
              - **CRITICAL**: Fixed all remaining command injection vulnerabilities in repository.rb
         
     | 
| 
       149 
257 
     | 
    
         
             
              - Replaced all backtick execution with Open3.capture3/capture2e methods
         
     | 
| 
         @@ -210,3 +318,5 @@ Before deploying ruborg in production: 
     | 
|
| 
       210 
318 
     | 
    
         
             
            - [ ] Configure borg_options for your security requirements
         
     | 
| 
       211 
319 
     | 
    
         
             
            - [ ] Use default archive names or sanitized custom names only
         
     | 
| 
       212 
320 
     | 
    
         
             
            - [ ] Ensure backup paths don't contain empty or nil values
         
     | 
| 
      
 321 
     | 
    
         
            +
            - [ ] Use boolean `true` (not strings) for `allow_remove_source` configuration
         
     | 
| 
      
 322 
     | 
    
         
            +
            - [ ] Configure hostname validation for multi-server environments
         
     | 
    
        data/exe/ruborg
    CHANGED
    
    
    
        data/lib/ruborg/backup.rb
    CHANGED
    
    | 
         @@ -3,11 +3,12 @@ 
     | 
|
| 
       3 
3 
     | 
    
         
             
            module Ruborg
         
     | 
| 
       4 
4 
     | 
    
         
             
              # Backup operations using Borg
         
     | 
| 
       5 
5 
     | 
    
         
             
              class Backup
         
     | 
| 
       6 
     | 
    
         
            -
                def initialize(repository, config:, retention_mode: "standard", repo_name: nil)
         
     | 
| 
      
 6 
     | 
    
         
            +
                def initialize(repository, config:, retention_mode: "standard", repo_name: nil, logger: nil)
         
     | 
| 
       7 
7 
     | 
    
         
             
                  @repository = repository
         
     | 
| 
       8 
8 
     | 
    
         
             
                  @config = config
         
     | 
| 
       9 
9 
     | 
    
         
             
                  @retention_mode = retention_mode
         
     | 
| 
       10 
10 
     | 
    
         
             
                  @repo_name = repo_name
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @logger = logger
         
     | 
| 
       11 
12 
     | 
    
         
             
                end
         
     | 
| 
       12 
13 
     | 
    
         | 
| 
       13 
14 
     | 
    
         
             
                def create(name: nil, remove_source: false)
         
     | 
| 
         @@ -37,19 +38,25 @@ module Ruborg 
     | 
|
| 
       37 
38 
     | 
    
         | 
| 
       38 
39 
     | 
    
         
             
                  raise BorgError, "No files found to backup" if files_to_backup.empty?
         
     | 
| 
       39 
40 
     | 
    
         | 
| 
      
 41 
     | 
    
         
            +
                  @logger&.info("Per-file mode: Found #{files_to_backup.size} file(s) to backup")
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
       40 
43 
     | 
    
         
             
                  timestamp = Time.now.strftime("%Y-%m-%d_%H-%M-%S")
         
     | 
| 
       41 
44 
     | 
    
         | 
| 
       42 
     | 
    
         
            -
                  files_to_backup. 
     | 
| 
      
 45 
     | 
    
         
            +
                  files_to_backup.each_with_index do |file_path, index|
         
     | 
| 
       43 
46 
     | 
    
         
             
                    # Generate hash-based archive name
         
     | 
| 
       44 
47 
     | 
    
         
             
                    path_hash = generate_path_hash(file_path)
         
     | 
| 
       45 
48 
     | 
    
         
             
                    archive_name = name_prefix || "#{@repo_name}-#{path_hash}-#{timestamp}"
         
     | 
| 
       46 
49 
     | 
    
         | 
| 
      
 50 
     | 
    
         
            +
                    @logger&.info("Backing up file #{index + 1}/#{files_to_backup.size}: #{file_path}")
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
       47 
52 
     | 
    
         
             
                    # Create archive for single file with original path as comment
         
     | 
| 
       48 
53 
     | 
    
         
             
                    cmd = build_per_file_create_command(archive_name, file_path)
         
     | 
| 
       49 
54 
     | 
    
         | 
| 
       50 
55 
     | 
    
         
             
                    execute_borg_command(cmd)
         
     | 
| 
       51 
56 
     | 
    
         
             
                  end
         
     | 
| 
       52 
57 
     | 
    
         | 
| 
      
 58 
     | 
    
         
            +
                  @logger&.info("Per-file backup completed: #{files_to_backup.size} file(s) backed up")
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
       53 
60 
     | 
    
         
             
                  # NOTE: remove_source handled per file after successful backup
         
     | 
| 
       54 
61 
     | 
    
         
             
                  remove_source_files if remove_source
         
     | 
| 
       55 
62 
     | 
    
         
             
                end
         
     | 
| 
         @@ -108,6 +115,9 @@ module Ruborg 
     | 
|
| 
       108 
115 
     | 
    
         
             
                def extract(archive_name, destination: ".", path: nil)
         
     | 
| 
       109 
116 
     | 
    
         
             
                  raise BorgError, "Repository does not exist" unless @repository.exists?
         
     | 
| 
       110 
117 
     | 
    
         | 
| 
      
 118 
     | 
    
         
            +
                  extract_target = path ? "#{path} from #{archive_name}" : archive_name
         
     | 
| 
      
 119 
     | 
    
         
            +
                  @logger&.info("Extracting #{extract_target} to #{destination}")
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
       111 
121 
     | 
    
         
             
                  cmd = [@repository.borg_path, "extract", "#{@repository.path}::#{archive_name}"]
         
     | 
| 
       112 
122 
     | 
    
         
             
                  cmd << path if path
         
     | 
| 
       113 
123 
     | 
    
         | 
| 
         @@ -125,6 +135,8 @@ module Ruborg 
     | 
|
| 
       125 
135 
     | 
    
         
             
                      execute_borg_command(cmd)
         
     | 
| 
       126 
136 
     | 
    
         
             
                    end
         
     | 
| 
       127 
137 
     | 
    
         
             
                  end
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
                  @logger&.info("Extraction completed successfully")
         
     | 
| 
       128 
140 
     | 
    
         
             
                end
         
     | 
| 
       129 
141 
     | 
    
         | 
| 
       130 
142 
     | 
    
         
             
                def list_archives
         
     | 
| 
         @@ -132,8 +144,10 @@ module Ruborg 
     | 
|
| 
       132 
144 
     | 
    
         
             
                end
         
     | 
| 
       133 
145 
     | 
    
         | 
| 
       134 
146 
     | 
    
         
             
                def delete(archive_name)
         
     | 
| 
      
 147 
     | 
    
         
            +
                  @logger&.info("Deleting archive: #{archive_name}")
         
     | 
| 
       135 
148 
     | 
    
         
             
                  cmd = [@repository.borg_path, "delete", "#{@repository.path}::#{archive_name}"]
         
     | 
| 
       136 
149 
     | 
    
         
             
                  execute_borg_command(cmd)
         
     | 
| 
      
 150 
     | 
    
         
            +
                  @logger&.info("Archive deleted successfully: #{archive_name}")
         
     | 
| 
       137 
151 
     | 
    
         
             
                end
         
     | 
| 
       138 
152 
     | 
    
         | 
| 
       139 
153 
     | 
    
         
             
                private
         
     | 
| 
         @@ -171,29 +185,45 @@ module Ruborg 
     | 
|
| 
       171 
185 
     | 
    
         
             
                def remove_source_files
         
     | 
| 
       172 
186 
     | 
    
         
             
                  require "fileutils"
         
     | 
| 
       173 
187 
     | 
    
         | 
| 
      
 188 
     | 
    
         
            +
                  @logger&.info("Removing source files after successful backup")
         
     | 
| 
      
 189 
     | 
    
         
            +
             
     | 
| 
      
 190 
     | 
    
         
            +
                  removed_count = 0
         
     | 
| 
      
 191 
     | 
    
         
            +
             
     | 
| 
       174 
192 
     | 
    
         
             
                  @config.backup_paths.each do |path|
         
     | 
| 
       175 
193 
     | 
    
         
             
                    # Resolve symlinks and validate path
         
     | 
| 
       176 
194 
     | 
    
         
             
                    begin
         
     | 
| 
       177 
195 
     | 
    
         
             
                      real_path = File.realpath(path)
         
     | 
| 
       178 
196 
     | 
    
         
             
                    rescue Errno::ENOENT
         
     | 
| 
       179 
197 
     | 
    
         
             
                      # Path doesn't exist, skip
         
     | 
| 
      
 198 
     | 
    
         
            +
                      @logger&.warn("Source path does not exist, skipping: #{path}")
         
     | 
| 
       180 
199 
     | 
    
         
             
                      next
         
     | 
| 
       181 
200 
     | 
    
         
             
                    end
         
     | 
| 
       182 
201 
     | 
    
         | 
| 
       183 
202 
     | 
    
         
             
                    # Security check: ensure path hasn't been tampered with
         
     | 
| 
       184 
     | 
    
         
            -
                     
     | 
| 
      
 203 
     | 
    
         
            +
                    unless File.exist?(real_path)
         
     | 
| 
      
 204 
     | 
    
         
            +
                      @logger&.warn("Source path no longer exists, skipping: #{real_path}")
         
     | 
| 
      
 205 
     | 
    
         
            +
                      next
         
     | 
| 
      
 206 
     | 
    
         
            +
                    end
         
     | 
| 
       185 
207 
     | 
    
         | 
| 
       186 
208 
     | 
    
         
             
                    # Additional safety: don't delete root or system directories
         
     | 
| 
       187 
209 
     | 
    
         
             
                    if real_path == "/" || real_path.start_with?("/bin", "/sbin", "/usr", "/etc", "/sys", "/proc")
         
     | 
| 
      
 210 
     | 
    
         
            +
                      @logger&.error("Refusing to delete system path: #{real_path}")
         
     | 
| 
       188 
211 
     | 
    
         
             
                      raise BorgError, "Refusing to delete system path: #{real_path}"
         
     | 
| 
       189 
212 
     | 
    
         
             
                    end
         
     | 
| 
       190 
213 
     | 
    
         | 
| 
      
 214 
     | 
    
         
            +
                    file_type = File.directory?(real_path) ? "directory" : "file"
         
     | 
| 
      
 215 
     | 
    
         
            +
                    @logger&.info("Removing #{file_type}: #{real_path}")
         
     | 
| 
      
 216 
     | 
    
         
            +
             
     | 
| 
       191 
217 
     | 
    
         
             
                    if File.directory?(real_path)
         
     | 
| 
       192 
218 
     | 
    
         
             
                      FileUtils.rm_rf(real_path, secure: true)
         
     | 
| 
       193 
219 
     | 
    
         
             
                    elsif File.file?(real_path)
         
     | 
| 
       194 
220 
     | 
    
         
             
                      FileUtils.rm(real_path)
         
     | 
| 
       195 
221 
     | 
    
         
             
                    end
         
     | 
| 
      
 222 
     | 
    
         
            +
             
     | 
| 
      
 223 
     | 
    
         
            +
                    removed_count += 1
         
     | 
| 
       196 
224 
     | 
    
         
             
                  end
         
     | 
| 
      
 225 
     | 
    
         
            +
             
     | 
| 
      
 226 
     | 
    
         
            +
                  @logger&.info("Source file removal completed: #{removed_count} item(s) removed")
         
     | 
| 
       197 
227 
     | 
    
         
             
                end
         
     | 
| 
       198 
228 
     | 
    
         | 
| 
       199 
229 
     | 
    
         
             
                def validate_destination_path(destination)
         
     |