Rails antivirus made easy. Developed by Mainio Tech.
Ratonvirus allows your Rails application to rat on the viruses that your users try to upload to your site. This works through Rails validators that you can easily attach to your models.
The purpose of Ratonvirus is to act as the glue that binds your Rails application to a virus scanner and file storage engine of your choise.
Setting up scanning for files attached to models:
class Model < ApplicationRecord
# ...
validates :file, antivirus: true
# ...
end
Running manual scans:
puts "File contains a virus" if Ratonvirus.scanner.virus?("/path/to/file.pdf")
Manual scanning works e.g. for file uploads, file object and file paths.
Ratonvirus works with Active Storage out of the box. Support for CarrierWave is also built in, assuming you already have CarrierWave as a dependency.
When to use this?
This gem can be handy if you want to:
- Scan files for viruses in Ruby, especially in Rails
- Make the scanning logic agnostic of the
- scanner implementation (e.g. ClamAV)
- file storage (e.g. Active Storage, CarrierWave, no storage engine)
- Separate testing code for the scanner implementation or the file storage cleanly into its own place.
Prerequisites
There is no fully Ruby-based virus scanner available on the market for a good reason: it is a heavy task. Therefore, this gem may not work as automagically as you are used to with many other gems.
You will need to setup a virus scanner on your machine. If you have done that
before, configuration should be rather simple. Instructions are provided for
the open source ClamAV scanner in the
ratonvirus-clamby
documentation.
This gem ships with an example EICAR file scanner to test out the configuration process. This scanner allows you to test the functionality of this gem with no external requirements but it should not be used in production environments.
Installation
Add this line to your application's Gemfile:
gem "ratonvirus"
And then execute:
$ bundle
Add this initializer to your application's config/initializers/ratonvirus.rb
:
# config/initializers/ratonvirus.rb
Ratonvirus.configure do |config|
config.scanner = :eicar
config.storage = :active_storage
end
After installation, test that the gem is loaded properly in your it is ready to do a sample validation:
$ bundle exec rails ratonvirus:test
This command should show the following message when correctly installed:
Ratonvirus correctly configured.
NOTE:
By default Ratonvirus is set to remove all infected files that it detects after scanning them. If you want to remove this functionality, please refer to the Scanner addons section of the developer documentation.
Usage
Applying the antivirus validator to your models
In order to apply the antivirus validator, you need to have your file uploads handled by a storage backend such as Active Storage. Examples are provided below for the most common options.
Example with Active Storage
Your model should look similar to this:
class YourModel < ApplicationRecord
has_one_attached :file
validates :file, antivirus: true # Add this for antivirus validation
end
Example with CarrierWave
Your model should look similar to this:
class YourModel < ApplicationRecord
mount_uploader :file, YourUploader
validates :file, antivirus: true # Add this for antivirus validation
end
Please note the extra configuration you need for CarrierWave from the configuration examples.
Manually checking for viruses
For the manual scans to work you need to configure the correct storage backend first that accepts these resources:
# config/initializers/ratonvirus.rb
# When scanning files or file paths only
Ratonvirus.configure do |config|
config.storage = :filepath
end
# When scanning files, file paths or active storage resources
Ratonvirus.configure do |config|
config.storage = :multi, {storages: [:filepath, :active_storage]}
end
In case you want to manually scan for viruses, you can use any of the following examples:
# It is a good idea to check first that the scanner is available.
if Ratonvirus.scanner.available?
# Scanning a file path
path = "/path/to/file.pdf"
if Ratonvirus.scanner.virus?(path)
puts "There is a virus at #{path}"
end
# Scanning a File object
file = File.new(path)
if Ratonvirus.scanner.virus?(file)
puts "There is a virus at #{file.path}"
end
end
Sample configurations
Here are few sample configurations to speed up the configuration process.
Active Storage and ClamAV
Gemfile:
gem "ratonvirus"
gem "ratonvirus-clamby"
Initializer:
# config/initializers/ratonvirus.rb
Ratonvirus.configure do |config|
config.scanner = :clamby
config.storage = :active_storage
end
Model:
class YourModel < ApplicationRecord
has_one_attached :file
validates :file, antivirus: true
end
For installing ClamAV, refer to
ratonvirus-clamby
CarrierWave and ClamAV
Gemfile:
gem "ratonvirus"
gem "ratonvirus-clamby"
Initializer:
# config/initializers/ratonvirus.rb
Ratonvirus.configure do |config|
config.scanner = :clamby
config.storage = :carrierwave
end
Model:
class YourModel < ApplicationRecord
mount_uploader :file, YourUploader
validates :file, antivirus: true
end
For installing ClamAV, refer to
ratonvirus-clamby
Further configuration and development
For further information about the configurations and how to create custom scanners, please refer to the documentation.
Common issues
NoMethodError (undefined method `attached?' ...)
Multiple issues have been opened because of users getting the following error when trying to run a scan against a file path:
NoMethodError (undefined method `attached?' for "/path/to/file.pdf":String)
Most of the times this issue is because you have not configured the storage
correctly. If you want to run direct scans against files, please use the
:filepath
storage option as described at
Manually checking for viruses.
If you need both: scans against file paths and scans against Active Storage
attached files, please use the :multi
storage option as described in the same
section of the documentation.
License
MIT, see LICENSE.