Skip to content
This repository
Browse code

Group finalize_update shell commands into one command, harden shell c…

…alls with #shellescape, and separate arguments with --
  • Loading branch information...
commit 483d2538e67a73ffca6062200bba8ffbdc823e66 1 parent ec1f06f
Nathan Broadbent ndbroadbent authored

Showing 1 changed file with 15 additions and 8 deletions. Show diff stats Hide diff stats

  1. +15 8 lib/capistrano/recipes/deploy.rb
23 lib/capistrano/recipes/deploy.rb
... ... @@ -1,5 +1,6 @@
1 1 require 'benchmark'
2 2 require 'yaml'
  3 +require 'shellwords'
3 4 require 'capistrano/recipes/deploy/scm'
4 5 require 'capistrano/recipes/deploy/strategy'
5 6
@@ -240,23 +241,29 @@ def try_runner(*args)
240 241 using the :public_children variable.
241 242 DESC
242 243 task :finalize_update, :except => { :no_release => true } do
243   - run "chmod -R g+w #{latest_release}" if fetch(:group_writable, true)
  244 + escaped_release = latest_release.to_s.shellescape
  245 + commands = []
  246 + commands << "chmod -R -- g+w #{escaped_release}" if fetch(:group_writable, true)
244 247
245 248 # mkdir -p is making sure that the directories are there for some SCM's that don't
246 249 # save empty folders
247   - shared_children.map do |d|
248   - if (d.rindex('/')) then
249   - run "rm -rf #{latest_release}/#{d} && mkdir -p #{latest_release}/#{d.slice(0..(d.rindex('/')))}"
  250 + shared_children.map do |dir|
  251 + d = dir.shellescape
  252 + if (dir.rindex('/')) then
  253 + commands += ["rm -rf -- #{escaped_release}/#{d}",
  254 + "mkdir -p -- #{escaped_release}/#{dir.slice(0..(dir.rindex('/'))).shellescape}"]
250 255 else
251   - run "rm -rf #{latest_release}/#{d}"
  256 + commands << "rm -rf -- #{escaped_release}/#{d}"
252 257 end
253   - run "ln -s #{shared_path}/#{d.split('/').last} #{latest_release}/#{d}"
  258 + commands << "ln -s -- #{shared_path}/#{dir.split('/').last.shellescape} #{escaped_release}/#{d}"
254 259 end
255 260
  261 + run commands.join(' && ') if commands.any?
  262 +
256 263 if fetch(:normalize_asset_timestamps, true)
257 264 stamp = Time.now.utc.strftime("%Y%m%d%H%M.%S")
258   - asset_paths = fetch(:public_children, %w(images stylesheets javascripts)).map { |p| "#{latest_release}/public/#{p}" }
259   - run("find #{asset_paths.join(" ")} -exec touch -t #{stamp} {} ';'; true", :env => { "TZ" => "UTC" }) if asset_paths.any?
  265 + asset_paths = fetch(:public_children, %w(images stylesheets javascripts)).map { |p| "#{escaped_release}/public/#{p}" }
  266 + run("find #{asset_paths.join(" ").shellescape} -exec touch -t -- #{stamp} {} ';'; true", :env => { "TZ" => "UTC" }) if asset_paths.any?
260 267 end
261 268 end
262 269

1 comment on commit 483d253

Felix Bünemann

This actually breaks deployments, if your release path is relative to the users home (e.g. set :deploy_to, "~/releases"), because ~ gets escaped to \\~. It is also incomplete, because e.g. shared_path is not escaped.

Found this issue to be covered in #300.

Please sign in to comment.
Something went wrong with that request. Please try again.