在Ruby / Rails中清理文件名

3
为了确定附加文件的文件类型,我使用了操作系统中的“file”实用工具:
class AttachedFileTypeValidator < ActiveModel::Validator
  def validate(record)
    file = record.resource.uploaded_file
    attached_file = Rails.root + file.path
    file_type = `file #{attached_file}`
    Rails.logger.info "Attached file type determined to be: #{file_type}"
    unless file_type.split(',').first =~ /ASCII|UTF/
      record.errors[:resource_content_type] << "Attachment does not appear to be a text CSV file, please ensure it was saved correctly."
    end
  end
end

很不幸,brakeman 表示这是一个命令行注入的机会。我猜这意味着有人想出了一个聪明的文件名,比如:
; rm -rf /;

开始吧。如何有效地清理文件名?


转义分隔符?用合法字符(如下划线)替换? - Dave Newton
@DaveNewton:用下划线替换是不好的,文件已经以给定名称上传。 应该有一个库来做shell转义。 - Asherah
@Len 那就太晚了,不是吗。文件名应该在写入文件系统之前进行清理 - 常见的库有钩子允许这样做,据我所知。 - Dave Newton
@DaveNewton:不,它不是。该文件被写入文件系统,并且我们假定上传时使用的任何库或系统部分都是安全的。但这并不改变文件名本身如果未经转义放入shell命令中会产生危险的事实。 - Asherah
@DaveNewton:即使上传处理程序能够创建这样的文件,如果文件名是带有空格的abc def,那么\file #{attached_file}``显然会失败。 - Asherah
@Len 哦,我明白你的意思。 - Dave Newton
1个回答

3

使用IO#popen调用外部命令:

file_type = IO.popen(['file', attached_file]).read

这将为您处理文件名中有趣字符的适当转义。

不幸的是,这个解决方案似乎也会在单线程环境中(比如运行规范)导致锁定问题。http://stackoverflow.com/questions/10834556/jruby-io-popen-read-hangs-in-action-when-requests-are-made-to-the-local-dev-serv - Allyl Isocyanate

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接