Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Encrypts/Decrypts, with key rotation, attributes on classes, using RbNaCl (libsodium).
This library was developed for- and extracted from HireFire.
The documentation can be found on RubyDoc.
Ensure that you've installed libsodium, then add the gem to your Gemfile and run bundle
.
gem "attr_encrypter", "~> 1"
class Account
include AttrEncrypter::Accessors
# Defines the token accessor that seamlessly encrypts and decrypts
# data stored in @token_digest.
#
# Note: This won't define a @token instance variable, as state is
# managed by the token_digest accessor using @token_digest.
#
# Note: You can add multiple attributes in a single attr_encrypter call.
# e.g. `attr_encrypter ENV["KEYCHAIN"], :attr_a, :attr_b, :attr_c`
#
attr_encrypter ENV["KEYCHAIN"], :token
# Defines the token_digest accessor for storing and retrieving encrypted data.
# You don't directly use this accessor. Both read and write operations should
# always go through the token/token= methods provided by the attr_encrypter method.
#
# Consider making this accessor private. We'll leave it public for this demo.
#
attr_accessor :token_digest
end
The KEYCHAIN
environment variable must contain one or more keys. To generate a key, use the following function.
AttrEncrypter::Generator.generate_key
Place the generated key in the KEYCHAIN
environment variable.
The key consists of two segments, <version>.<secret>
. The initial key has a version of 1. Versions determine which secrets will be used to encrypt and decrypt data.
With the key in place you'll be able to store and retrieve data using the dynamically defined token
accessor. Data assigned with token=
will automatically be encrypted and stored with token_digest=
in @token_digest
.
account = Account.new
account.token = "my_secret_token"
account.token_digest # => "1.yCZGH0QEk8+OPT0ad29wVmCkvr/7NXZjZtxu23v2j9HKfehndH0qv9MsF4ME\n"
account.token # => "my_secret_token"
account.instance_variable_get("@token") # => nil
account.instance_variable_get("@token_digest") # => "1.yCZGH0QEk8+OPT0ad29wVmCkvr/7NXZjZtxu23v2j9HKfehndH0qv9MsF4ME\n"
The @token_digest
value, like the keychain, also consists of two segments, <version>.<data>
. The version matches the key version used to encrypt the data. This way, whenever data is accessed via token
, it knows which secret to use to decrypt the data.
To clear the token, simply assign nil
to it.
account.token = nil
account.token_digest # => nil
This is a general purpose library, and while its only hard dependency is rbnacl (libsodium), it was designed to work seamlessly with Active Record.
class User < ActiveRecord::Base
include AttrEncrypter::Accessors
attr_encrypter ENV["KEYCHAIN"], :token
end
This assumes that you have a users table in the database, containing a column named token_digest
of type text.
You'll want to rotate your keys at some point.
First, add a second key to the keychain (ENV["KEYCHAIN"]
in this case).
To generate version 2 you can again use the following function, but this time using the version argument.
AttrEncrypter::Generator.generate_key 2 # or 3, 4, 5...
The keychain format allows any kind of whitespace to delimit keys.
ENV["KEYCHAIN"] = "<version>.<secret> <version>.<secret> <version>.<secret>"
For example.
ENV["KEYCHAIN"] = <<-EOS
1.c1dbb0dd094d4f40916c9cc0d8c974151949f105c499366b2acd9da76de7e5e9
2.3054563b2d80ae13c6e115405d6263e70be004f81eb3982f4a61ff9e9821e7d4
EOS
Then simply reassign the token to re-encrypt the token with key version 2.
User.find_each do |user|
user.token = user.token
user.save
end
The user.token
(reader) decrypts the existing encrypted token from token_digest
back to its unencrypted form using key version 1. It then uses the highest key version in the keychain, version 2, to re-encrypt the token with user.token=
which overwrites the key version 1-encrypted token in token_digest
with the key version 2-encrypted token. We then persist the key version 2-encrypted token to the database.
<version>.<secret>
).Bug reports and pull requests are welcome on GitHub at https://github.com/mrrooijen/attr_encrypter.
First, install libsodium on your machine, and then install the remaining development dependencies:
$ bundle
To open an interactive console:
$ bundle console
To run the tests:
$ bundle exec rake
To view the code coverage (generated after each test run):
$ open coverage/index.html
To run the local documentation server:
$ bundle exec rake doc
To build a gem:
$ bundle exec rake build
To build and install a gem on your local machine:
$ bundle exec rake install
For a list of available tasks:
$ bundle exec rake --tasks
Released under the MIT License by Michael van Rooijen.
FAQs
Unknown package
We found that attr_encrypter demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.