Skip to content

Commit b87ff3e

Browse files
fix: security advisory (#297)
* fix(encryption): change encryption method to AES-GCM * fix(sec): remove dummy postgres addresses from compose files * fix(sec): add .env to gitignore * fix(sec): put docker-compose specific env files in .env.docker * fix(sec): add encryption tag to db
1 parent 59bc5fd commit b87ff3e

8 files changed

Lines changed: 40 additions & 19 deletions

File tree

.env

Whitespace-only changes.

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ Thumbs.db
4343
**/@generated
4444
.nx-container
4545

46+
.env
4647
.env.local
48+
.env.docker
4749
schema.graphql
4850

4951
# temp
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/*
2+
Warnings:
3+
4+
- Added the required column `encryptionTag` to the `ProviderApiKey` table without a default value. This is not possible if the table is not empty.
5+
6+
*/
7+
-- AlterTable
8+
ALTER TABLE "ProviderApiKey" ADD COLUMN "encryptionTag" TEXT NOT NULL;

apps/server/prisma/schema.prisma

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ model ProviderApiKey {
174174
encryptedData String
175175
/// @HideField({ input: true, output: true })
176176
encryptedDataKey String
177+
/// @HideField({ input: true, output: true })
178+
encryptionTag String
177179
censoredValue String
178180
provider String
179181
organizationId String

apps/server/src/app/credentials/provider-api-keys.service.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { Injectable } from "@nestjs/common";
22
import { PrismaService } from "../prisma.service";
33
import { EncryptionService } from "../encryption/encryption.service";
44
import { ProviderApiKey } from "@prisma/client";
5-
import { StringFilter } from "../../@generated/prisma/string-filter.input";
65

76
@Injectable()
87
export class ProviderApiKeysService {
@@ -21,7 +20,8 @@ export class ProviderApiKeysService {
2120
async decryptProviderApiKey(key: ProviderApiKey): Promise<string> {
2221
const decrypted = await this.encryptionService.decrypt(
2322
key.encryptedData,
24-
key.encryptedDataKey
23+
key.encryptedDataKey,
24+
key.encryptionTag
2525
);
2626
return decrypted;
2727
}
@@ -42,7 +42,7 @@ export class ProviderApiKeysService {
4242
where: { provider, organizationId },
4343
});
4444

45-
const { encryptedData, encryptedDataKey } =
45+
const { encryptedData, encryptedDataKey, encryptionTag } =
4646
await this.encryptionService.encrypt(value);
4747

4848
const censoredValue = this.censorApiKey(value);
@@ -55,6 +55,7 @@ export class ProviderApiKeysService {
5555
data: {
5656
encryptedData,
5757
encryptedDataKey,
58+
encryptionTag,
5859
censoredValue,
5960
},
6061
});
@@ -67,6 +68,7 @@ export class ProviderApiKeysService {
6768
provider,
6869
encryptedData,
6970
encryptedDataKey,
71+
encryptionTag,
7072
censoredValue,
7173
organizationId,
7274
},

apps/server/src/app/encryption/encryption.service.ts

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,35 +48,40 @@ export class EncryptionService {
4848
async encrypt(data: string): Promise<{
4949
encryptedData: string;
5050
encryptedDataKey: string;
51+
encryptionTag: string;
5152
}> {
5253
this.logger.info("Encrypting data");
5354

5455
const dataKey = await this.generateDataKey();
55-
const iv = crypto.randomBytes(16);
56-
const cipher = crypto.createCipheriv("aes-256-cbc", dataKey.plaintext, iv);
57-
const encrypted = Buffer.concat([
58-
cipher.update(data, "utf8"),
59-
cipher.final(),
60-
]);
61-
const encryptedData = Buffer.concat([iv, encrypted]);
56+
const iv = crypto.randomBytes(12); // 12 bytes is recommended for GCM
57+
const cipher = crypto.createCipheriv("aes-256-gcm", dataKey.plaintext, iv);
58+
let encrypted = cipher.update(data, "utf8");
59+
encrypted = Buffer.concat([encrypted, cipher.final()]);
6260

6361
return {
64-
encryptedData: encryptedData.toString("hex"),
62+
encryptedData: Buffer.concat([iv, encrypted]).toString("hex"),
6563
encryptedDataKey: Buffer.from(dataKey.ciphertext).toString("base64"),
64+
encryptionTag: cipher.getAuthTag().toString("hex"), // Store the tag for verification during decryption
6665
};
6766
}
6867

69-
async decrypt(encryptedData: string, dataKeyBase64: string): Promise<string> {
68+
async decrypt(
69+
encryptedData: string,
70+
dataKeyBase64: string,
71+
tagHex: string
72+
): Promise<string> {
7073
this.logger.info("Decrypting data");
7174

7275
const encryptedDataBuffer = Buffer.from(encryptedData, "hex");
7376
const { Plaintext: dataKey } = await this.kms.decrypt({
7477
CiphertextBlob: Buffer.from(dataKeyBase64, "base64"),
7578
});
7679

77-
const iv = encryptedDataBuffer.slice(0, 16);
78-
const data = encryptedDataBuffer.slice(16);
79-
const decipher = crypto.createDecipheriv("aes-256-cbc", dataKey, iv);
80+
const iv = encryptedDataBuffer.slice(0, 12);
81+
const data = encryptedDataBuffer.slice(12);
82+
const decipher = crypto.createDecipheriv("aes-256-gcm", dataKey, iv);
83+
decipher.setAuthTag(Buffer.from(tagHex, "hex")); // Set the authentication tag for verification
84+
8085
return decipher.update(data) + decipher.final("utf8");
8186
}
8287
}

docker-compose.infra.yaml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ services:
2424
dockerfile: ./apps/server/Dockerfile
2525
entrypoint: /bin/sh
2626
command: -c "npx prisma migrate deploy"
27-
environment:
28-
- DATABASE_URL=postgres://postgres:postgres@postgres:5432/pezzo
27+
env_file:
28+
- ./.env.docker
2929
depends_on:
3030
postgres:
3131
condition: service_healthy
@@ -72,8 +72,10 @@ services:
7272
depends_on:
7373
postgres:
7474
condition: service_healthy
75+
env_file:
76+
- ./.env.docker
7577
environment:
76-
POSTGRES_CONNECTION_URI: postgres://postgres:postgres@postgres:5432/supertokens
78+
POSTGRES_CONNECTION_URI: "${SUPERTOKENS_DATABASE_URL}"
7779
healthcheck:
7880
test: >
7981
bash -c 'exec 3<>/dev/tcp/127.0.0.1/3567 && echo -e "GET /hello HTTP/1.1\r\nhost: 127.0.0.1:3567\r\nConnection: close\r\n\r\n" >&3 && cat <&3 | grep "Hello"'

docker-compose.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ services:
1111
env_file:
1212
- ./.env
1313
- ./.env.local
14+
- ./.env.docker
1415
- ./apps/server/.env
1516
- ./apps/server/.env.local
1617
environment:
17-
- DATABASE_URL=postgres://postgres:postgres@postgres:5432/pezzo
1818
- SUPERTOKENS_CONNECTION_URI=http://supertokens:3567
1919
- CLICKHOUSE_HOST=clickhouse
2020
- REDIS_URL=redis://redis-stack-server:6379

0 commit comments

Comments
 (0)