mirror of
https://github.com/discourse/discourse.git
synced 2026-08-11 02:59:07 +08:00
Create a dedicated tmp directory so that we don't have to grant read/write access to the system-level tmp directory.
54 lines
1.7 KiB
Ruby
Vendored
54 lines
1.7 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
require "image_optim/cmd"
|
|
require "image_optim/path"
|
|
require "tmpdir"
|
|
|
|
# Route image_optim's optimizer binaries through the Landlock sandbox, confining
|
|
# them to the file being optimized with no network. Cmd.capture (version/CPU
|
|
# probes, no untrusted input) is intentionally not patched.
|
|
class ImageOptim
|
|
# Per-thread tmp directory, so that we don't have to grant access to the global tmpdir
|
|
def self.discourse_tmp_root
|
|
Thread.current[:discourse_image_optim_tmp_root] ||= Dir.mktmpdir("discourse-image-optim-")
|
|
end
|
|
|
|
module DiscourseScratchDestination
|
|
def temp_path(*args, &block)
|
|
return super if args.any?
|
|
|
|
super(ImageOptim.discourse_tmp_root, &block)
|
|
end
|
|
end
|
|
ImageOptim::Path.prepend(DiscourseScratchDestination)
|
|
|
|
module Cmd
|
|
class << self
|
|
def run(*args)
|
|
options = args.last.is_a?(Hash) ? args.pop : {}
|
|
env = args.first.is_a?(Hash) ? args.shift : {}
|
|
|
|
files = args.select { |arg| arg.is_a?(String) && File.file?(arg) }
|
|
|
|
Discourse::SafeExec.capture(
|
|
*args,
|
|
env: {
|
|
**env,
|
|
"MALLOC_ARENA_MAX" => "2",
|
|
},
|
|
unsetenv_others: true,
|
|
read: [*Discourse::SafeExec.default_read_paths, *files],
|
|
write: [ImageOptim.discourse_tmp_root],
|
|
execute: Discourse::SafeExec.default_execute_paths,
|
|
timeout: options[:timeout]&.to_f || ImageMagick::DEFAULT_TIMEOUT,
|
|
rlimits: ImageMagick::RLIMITS,
|
|
seccomp_deny_network: true,
|
|
)
|
|
true
|
|
rescue Discourse::Utils::CommandError
|
|
# non-zero exit means "kept the original", like system(*args) => false
|
|
false
|
|
end
|
|
end
|
|
end
|
|
end
|