Back to docs
reference

Security & File Handling

File Security Policy

Strayfiles implements strict security policies to protect your system from path traversal attacks and malicious file operations.

Strayfiles blocks direct symlinks during file discovery but allows files within symlinked directories.

This policy balances security with real-world filesystem usage, since system directories like /tmp and /var are often symlinks.

What is Blocked

ScenarioExampleResult
Direct symlinknotes/link.md -> /etc/passwdSkipped, warning logged
Dangling symlinknotes/broken.md -> /nonexistentSkipped, warning logged

What is Allowed

ScenarioExampleResult
File through symlinked directory/var/tmp/notes/file.mdAllowed if file.md is regular
Regular filenotes/example.mdAllowed

Direct symlinks pose security risks:

  1. Path Traversal - A symlink could point to sensitive system files outside your notes directory (e.g., /etc/passwd, ~/.ssh/id_rsa)

  2. Sandbox Escape - An attacker could use symlinks to read or write files outside the intended workspace

  3. Time-of-Check-Time-of-Use - Dangling symlinks could be replaced with malicious targets after discovery

Why Allow Symlinked Directories?

Blocking parent symlinks would break common system setups:

  • /tmp is often symlinked to /private/tmp on macOS
  • /var is often symlinked to /private/var on macOS
  • User home directories may be symlinked (e.g., network mounts)

Strayfiles validates only the final file component, not parent directories, to support these standard configurations.

If a symlink is detected during file scanning:

  1. The file is skipped - Not indexed or tracked
  2. A warning is logged - DiscoveryWarning::SymlinkDetected { path }
  3. Discovery continues - Other files are processed normally

You can check the discovery log for warnings after scanning.

Security Function Reference

The security validation is performed by:

validate_no_symlinks(path: &Path) -> Result<()>

This function:

  • Uses std::fs::symlink_metadata() to detect symlinks
  • Checks only the final path component, not parents
  • Detects both regular and dangling symlinks
  • Returns Error::Security if the path is a symlink

Best Practices

To avoid symlink warnings:

  1. Use real paths - Store notes in regular directories, not symlinks
  2. Check discovery logs - Review warnings to identify symlink issues
  3. Move files if needed - Copy symlinked files to regular locations
  4. Use TOML tracking - Add symlink targets to strayfiles.toml if you control both ends

Alternative: TOML-Based Tracking

If you need to track a file that’s behind a symlink:

  1. Add the symlink target’s real path to strayfiles.toml
  2. Use the Project TOML or User TOML tracking method

This bypasses symlink validation while still providing some tracking capability (note: TOML tracking is path-based and won’t survive file moves).

Additional Security Features

Keychain Integration

Sensitive credentials are stored in the system keychain:

  • macOS: Keychain Services
  • Linux: Secret Service API
  • Windows: Windows Credential Manager

Never store passwords or tokens in plain text files.

Atomic File Writes

All file writes use atomic operations:

  • Write to temporary file first
  • Verify write success
  • Rename to target path (atomic on POSIX)
  • Original preserved on failure

Input Validation

All user-provided inputs are validated:

  • Paths: Checked for symlinks, parent traversal
  • URLs: Validated format, SSRF protection
  • Emails: Validated format before sending
  • Git remotes: Validated URL structure

Code Execution Prevention

Strayfiles never executes code from Markdown content:

  • No script tags rendered
  • No eval() or dynamic code generation
  • Markdown rendered safely without HTML injection
  • Preview mode uses sanitized rendering

Filesystem Sandboxing

File discovery is sandboxed:

  • Respects configured root directories
  • Honors .gitignore patterns
  • Skips system directories by default
  • Validates paths before access