mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-23 09:42:53 +00:00
fix(pairing): warn that pairing links grant daemon access (#3734)
A pairing offer remains valid across daemon restarts, so remove the incorrect rotation guidance and warn users where the durable credential is displayed.
This commit is contained in:
@@ -113,6 +113,11 @@ export async function enableRelayAndExpectOffer(page: Page): Promise<void> {
|
||||
export async function expectPairingOffer(page: Page): Promise<void> {
|
||||
await expect(page.getByRole("img", { name: "Pairing QR code" })).toBeVisible();
|
||||
await expect(page.getByRole("textbox", { name: "Pairing link" })).toHaveValue(/#offer=/);
|
||||
await expect(
|
||||
page.getByRole("alert").filter({
|
||||
hasText: "Treat this pairing link like a password. Anyone with it can access this daemon.",
|
||||
}),
|
||||
).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: "Copy", exact: true })).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: "Enable relay", exact: true })).toHaveCount(0);
|
||||
}
|
||||
|
||||
@@ -262,6 +262,7 @@ function PairingOffer(props: PairDeviceBodyProps & { offer: { url: string } }) {
|
||||
{props.copied ? t("pairing.device.copied") : t("pairing.device.copy")}
|
||||
</Button>
|
||||
</View>
|
||||
<Alert variant="warning" description={t("pairing.device.securityWarning")} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1630,6 +1630,8 @@ export const ar: TranslationResources = {
|
||||
updateRequired: "حدّث المضيف لتمكين التتابع من Paseo Desktop.",
|
||||
unavailable: "عرض الاقتران غير متاح.",
|
||||
hint: "قم بمسح رمز QR هذا باستخدام Paseo على هاتفك، أو انسخ الرابط أدناه.",
|
||||
securityWarning:
|
||||
"تعامل مع رابط الاقتران هذا ككلمة مرور. يمكن لأي شخص يملكه الوصول إلى هذا البرنامج الخفي.",
|
||||
qrUnavailable: "رمز QR غير متاح.",
|
||||
qrAccessibility: "رمز QR للإقران",
|
||||
retry: "أعد المحاولة",
|
||||
|
||||
@@ -1640,6 +1640,8 @@ export const en = {
|
||||
updateRequired: "Update the host to enable relay from Paseo Desktop.",
|
||||
unavailable: "Pairing offer unavailable.",
|
||||
hint: "Scan this QR code with Paseo on your phone, or copy the link below.",
|
||||
securityWarning:
|
||||
"Treat this pairing link like a password. Anyone with it can access this daemon.",
|
||||
qrUnavailable: "QR code unavailable.",
|
||||
qrAccessibility: "Pairing QR code",
|
||||
retry: "Retry",
|
||||
|
||||
@@ -1676,6 +1676,8 @@ export const es: TranslationResources = {
|
||||
updateRequired: "Actualice el host para habilitar el relé desde Paseo Desktop.",
|
||||
unavailable: "Oferta de maridaje no disponible.",
|
||||
hint: "Escanee este códigoQRconPaseoen su teléfono o copie el enlace a continuación.",
|
||||
securityWarning:
|
||||
"Trata este enlace de emparejamiento como una contraseña. Cualquiera que lo tenga puede acceder a este daemon.",
|
||||
qrUnavailable: "CódigoQRno disponible.",
|
||||
qrAccessibility: "Código QR de emparejamiento",
|
||||
retry: "Rever",
|
||||
|
||||
@@ -1680,6 +1680,8 @@ export const fr: TranslationResources = {
|
||||
updateRequired: "Mettez à jour l’hôte pour activer le relais depuis Paseo Desktop.",
|
||||
unavailable: "Offre de jumelage indisponible.",
|
||||
hint: "Scannez ce codeQRavecPaseosur votre téléphone ou copiez le lien ci-dessous.",
|
||||
securityWarning:
|
||||
"Traitez ce lien d’association comme un mot de passe. Toute personne qui le possède peut accéder à ce daemon.",
|
||||
qrUnavailable: "CodeQRindisponible.",
|
||||
qrAccessibility: "Code QR de couplage",
|
||||
retry: "Réessayer",
|
||||
|
||||
@@ -1647,6 +1647,8 @@ export const ja: TranslationResources = {
|
||||
updateRequired: "Paseo Desktop からリレーを有効にするにはホストを更新してください。",
|
||||
unavailable: "ペアリングオファーが利用できません。",
|
||||
hint: "スマートフォンのPaseoでこのQRコードをスキャンするか、以下のリンクをコピーしてください。",
|
||||
securityWarning:
|
||||
"このペアリングリンクはパスワードと同様に扱ってください。リンクを知っている人は誰でもこのデーモンにアクセスできます。",
|
||||
qrUnavailable: "QRコードが利用できません。",
|
||||
qrAccessibility: "ペアリング QR コード",
|
||||
retry: "再試行",
|
||||
|
||||
@@ -1640,6 +1640,8 @@ export const ko: TranslationResources = {
|
||||
updateRequired: "Paseo 데스크톱에서 릴레이를 활성화하려면 호스트를 업데이트하세요.",
|
||||
unavailable: "페어링 정보를 사용할 수 없습니다.",
|
||||
hint: "휴대폰의 Paseo로 이 QR 코드를 스캔하거나 아래 링크를 복사하세요.",
|
||||
securityWarning:
|
||||
"이 페어링 링크는 비밀번호처럼 취급하세요. 링크를 가진 사람은 누구나 이 데몬에 접근할 수 있습니다.",
|
||||
qrUnavailable: "QR 코드를 사용할 수 없습니다.",
|
||||
qrAccessibility: "페어링 QR 코드",
|
||||
retry: "다시 시도",
|
||||
|
||||
@@ -1662,6 +1662,8 @@ export const ptBR: TranslationResources = {
|
||||
updateRequired: "Atualize o host para ativar o relay pelo Paseo Desktop.",
|
||||
unavailable: "Oferta de pareamento indisponível.",
|
||||
hint: "Escaneie este QR code com o Paseo no seu celular ou copie o link abaixo.",
|
||||
securityWarning:
|
||||
"Trate este link de pareamento como uma senha. Qualquer pessoa com o link pode acessar este daemon.",
|
||||
qrUnavailable: "QR code indisponível.",
|
||||
qrAccessibility: "Código QR de pareamento",
|
||||
retry: "Tentar novamente",
|
||||
|
||||
@@ -1660,6 +1660,8 @@ export const ru: TranslationResources = {
|
||||
updateRequired: "Обновите хост, чтобы включить ретранслятор из Paseo Desktop.",
|
||||
unavailable: "Данные для сопряжения недоступны.",
|
||||
hint: "Отсканируйте этот QR-код с помощью Paseo на телефоне или скопируйте ссылку ниже.",
|
||||
securityWarning:
|
||||
"Обращайтесь с этой ссылкой для сопряжения как с паролем. Любой, у кого она есть, может получить доступ к этому демону.",
|
||||
qrUnavailable: "QR-код недоступен.",
|
||||
qrAccessibility: "QR-код сопряжения",
|
||||
retry: "Повторить попытку",
|
||||
|
||||
@@ -1610,6 +1610,7 @@ export const zhCN: TranslationResources = {
|
||||
updateRequired: "请更新主机,以便从 Paseo Desktop 启用中继。",
|
||||
unavailable: "配对 offer 不可用。",
|
||||
hint: "用手机上的 Paseo 扫描此二维码,或复制下方链接。",
|
||||
securityWarning: "请像保管密码一样保管此配对链接。任何获得此链接的人都可以访问此守护进程。",
|
||||
qrUnavailable: "二维码不可用。",
|
||||
qrAccessibility: "配对二维码",
|
||||
retry: "重试",
|
||||
|
||||
@@ -10,6 +10,9 @@ describe("formatPairingInstructions", () => {
|
||||
|
||||
expect(output).toContain(QR);
|
||||
expect(output.split("\n")).toContain(URL);
|
||||
expect(output).toContain(
|
||||
"Treat this pairing link like a password. Anyone with it can access this daemon.",
|
||||
);
|
||||
});
|
||||
|
||||
it("does not print a QR that would reach the terminal edge", () => {
|
||||
|
||||
@@ -33,5 +33,5 @@ function formatQr(qr: string | null, columns: number | undefined): string {
|
||||
}
|
||||
|
||||
export function formatPairingInstructions({ url, qr, columns }: PairingInstructions): string {
|
||||
return `\nScan to pair:\n${formatQr(qr, columns)}\n\nPairing link:\n${url}\n`;
|
||||
return `\nScan to pair:\n${formatQr(qr, columns)}\n\nPairing link:\n${url}\n\nTreat this pairing link like a password. Anyone with it can access this daemon.\n`;
|
||||
}
|
||||
|
||||
@@ -52,8 +52,6 @@ The daemon requires a valid cryptographic handshake before processing any comman
|
||||
|
||||
The QR code or pairing link is the trust anchor. It contains the daemon's public key, which is required to establish the encrypted connection. Treat it like a password, don't share it publicly.
|
||||
|
||||
If you believe a pairing offer has been compromised, restart the daemon to generate a new session ID and rotate the relay pairing.
|
||||
|
||||
## Direct connections
|
||||
|
||||
By default, the daemon listens on `127.0.0.1:6767` (localhost only). This is safe for local CLI usage but not reachable from your phone or other devices.
|
||||
|
||||
Reference in New Issue
Block a user