Class: Gitlab::Sanitizers::Exif

Inherits:
Object
  • Object
show all
Defined in:
lib/gitlab/sanitizers/exif.rb

Constant Summary collapse

WHITELISTED_TAGS =

these tags are not removed from the image

%w[
  ResolutionUnit
  XResolution
  YResolution
  YCbCrSubSampling
  YCbCrPositioning
  BitsPerSample
  ImageHeight
  ImageWidth
  ImageSize
  Copyright
  CopyrightNotice
  Orientation
].freeze
IGNORED_TAGS =

these tags are common in exiftool output, these do not contain any sensitive information, but we don’t need to preserve them when removing exif tags

%w[
  ColorComponents
  EncodingProcess
  ExifByteOrder
  ExifToolVersion
  JFIFVersion
  Directory
  FileAccessDate
  FileInodeChangeDate
  FileModifyDate
  FileName
  FilePermissions
  FileSize
  SourceFile
  Megapixels
  FileType
  FileTypeExtension
  MIMEType
].freeze
ALLOWED_TAGS =
WHITELISTED_TAGS + IGNORED_TAGS
EXCLUDE_PARAMS =
WHITELISTED_TAGS.map { |tag| "-#{tag}" }
ALLOWED_MIME_TYPES =
%w[image/jpeg image/tiff].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(logger: Gitlab::AppLogger) ⇒ Exif

Returns a new instance of Exif.



52
53
54
# File 'lib/gitlab/sanitizers/exif.rb', line 52

def initialize(logger: Gitlab::AppLogger)
  @logger = logger
end

Instance Attribute Details

#loggerObject (readonly)

Returns the value of attribute logger.



50
51
52
# File 'lib/gitlab/sanitizers/exif.rb', line 50

def logger
  @logger
end

Instance Method Details

#batch_clean(start_id: nil, stop_id: nil, dry_run: true, sleep_time: nil, uploader: nil, since: nil) ⇒ Object

rubocop: disable CodeReuse/ActiveRecord



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/gitlab/sanitizers/exif.rb', line 57

def batch_clean(start_id: nil, stop_id: nil, dry_run: true, sleep_time: nil, uploader: nil, since: nil)
  relation = Upload.where('lower(path) like ? or lower(path) like ? or lower(path) like ?',
                          '%.jpg', '%.jpeg', '%.tiff')
  relation = relation.where(uploader: uploader) if uploader
  relation = relation.where('created_at > ?', since) if since

  logger.info "running in dry run mode, no images will be rewritten" if dry_run

  find_params = {
    start: start_id.present? ? start_id.to_i : nil,
    finish: stop_id.present? ? stop_id.to_i : Upload.last&.id,
    batch_size: 1000
  }

  relation.find_each(**find_params) do |upload|
    clean(upload.retrieve_uploader, dry_run: dry_run)
    sleep sleep_time if sleep_time
  rescue StandardError => err
    logger.error "failed to sanitize #{upload_ref(upload)}: #{err.message}"
    logger.debug err.backtrace.join("\n ")
  end
end

#clean(uploader, dry_run: true) ⇒ Object

rubocop: enable CodeReuse/ActiveRecord



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/gitlab/sanitizers/exif.rb', line 81

def clean(uploader, dry_run: true)
  Dir.mktmpdir('gitlab-exif') do |tmpdir|
    src_path = fetch_upload_to_file(uploader, tmpdir)

    to_remove = extra_tags(src_path)

    if to_remove.empty?
      logger.info "#{upload_ref(uploader.upload)}: only whitelisted tags present, skipping"
      break
    end

    logger.info "#{upload_ref(uploader.upload)}: found exif tags to remove: #{to_remove}"

    break if dry_run

    remove_and_store(tmpdir, src_path, uploader)
  end
end

#clean_existing_path(src_path, dry_run: false, content: nil, skip_unallowed_types: false) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/gitlab/sanitizers/exif.rb', line 100

def clean_existing_path(src_path, dry_run: false, content: nil, skip_unallowed_types: false)
  content ||= File.read(src_path)

  if skip_unallowed_types
    return unless check_for_allowed_types(content, raise_error: false)
  else
    check_for_allowed_types(content)
  end

  to_remove = extra_tags(src_path)

  if to_remove.empty?
    logger.info "#{src_path}: only whitelisted tags present, skipping"
    return
  end

  logger.info "#{src_path}: found exif tags to remove: #{to_remove}"
  return if dry_run

  exec_remove_exif!(src_path)
end