1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-06 00:13:28 +00:00
This commit is contained in:
Jordan Aasen
2025-03-27 10:46:39 -07:00
committed by GitHub
parent 7d3e43abd8
commit 93a289bfa8
2 changed files with 57 additions and 18 deletions

View File

@@ -305,51 +305,86 @@ describe("Cipher Service", () => {
});
describe("cipher.key", () => {
it("is null when feature flag is false", async () => {
configService.getFeatureFlag.mockResolvedValue(false);
beforeEach(() => {
keyService.getOrgKey.mockReturnValue(
Promise.resolve<any>(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey),
);
});
it("is null when feature flag is false", async () => {
configService.getFeatureFlag.mockResolvedValue(false);
const cipher = await cipherService.encrypt(cipherView, userId);
expect(cipher.key).toBeNull();
});
it("is defined when feature flag flag is true", async () => {
configService.getFeatureFlag.mockResolvedValue(true);
describe("when feature flag is true", () => {
beforeEach(() => {
configService.getFeatureFlag.mockResolvedValue(true);
});
const cipher = await cipherService.encrypt(cipherView, userId);
it("is null when the cipher is not viewPassword", async () => {
cipherView.viewPassword = false;
expect(cipher.key).toBeDefined();
const cipher = await cipherService.encrypt(cipherView, userId);
expect(cipher.key).toBeNull();
});
it("is defined when the cipher is viewPassword", async () => {
cipherView.viewPassword = true;
const cipher = await cipherService.encrypt(cipherView, userId);
expect(cipher.key).toBeDefined();
});
});
});
describe("encryptWithCipherKey", () => {
beforeEach(() => {
jest.spyOn<any, string>(cipherService, "encryptCipherWithCipherKey");
keyService.getOrgKey.mockReturnValue(
Promise.resolve<any>(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey),
);
});
it("is not called when feature flag is false", async () => {
configService.getFeatureFlag.mockResolvedValue(false);
keyService.getOrgKey.mockReturnValue(
Promise.resolve<any>(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey),
);
await cipherService.encrypt(cipherView, userId);
expect(cipherService["encryptCipherWithCipherKey"]).not.toHaveBeenCalled();
});
it("is called when feature flag is true", async () => {
configService.getFeatureFlag.mockResolvedValue(true);
keyService.getOrgKey.mockReturnValue(
Promise.resolve<any>(new SymmetricCryptoKey(new Uint8Array(32)) as OrgKey),
);
describe("when feature flag is true", () => {
beforeEach(() => {
configService.getFeatureFlag.mockResolvedValue(true);
});
await cipherService.encrypt(cipherView, userId);
it("is called when cipher viewPassword is true", async () => {
cipherView.viewPassword = true;
expect(cipherService["encryptCipherWithCipherKey"]).toHaveBeenCalled();
await cipherService.encrypt(cipherView, userId);
expect(cipherService["encryptCipherWithCipherKey"]).toHaveBeenCalled();
});
it("is not called when cipher viewPassword is false and original cipher has no key", async () => {
cipherView.viewPassword = false;
await cipherService.encrypt(cipherView, userId, undefined, undefined, new Cipher());
expect(cipherService["encryptCipherWithCipherKey"]).not.toHaveBeenCalled();
});
it("is called when cipher viewPassword is false and original cipher has a key", async () => {
cipherView.viewPassword = false;
await cipherService.encrypt(cipherView, userId, undefined, undefined, cipherObj);
expect(cipherService["encryptCipherWithCipherKey"]).toHaveBeenCalled();
});
});
});
});

View File

@@ -222,7 +222,11 @@ export class CipherService implements CipherServiceAbstraction {
cipher.reprompt = model.reprompt;
cipher.edit = model.edit;
if (await this.getCipherKeyEncryptionEnabled()) {
if (
// prevent unprivileged users from migrating to cipher key encryption
(model.viewPassword || originalCipher?.key) &&
(await this.getCipherKeyEncryptionEnabled())
) {
cipher.key = originalCipher?.key ?? null;
const userOrOrgKey = await this.getKeyForCipherKeyDecryption(cipher, userId);
// The keyForEncryption is only used for encrypting the cipher key, not the cipher itself, since cipher key encryption is enabled.