Super-Simple Includes Documentation

v0.244.0

Security Features

Security Features and Protections

Write Protection

Super Simple Includes implements strict write protection to prevent accidental or malicious writes to critical system directories.

Protected System Directories (MUST BLOCK)

The following directories are strictly protected. Any attempt to write to these locations will result in an error:

  • /bin - System binaries
  • /dev - Device files
  • /etc - System configuration
  • /lib - System libraries
  • /lib64 - 64-bit system libraries
  • /proc - Process information
  • /root - Root user home
  • /sbin - System administration binaries
  • /usr - User programs and data

Allowed Directories (NO WARNING)

Writes to the following directories are considered normal and will not generate warnings:

  • /home - User home directories
  • /var - Variable data (logs, temporary files, etc.)
  • /opt - Optional/third-party software
  • /mnt - Temporary mount points
  • /run/media - Removable media mount points

Unusual Locations (WARNING)

Writes to any location not listed above will generate a warning but will be allowed to proceed. This includes:

  • /tmp - Temporary files (warning because deployments here are unusual)
  • Custom mount points
  • Other non-standard locations

Symlink Protection

All symlinks are resolved to their real paths before checking. This prevents bypass attempts such as:

  • Creating a symlink to /etc and trying to write through it
  • Using complex symlink chains to obscure the final destination
  • Directory traversal attacks using ../ sequences

Path Resolution

Before any write operation:

  1. The path is normalized to remove . and .. components
  2. Symlinks are resolved to their real destinations
  3. The final resolved path is checked against the protection rules

Implementation Requirements

Both the Rust implementation MUST:

  1. Block writes to protected system directories with a clear error message
  2. Warn about writes to unusual locations (outside allowed directories)
  3. Resolve symlinks to prevent bypass attempts
  4. Normalize paths to prevent traversal attacks
  5. Apply these checks to all write operations (deployments, preserve operations, etc.)

Error Messages

When blocking a write, the error message should:

  • Clearly indicate that the operation was blocked for security reasons
  • Specify which protected directory was targeted
  • Suggest using an allowed directory instead

Example:

Error: Cannot write to protected system directory /etc
                Please choose a deployment directory under /home, /var, /opt, /mnt, or /run/media
                

Testing

Security tests are located in tests/security/write_protection.py and verify:

  • Direct writes to system directories are blocked
  • Symlink bypasses are prevented
  • Directory traversal attacks are blocked
  • Warnings are generated for unusual locations
  • Allowed directories work without warnings
  • Complex symlink chains are properly resolved

Source Path Validation

Super Simple Includes enforces strict validation on all source paths in configuration files to ensure they remain within the site directory.

Path Restrictions

All source paths in ssi-config.toml must be relative paths within the site directory. The following are strictly forbidden:

  1. Absolute paths - Paths starting with /
  2. Parent directory references - Paths containing ..

This applies to:

  • Processing steps ([[step]]) - All source paths
  • Include sources ([[step]]) - All source paths

Security Rationale

These restrictions prevent:

  • Information disclosure - Accessing sensitive files outside the site directory
  • Path traversal attacks - Using ../ sequences to escape the site boundary
  • Configuration confusion - Unclear dependencies on external files

Examples

❌ Forbidden Configurations
# Absolute path - NOT ALLOWED
                [[step]]
                emoji = "πŸ”’"
                source = "/etc/passwd"  # ❌ Absolute path
                processing = "preserve"
                
                # Parent directory reference - NOT ALLOWED
                [[step]]
                emoji = "🌍"
                path = "../config/environment.txt"  # ❌ Parent directory reference
                type = "environment"
                
                # Multiple parent references - NOT ALLOWED
                [[step]]
                emoji = "πŸ“„"
                source = "../../shared/pages/"  # ❌ Escapes site directory
                processing = "page"
                
