Back to Repositories

Testing File System Security and Path Resolution in Shopify/liquid

This test suite validates the Liquid template engine’s file system functionality, focusing on both default and local file system implementations. It ensures secure template file handling and proper path resolution for partial templates.

Test Coverage Overview

The test suite provides comprehensive coverage of file system operations in Liquid:

  • Default file system behavior and error handling
  • Local file system path resolution and security checks
  • Custom template filename pattern support
  • Path traversal attack prevention

Implementation Analysis

The testing approach employs Minitest framework with focused unit tests for file system components. It implements systematic validation of path handling, using both valid and invalid path scenarios to ensure robust security measures.

The tests utilize assertion patterns specific to path validation and error handling expectations.

Technical Details

  • Testing Framework: Minitest
  • File System Classes: BlankFileSystem, LocalFileSystem
  • Test Environment: Ruby
  • Key Methods Tested: read_template_file, full_path
  • Security Validations: Path traversal prevention, file access restrictions

Best Practices Demonstrated

The test suite exemplifies several testing best practices including comprehensive security testing, clear test case organization, and thorough edge case coverage. Each test method focuses on a specific aspect of the file system functionality, with explicit assertions and error case validation.

  • Isolated test cases for each feature
  • Security-first approach to file system testing
  • Clear test method naming conventions
  • Comprehensive error case coverage

shopify/liquid

test/unit/file_system_unit_test.rb

            
# frozen_string_literal: true

require 'test_helper'

class FileSystemUnitTest < Minitest::Test
  include Liquid

  def test_default
    assert_raises(FileSystemError) do
      BlankFileSystem.new.read_template_file("dummy")
    end
  end

  def test_local
    file_system = Liquid::LocalFileSystem.new("/some/path")
    assert_equal("/some/path/_mypartial.liquid", file_system.full_path("mypartial"))
    assert_equal("/some/path/dir/_mypartial.liquid", file_system.full_path("dir/mypartial"))

    assert_raises(FileSystemError) do
      file_system.full_path("../dir/mypartial")
    end

    assert_raises(FileSystemError) do
      file_system.full_path("/dir/../../dir/mypartial")
    end

    assert_raises(FileSystemError) do
      file_system.full_path("/etc/passwd")
    end
  end

  def test_custom_template_filename_patterns
    file_system = Liquid::LocalFileSystem.new("/some/path", "%s.html")
    assert_equal("/some/path/mypartial.html", file_system.full_path("mypartial"))
    assert_equal("/some/path/dir/mypartial.html", file_system.full_path("dir/mypartial"))
  end
end # FileSystemTest