mirror of
https://github.com/bulwarkmail/native.git
synced 2026-10-31 16:06:32 +00:00
fix: allow cleartext server URLs only on local hosts, name the mail domain as TOTP issuer and guard external links
This commit is contained in:
Binary file not shown.
@@ -12,6 +12,24 @@ import { secureFetch } from './client-cert';
|
||||
export const DISCOVERY_TIMEOUT_MS = 2500;
|
||||
|
||||
const SCHEME_RE = /^([a-z][a-z0-9+.-]*):\/\//i;
|
||||
|
||||
/** Loopback, the Android emulator's host alias, RFC 1918 ranges and `.local`. */
|
||||
export function isLocalHost(url: string): boolean {
|
||||
const m = /^[a-z][a-z0-9+.-]*:\/\/([^/?#:]+)/i.exec(url);
|
||||
const host = (m ? m[1] : '').toLowerCase();
|
||||
if (!host) return false;
|
||||
if (host === 'localhost' || host === '127.0.0.1' || host === '::1' || host === '10.0.2.2') return true;
|
||||
if (host.endsWith('.local') || host.endsWith('.localhost')) return true;
|
||||
const ip = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/.exec(host);
|
||||
if (!ip) return false;
|
||||
const [a, b] = [Number(ip[1]), Number(ip[2])];
|
||||
return a === 10 || (a === 172 && b >= 16 && b <= 31) || (a === 192 && b === 168);
|
||||
}
|
||||
|
||||
/** True when a normalised server URL uses plain http. */
|
||||
export function isCleartextUrl(url: string): boolean {
|
||||
return /^http:\/\//i.test(url);
|
||||
}
|
||||
const EMAIL_RE = /^[^\s@]+@([^\s@]+\.[^\s@]+)$/;
|
||||
|
||||
/**
|
||||
@@ -32,6 +50,12 @@ export function normalizeServerUrl(input: string): string | null {
|
||||
value = `https://${value}`;
|
||||
}
|
||||
|
||||
// Basic credentials travel in every request. Cleartext is only acceptable
|
||||
// for a server on the developer's own machine / LAN; on a public host it
|
||||
// would fail opaquely on Android anyway (no cleartext traffic allowed) and
|
||||
// leak the password on iOS.
|
||||
if (/^http:\/\//i.test(value) && !isLocalHost(value)) return null;
|
||||
|
||||
// Someone pasting the endpoint they found in the webmail's settings gets the
|
||||
// same result as someone typing the address they use in the browser.
|
||||
value = value
|
||||
|
||||
+6
-2
@@ -46,9 +46,13 @@ export interface TotpEnrolment {
|
||||
url: string;
|
||||
}
|
||||
|
||||
export function generateTotpEnrolment(accountLabel: string): TotpEnrolment {
|
||||
export function generateTotpEnrolment(accountLabel: string, issuerOverride?: string): TotpEnrolment {
|
||||
const secret = base32Encode(randomBytes(SECRET_BYTES));
|
||||
const issuer = 'Stalwart';
|
||||
// The issuer is what the authenticator app shows above the code; the
|
||||
// account's mail domain identifies the service far better than the
|
||||
// server software's name.
|
||||
const at = accountLabel.lastIndexOf('@');
|
||||
const issuer = issuerOverride || (at > 0 ? accountLabel.slice(at + 1) : 'Bulwark');
|
||||
const label = accountLabel || 'account';
|
||||
const params = new URLSearchParams({
|
||||
secret,
|
||||
|
||||
Reference in New Issue
Block a user