class ActiveStorage::Service::DiskService
def path_for(key) # :nodoc:
path_for or make_path_for -- never construct paths from +root+ directly.
path-traversal protection is enforced here. New methods that touch the filesystem MUST use
make_path_for, which delegates here). This is the primary filesystem security check: all
Every filesystem operation in DiskService resolves paths through this method (or through
def path_for(key) # :nodoc: if key.blank? raise ActiveStorage::InvalidKeyError, "key is blank" end # Reject keys with dot segments as defense in depth. This prevents path traversal both outside # and within the storage root. The root containment check below is a more fundamental check on # path traversal outside of the disk service root. begin if key.split("/").intersect?(%w[. ..]) raise ActiveStorage::InvalidKeyError, "key has path traversal segments" end rescue Encoding::CompatibilityError raise ActiveStorage::InvalidKeyError, "key has incompatible encoding" end begin path = File.expand_path(File.join(root, folder_for(key), key)) rescue ArgumentError # ArgumentError catches null bytes raise ActiveStorage::InvalidKeyError, "key is an invalid string" end # The resolved path must be inside the root directory. unless path.start_with?(File.expand_path(root) + "/") raise ActiveStorage::InvalidKeyError, "key is outside of disk service root" end path end