Module: Gitlab::PathTraversal

Extended by:
PathTraversal
Included in:
PathTraversal
Defined in:
lib/gitlab/path_traversal.rb

Constant Summary collapse

PathTraversalAttackError =
Class.new(StandardError)
PATH_TRAVERSAL_REGEX =
%r{(\A(\.{1,2})\z|\A\.\.[/\\]|[/\\]\.\.\z|[/\\]\.\.[/\\]|\n)}

Instance Method Summary collapse

Instance Method Details

#check_allowed_absolute_path!(path, allowlist) ⇒ Object

Raises:

  • (StandardError)


34
35
36
37
38
39
# File 'lib/gitlab/path_traversal.rb', line 34

def check_allowed_absolute_path!(path, allowlist)
  return unless Pathname.new(path).absolute?
  return if ::Gitlab::Utils.allowlisted?(path, allowlist)

  raise StandardError, "path #{path} is not allowed"
end

#check_allowed_absolute_path_and_path_traversal!(path, path_allowlist) ⇒ Object

Raises:

  • (StandardError)


41
42
43
44
45
46
# File 'lib/gitlab/path_traversal.rb', line 41

def check_allowed_absolute_path_and_path_traversal!(path, path_allowlist)
  traversal_path = check_path_traversal!(path)
  raise StandardError, "path is not a string!" unless traversal_path.is_a?(String)

  check_allowed_absolute_path!(traversal_path, path_allowlist)
end

#check_path_traversal!(path) ⇒ Object

Ensure that the relative path will not traverse outside the base directory We url decode the path to avoid passing invalid paths forward in url encoded format. Also see gitlab.com/gitlab-org/gitlab/-/merge_requests/24223#note_284122580 It also checks for backslash ‘', which is sometimes a File::ALT_SEPARATOR.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/gitlab/path_traversal.rb', line 18

def check_path_traversal!(path)
  return unless path

  path = path.to_s if path.is_a?(Gitlab::HashedPath)
  raise PathTraversalAttackError, 'Invalid path' unless path.is_a?(String)

  path = ::Gitlab::Utils.decode_path(path)

  if path.match?(PATH_TRAVERSAL_REGEX)
    logger.warn(message: "Potential path traversal attempt detected", path: path.to_s)
    raise PathTraversalAttackError, 'Invalid path'
  end

  path
end