βœ… Correct Configurations
# Relative path within site - ALLOWED
                [[step]]
                emoji = "πŸ”’"
                path = "preservelist.txt"  # βœ… Relative to site directory
                processing = "preserve"
                
                # Subdirectory path - ALLOWED
                [[step]]
                emoji = "🌍"
                source = "config/environment.txt"  # βœ… Within site directory
                type = "environment"
                
                # Nested subdirectories - ALLOWED
                [[step]]
                emoji = "πŸ“„"
                path = "content/pages/"  # βœ… Stays within site
                processing = "page"
                

Error Messages

When a forbidden path is detected:

❌ Absolute paths not allowed in Processing steps configuration: '/etc/passwd'
                πŸ’‘ All source paths must be relative to the site directory
                
                ❌ Parent directory references not allowed in Include sources paths: '../secret.txt'
                πŸ’‘ All source paths must be within the site directory
                

Symlink Security

In addition to the path restrictions above, source paths that are symlinks are validated to ensure they don’t escape the site directory:

  1. Direct symlinks - If a source path is a symlink, it must point to a location within the site directory
  2. Symlink chains - Symlinks that point to other symlinks are followed to their final destination, which must be within the site directory
  3. No escape allowed - Even if the symlink itself is within the site directory, if it points outside, it will be rejected
Examples of Forbidden Symlinks
# In site directory:
                ln -s /etc/passwd evil-symlink
                ln -s ../../../secrets/api-keys external-link
                ln -s external-link chained-link
                
                # All of these would be rejected:
                [[step]]
                source = "evil-symlink"       # ❌ Points to /etc/passwd
                source = "external-link"      # ❌ Points outside site
                source = "chained-link"       # ❌ Eventually points outside
                

Note on Preserve Lists and Environment Files

While the paths TO these configuration files must be within the site directory, the CONTENTS of preserve lists are separately validated with even stricter rules (see preserve processor documentation for details).

Unicode Security Protections

Super Simple Includes implements protection against Unicode-based attacks, including bidirectional text injection and other Unicode exploitation vectors.

Bidirectional Text Injection Protection

SSI blocks all nine dangerous bidirectional (bidi) control characters that can create visual spoofing attacks:

  • U+202A (LRE - Left-to-Right Embedding)
  • U+202B (RLE - Right-to-Left Embedding)
  • U+202C (PDF - Pop Directional Formatting)
  • U+202D (LRO - Left-to-Right Override)
  • U+202E (RLO - Right-to-Left Override)
  • U+2066 (LRI - Left-to-Right Isolate)
  • U+2067 (RLI - Right-to-Left Isolate)
  • U+2068 (FSI - First Strong Isolate)
  • U+2069 (PDI - Pop Directional Isolate)

Multi-Layer Defense Strategy

Protection occurs at three validation points:

  1. Token Name Validation (Config Parsing): Rejects bidi controls in emoji prefixes and TOML keys at configuration load time
  2. File Content Validation (Filesystem Read): Validates template content inline as files are read
  3. Final Output Validation (Pre-Write): Safety gate validation just before writing to disk

This defense-in-depth approach ensures that even if bidi characters are introduced through complex token substitution, they will be caught before deployment.

Legitimate RTL Text

Important: These protections do not affect legitimate right-to-left languages!

βœ… Allowed: Arabic, Hebrew, and other RTL text work naturally without needing bidi control characters:

Ω…Ψ±Ψ­Ψ¨Ψ§  (Arabic)
                Χ©ΧœΧ•Χ   (Hebrew)
                

❌ Blocked: Text with embedded bidi control characters:

text\u202e  (Text with RLO)
                

RTL languages display correctly without explicit bidi control characters in token names or simple content.

Error Messages

When SSI detects a bidi control character, it provides detailed information:

🚨 Security: file content in index.html contains bidirectional control character
                   Text: "token\u202ename"
                   Character: '\u202e' (U+202E)
                   πŸ’‘ Bidi controls can create visual spoofing attacks
                   πŸ”§ Remove bidirectional control characters from your content
                

Documentation

For more information about Unicode security threats and SSI’s protections:

  • See docs/help/unicode-security-overview.md for user guide
  • See test suite in tests/security/test_*.py for validation behavior

Implementation

Both the Rust implementation provide identical Unicode security protections using character iteration (not regex) for reliable detection across all platforms.