Skip to content

Commit

Permalink
#2183 Blind carbon copy leak fix (#2329)
Browse files Browse the repository at this point in the history
* fix: blink carbon copy link

* fix: remove unused code

* fix: ui test

* fix: pr reviews
  • Loading branch information
ioanmo226 authored Aug 29, 2023
1 parent 040fc13 commit 5d53fc9
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 12 deletions.
4 changes: 2 additions & 2 deletions FlowCrypt/Core/CoreTypes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,13 @@ struct SendableMsg: Equatable {
}

extension SendableMsg {
func copy(body: SendableMsgBody, atts: [Attachment], pubKeys: [String]?) -> SendableMsg {
func copy(body: SendableMsgBody, atts: [Attachment], pubKeys: [String]?, includeBcc: Bool = true) -> SendableMsg {
SendableMsg(
text: body.text,
html: body.html,
to: self.to,
cc: self.cc,
bcc: self.bcc,
bcc: includeBcc ? bcc : [],
from: self.from,
subject: self.subject,
replyToMsgId: self.replyToMsgId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,8 @@ extension ComposeMessageHelper {
let sendableMsg = message.copy(
body: messageBody,
atts: [encryptedBodyAttachment] + encryptedAttachments,
pubKeys: nil
pubKeys: nil,
includeBcc: true
)

return try await composeEmail(msg: sendableMsg)
Expand Down Expand Up @@ -404,7 +405,9 @@ extension ComposeMessageHelper {
let msgWithReplyToken = message.copy(
body: bodyWithReplyToken,
atts: message.atts,
pubKeys: nil
pubKeys: nil,
// Fix blind carbon copy leak. ref: https://github.com/FlowCrypt/flowcrypt-ios/issues/2183
includeBcc: false
)
let pgpMimeWithAttachments = try await composeEmail(msg: msgWithReplyToken)

Expand Down
3 changes: 2 additions & 1 deletion FlowCryptAppTests/Core/CoreTypesTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ class CoreTypesTest: XCTestCase {
let msgCopy = msg.copy(
body: copyBody,
atts: copyAttachments,
pubKeys: copyPubKeys
pubKeys: copyPubKeys,
includeBcc: true
)

XCTAssertEqual(msgCopy.text, copyBody.text)
Expand Down
27 changes: 20 additions & 7 deletions appium/api-mocks/apis/fes/fes-endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,26 @@ export const getMockFesEndpoints = (mockConfig: MockConfig, fesConfig: FesConfig
// body is a mime-multipart string, we're doing a few smoke checks here without parsing it
if (req.method === 'POST') {
expectContains(body, '-----BEGIN PGP MESSAGE-----');
expectContains(body, '"associateReplyToken":"mock-fes-reply-token"');
expectContains(body, '"to":["[email protected]"]');
expectContains(body, '"cc":[]');
expectContains(body, '"bcc":["[email protected]"]');
authenticate(req);
expectContains(body, '"from":"[email protected]:8001"');
return { url: `${mockConfig}/message/FES-MOCK-MESSAGE-ID` };
const match = String(body).match(/Content-Type: application\/json\s*\n\s*(\{.*\})/);

if (!match) {
throw new FesHttpErr('Bad request', Status.BAD_REQUEST);
}
const messageData = JSON.parse(match[0]);
const { associateReplyToken, to, cc, bcc } = messageData;

expect(associateReplyToken).toBe('mock-fes-reply-token');

if (fesConfig.messageUploadCheck) {
const { to: toCheck, cc: ccCheck, bcc: bccCheck } = fesConfig.messageUploadCheck;
if (toCheck) expect(to).toBe(toCheck);
if (ccCheck) expect(cc).toBe(ccCheck);
if (bccCheck) expect(bcc).toBe(bccCheck);
}

return {
url: `https://flowcrypt.com/shared-tenant-fes/message/6da5ea3c-d2d6-4714-b15e-f29c805e5c6a`,
};
}
throw new FesHttpErr('Not Found', Status.NOT_FOUND);
},
Expand Down
1 change: 1 addition & 0 deletions appium/api-mocks/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ export class Api<REQ, RES> {
req.url!.startsWith('/api/message/upload') || // flowcrypt.com/api pwd msg
(req.url!.startsWith('/attester/pub/') && req.method === 'POST') || // attester submit
req.url!.startsWith('/api/v1/message') || // FES pwd msg
req.url!.startsWith('/fes/api/v1/message') || // Shared TENANT FES pwd msg
req.url!.startsWith('/token') // gmail auth token
) {
parsedBody = body.toString();
Expand Down
7 changes: 7 additions & 0 deletions appium/api-mocks/lib/configuration-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,15 @@ type Fes$ClientConfiguration = {
enforce_keygen_expire_months?: number;
};

type FesMessageUploadCheck = {
to?: string[];
cc?: string[];
bcc?: string[];
};

export type FesConfig = {
returnError?: { code: number; message: string; format?: 'wrong-json' | 'wrong-text' };
messageUploadCheck?: FesMessageUploadCheck;
clientConfiguration?: Fes$ClientConfiguration;
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { MailFolderScreen, NewMessageScreen, SetupKeyScreen, SplashScreen } from '../../../screenobjects/all-screens';

import { MockApi } from 'api-mocks/mock';
import { MockApiConfig } from 'api-mocks/mock-config';
import { CommonData } from '../../../data';

describe('COMPOSE EMAIL: ', () => {
it('check sending password protected message bcc leakage', async () => {
const recipient = CommonData.recipientWithoutPublicKey.email;
const emailSubject = CommonData.recipientWithoutPublicKey.subject;
const emailText = CommonData.simpleEmail.message;
const emailPassword = CommonData.recipientWithoutPublicKey.password;
const bcc = '[email protected]';

const mockApi = new MockApi();

mockApi.ekmConfig = MockApiConfig.defaultEnterpriseEkmConfiguration;
mockApi.fesConfig = {
...MockApiConfig.defaultEnterpriseFesConfiguration,
messageUploadCheck: {
to: [recipient],
cc: [],
bcc: [],
},
};
mockApi.attesterConfig = {
servedPubkeys: {},
};

await mockApi.withMockedApis(async () => {
await SplashScreen.mockLogin();
await SetupKeyScreen.setPassPhrase();
await MailFolderScreen.checkInboxScreen();

await MailFolderScreen.clickCreateEmail();
await NewMessageScreen.composeEmail(recipient, emailSubject, emailText, undefined, bcc);
await NewMessageScreen.checkFilledComposeEmailInfo({
recipients: [recipient],
subject: emailSubject,
message: emailText,
bcc: [bcc],
});
await NewMessageScreen.clickPasswordCell();
await NewMessageScreen.setMessagePassword(emailPassword);
await NewMessageScreen.clickSendButton();
});
});
});

0 comments on commit 5d53fc9

Please sign in to comment.