From a8eab8d7c32b32ac4971af7cb341287d08599ec8 Mon Sep 17 00:00:00 2001 From: Roma Sosnovsky Date: Mon, 8 Jun 2026 21:39:21 +0300 Subject: [PATCH] Fix email encoding for path segments --- extension/js/common/api/flowcrypt-website.ts | 3 ++- extension/js/common/api/key-server/attester.ts | 8 ++++---- extension/js/common/core/common.ts | 4 ++++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/extension/js/common/api/flowcrypt-website.ts b/extension/js/common/api/flowcrypt-website.ts index 5ddc5fd6357..f1ed89b99c8 100644 --- a/extension/js/common/api/flowcrypt-website.ts +++ b/extension/js/common/api/flowcrypt-website.ts @@ -3,6 +3,7 @@ import { Api } from './shared/api.js'; import { Browser } from '../browser/browser.js'; +import { Url } from '../core/common.js'; import { CatchHelper } from '../platform/catch-helper.js'; namespace FlowCryptWebsiteRes { @@ -11,7 +12,7 @@ namespace FlowCryptWebsiteRes { export class FlowCryptWebsite extends Api { public static pubKeyUrl = (resource: string) => { - return `https://flowcrypt.com/pub/${encodeURIComponent(resource)}`; + return `https://flowcrypt.com/pub/${Url.encodeEmailAddressForPathSegment(resource)}`; }; public static retrieveBlogPosts = async (): Promise => { diff --git a/extension/js/common/api/key-server/attester.ts b/extension/js/common/api/key-server/attester.ts index d1d185679e4..a19c258be4c 100644 --- a/extension/js/common/api/key-server/attester.ts +++ b/extension/js/common/api/key-server/attester.ts @@ -3,7 +3,7 @@ 'use strict'; import { Api } from './../shared/api.js'; -import { Dict, Str } from '../../core/common.js'; +import { Dict, Str, Url } from '../../core/common.js'; import { PubkeysSearchResult } from './../pub-lookup.js'; import { AjaxErr, ApiErr } from '../shared/api-error.js'; import { ClientConfiguration } from '../../client-configuration'; @@ -74,7 +74,7 @@ export class Attester extends Api { if (!this.clientConfiguration.canSubmitPubToAttester()) { throw new Error('Cannot replace pubkey at attester because your organisation rules forbid it'); } - await this.pubCall(`pub/${encodeURIComponent(email)}`, pubkey, { authorization: `Bearer ${idToken}` }); + await this.pubCall(`pub/${Url.encodeEmailAddressForPathSegment(email)}`, pubkey, { authorization: `Bearer ${idToken}` }); }; /** @@ -86,7 +86,7 @@ export class Attester extends Api { if (!this.clientConfiguration.canSubmitPubToAttester()) { throw new Error('Cannot replace pubkey at attester because your organisation rules forbid it'); } - return await this.pubCall(`pub/${encodeURIComponent(email)}`, pubkey); + return await this.pubCall(`pub/${Url.encodeEmailAddressForPathSegment(email)}`, pubkey); }; public welcomeMessage = async (email: string, pubkey: string, idToken: string | undefined): Promise<{ sent: boolean }> => { @@ -110,7 +110,7 @@ export class Attester extends Api { private doLookup = async (email: string): Promise => { try { - const r = await this.pubCall(`pub/${encodeURIComponent(email)}`); + const r = await this.pubCall(`pub/${Url.encodeEmailAddressForPathSegment(email)}`); return await this.getPubKeysSearchResult(r); } catch (e) { if (ApiErr.isNotFound(e)) { diff --git a/extension/js/common/core/common.ts b/extension/js/common/core/common.ts index 47935789eff..81ace34c189 100644 --- a/extension/js/common/core/common.ts +++ b/extension/js/common/core/common.ts @@ -471,6 +471,10 @@ export class Url { return link; }; + public static encodeEmailAddressForPathSegment = (email: string) => { + return encodeURIComponent(email).replace(/%40/gi, '@'); + }; + public static removeParamsFromUrl = (url: string, paramsToDelete: string[]) => { const urlParts = url.split('?'); if (!urlParts[1]) {