1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-06-27 01:19:00 +02:00

fix: md5 is deprecated and fails FEDRAMP. Replace with sha256 (#10125)

#10121 points out that we're using md5 functions still. This PR updates
our migrations to no longer use md5 at all (so if you haven't run the
migrations, you won't get email hashes until you get to the included
migration with this PR). If you've already run the migrations, we'll
drop the existing `email_hash varchar(32)` column and replace it with a
`email_hash TEXT` column.

We're also replacing the md5 function with `encode(sha256(email),
'hex')`. encode has been supported since PG10, sha256 came with PG11.

Do we want an index on the email_hash? I wasn't sure, but if we want to
do lookup we probably should have an index on it (though not a unique
one)
This commit is contained in:
Christopher Kolstad 2025-06-13 09:41:40 +02:00 committed by GitHub
parent 37a125f0b5
commit b70f862f93
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 37 additions and 15 deletions

View File

@ -104,7 +104,7 @@ export class UserStore implements IUserStore {
async insert(user: ICreateUser): Promise<User> {
const emailHash = user.email
? this.db.raw('md5(?)', [user.email])
? this.db.raw(`encode(sha256(?::bytea), 'hex')`, [user.email])
: null;
const rows = await this.db(TABLE)
.insert({

View File

@ -2,9 +2,6 @@ exports.up = (db, cb) => {
db.runSql(`
ALTER TABLE users
ADD COLUMN IF NOT EXISTS email_hash VARCHAR(32);
UPDATE users
SET email_hash = md5(email::text);
`, cb);
};

View File

@ -1,14 +1,8 @@
exports.up = (db, cb) => {
db.runSql(`
UPDATE users
SET email_hash = md5(email::text)
WHERE scim_id IS NOT NULL;
`, cb);
cb();
};
exports.down = (db, cb) => {
cb();
};

View File

@ -0,0 +1,12 @@
exports.up = function(db, cb) {
db.runSql(`
ALTER TABLE users DROP COLUMN email_hash;
ALTER TABLE users ADD COLUMN email_hash TEXT;
UPDATE users SET email_hash = encode(sha256(email::bytea), 'hex') WHERE email IS NOT NULL;
CREATE INDEX users_email_hash_idx ON users(email_hash);
`, cb);
};
exports.down = function(db, cb) {
cb();
};

View File

@ -0,0 +1,19 @@
exports.up = function(db, cb) {
db.runSql(`
WITH deleted_users AS (
SELECT (pre_data ->> 'id')::int AS user_id,
pre_data ->> 'email' AS email
FROM events
WHERE type = 'user-deleted'
AND created_at >= now() - interval '30 days'
)
UPDATE users u
SET email_hash = encode(sha256(du.email::bytea), 'hex')
FROM deleted_users du
WHERE u.id = du.user_id AND u.email IS NULL;
`, cb);
};
exports.down = function(db, cb) {
cb();
};

View File

@ -409,7 +409,7 @@ test('Anonymises name, username and email fields if anonymiseEventLog flag is se
expect(body.users[0].username).toEqual(''); // Not set, so anonymise should return the empty string.
});
test('creates user with email md5 hash', async () => {
test('creates user with email sha256 hash', async () => {
await app.request
.post('/api/admin/user-admin')
.send({
@ -424,7 +424,7 @@ test('creates user with email md5 hash', async () => {
.where({ email: 'hasher@getunleash.ai' })
.first(['email_hash']);
const expectedHash = createHash('md5')
const expectedHash = createHash('sha256')
.update('hasher@getunleash.ai')
.digest('hex');