# [Security] Redacted attachment filenames exposed in downloads
We've discovered and patched an issue where attachment filenames redacted by censor rules can be exposed via download options.
We've released a fix in 0.46.2.0 [1] and 0.45.4.0 [2]. If you are running an older version of Alaveteli please see the pull request and patch your Alaveteli as appropriate [3].
# Summary and impact
The censor rule correctly redacts the filename on the public request page. However, when the file is downloaded, the saved file retains the original unredacted file path. Where filenames contained personal data (for example requesters’ names), this could reveal identifying information that should have been redacted.
This problem exists via two actions:
1. Downloading a zip file of a batch request in version 0.38.0.0+
2. Downloading (rather than "viewing") an attachment in version 0.46.0.0+
The problem does not affect downloading a zip of an individual request.
# Fix
We've updated code to use `FoiAttachment#display_filename` rather than the raw unredacted `FoiAttachment#filename` value. See pull request #9163 [3].
# Checking affected content
You can run the following script to check whether you have attachments with a redacted filename:
```
affected_requests = if CensorRule.global.exists?
InfoRequest.all
else
by_request = CensorRule.where.not(info_request_id: nil).pluck(:info_request_id)
by_user = CensorRule.where.not(user_id: nil).pluck(:user_id)
by_body = CensorRule.where.not(public_body_id: nil).pluck(:public_body_id)
InfoRequest.where(id: by_request)
.or(InfoRequest.where(user_id: by_user))
.or(InfoRequest.where(public_body_id: by_body))
end
attachments =
affected_requests.
includes(:censor_rules, public_body: :censor_rules, user: :censor_rules).
find_each.flat_map do |request|
request.foi_attachments.find_each.select do |a|
a.filename != a.redacted_filename
end
end
# Print a list of attachment IDs where the filename is redacted
puts attachments.map(&:id).join("\n")
# Print a CSV containing additional diagnostic information
str = CSV.generate do |csv|
csv << %w[
attachment_id,
admin_url,
public_url,
received_on
filename,
redacted_filename,
batch_id
]
attachments.each do |attachment|
request_slug = attachment.incoming_message.info_request.url_title
received_on = attachment.incoming_message.created_at.strftime('%Y-%m-%d')
batch_id = attachment.incoming_message.info_request.info_request_batch_id
csv << [
attachment.id,
"/admin/attachments/#{
attachment.id}/edit",
"/request/#{request_slug}#attachment-#{
attachment.id}",
received_on,
attachment.filename,
attachment.display_filename,
batch_id
]
end
end
puts str
```
You can map this information to information in the admin UI and/or server logs to assess impact and severity in your specific install. Let us know if you need any assistance in diagnosing this issue.
# Affected versions
Exposing unredacted attachment filenames via downloading a zip file of a batch request was introduced in version 0.38.0.0.
Exposing unredacted attachment filenames via downloading an attachment in version 0.46.0.0.
# Fixed versions
We've released a fix in 0.46.2.0 [1] and 0.45.4.0 [2]. If you are running an older version of Alaveteli please see the pull request and patch your Alaveteli as appropriate [3].
As ever, reach out if you have any questions.
Best,
Gareth
[1]
https://github.com/mysociety/alaveteli/releases/tag/0.46.2.0[2]
https://github.com/mysociety/alaveteli/releases/tag/0.45.4.0[3]
https://github.com/mysociety/alaveteli/pull/9163