From 1385021dcefb5f4e98c3b912d47ac1b915f7152b Mon Sep 17 00:00:00 2001 From: jakub-tldr <78603704+jakub-tldr@users.noreply.github.com> Date: Wed, 19 Nov 2025 16:25:29 +0100 Subject: [PATCH 1/3] filter mfa locations, validate ip/domain in wizard --- .../steps/MethodStep/MethodStep.tsx | 12 +++++++----- .../WizardNetworkConfiguration.tsx | 5 ++++- web/src/shared/validators.ts | 18 ++++++++++++------ 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/web/src/pages/devices/modals/AddStandaloneDeviceModal/steps/MethodStep/MethodStep.tsx b/web/src/pages/devices/modals/AddStandaloneDeviceModal/steps/MethodStep/MethodStep.tsx index a054a9150c..ef6b9f0853 100644 --- a/web/src/pages/devices/modals/AddStandaloneDeviceModal/steps/MethodStep/MethodStep.tsx +++ b/web/src/pages/devices/modals/AddStandaloneDeviceModal/steps/MethodStep/MethodStep.tsx @@ -88,11 +88,13 @@ export const MethodStep = () => { // biome-ignore lint/correctness/useExhaustiveDependencies: migration, checkMeLater useEffect(() => { if (networks) { - const options: SelectOption[] = networks.map((n) => ({ - key: n.id, - value: n.id, - label: n.name, - })); + const options: SelectOption[] = networks + .filter((n) => n.location_mfa_mode === 'disabled') + .map((n) => ({ + key: n.id, + value: n.id, + label: n.name, + })); setState({ networks, networkOptions: options, diff --git a/web/src/pages/wizard/components/WizardNetworkConfiguration/WizardNetworkConfiguration.tsx b/web/src/pages/wizard/components/WizardNetworkConfiguration/WizardNetworkConfiguration.tsx index 8d416e221e..6ecdd20349 100644 --- a/web/src/pages/wizard/components/WizardNetworkConfiguration/WizardNetworkConfiguration.tsx +++ b/web/src/pages/wizard/components/WizardNetworkConfiguration/WizardNetworkConfiguration.tsx @@ -118,7 +118,10 @@ export const WizardNetworkConfiguration = () => { .string() .trim() .min(1, LL.form.error.required()) - .refine((val) => validateIpOrDomain(val), LL.form.error.endpoint()), + .refine( + (val) => validateIpOrDomain(val, false, true), + LL.form.error.endpoint(), + ), port: z .number({ invalid_type_error: LL.form.error.invalid(), diff --git a/web/src/shared/validators.ts b/web/src/shared/validators.ts index 77df62d88a..8d99664003 100644 --- a/web/src/shared/validators.ts +++ b/web/src/shared/validators.ts @@ -1,6 +1,5 @@ import ipaddr from 'ipaddr.js'; import { z } from 'zod'; - import { patternValidDomain, patternValidWireguardKey } from './patterns'; export const validateWireguardPublicKey = (props: { @@ -24,11 +23,13 @@ export const validateIpOrDomain = ( allowMask = false, allowIPv6 = false, ): boolean => { - return ( - (allowIPv6 && validateIPv6(val, allowMask)) || - validateIPv4(val, allowMask) || - patternValidDomain.test(val) - ); + const hasLetter = /\p{L}/u.test(val); + const hasColon = /:/.test(val); + if (!hasLetter || hasColon) { + return (allowIPv6 && validateIPv6(val, allowMask)) || validateIPv4(val, allowMask); + } else { + return patternValidDomain.test(val); + } }; // Returns false when invalid @@ -41,6 +42,7 @@ export const validateIpList = ( .replace(' ', '') .split(splitWith) .every((el) => { + if (!el.includes('/') && allowMasks) return false; return validateIPv4(el, allowMasks) || validateIPv6(el, allowMasks); }); }; @@ -76,6 +78,10 @@ export const validateIPv4 = (ip: string, allowMask = false): boolean => { return ipaddr.IPv4.isValidCIDR(ip); } } + const ipv4Pattern = /^(\d{1,3}\.){3}\d{1,3}$/; + if (!ipv4Pattern.test(ip)) { + return false; + } return ipaddr.IPv4.isValid(ip); }; From 2dbed0c0a692bd001c305d01c9307a9c95cca028 Mon Sep 17 00:00:00 2001 From: jakub-tldr <78603704+jakub-tldr@users.noreply.github.com> Date: Fri, 21 Nov 2025 10:49:24 +0100 Subject: [PATCH 2/3] Reject device without name --- crates/defguard_core/src/grpc/enrollment.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/defguard_core/src/grpc/enrollment.rs b/crates/defguard_core/src/grpc/enrollment.rs index c7a43069ba..d3c8b1edb9 100644 --- a/crates/defguard_core/src/grpc/enrollment.rs +++ b/crates/defguard_core/src/grpc/enrollment.rs @@ -631,6 +631,8 @@ impl EnrollmentServer { return Err(Status::invalid_argument("invalid device type")); } + + device.wireguard_pubkey.clone_from(&request.pubkey); device.configured = true; @@ -695,6 +697,9 @@ impl EnrollmentServer { None, true, ); + if device.name.is_empty(){ + return Err(Status::invalid_argument("Cannot add a new device with no name. You may be trying to add a new user device as a network device. Defguard CLI supports only network devices.")); + } let device = device.save(&mut *transaction).await.map_err(|err| { error!( "Failed to save device {}, pubkey {} for user {}({:?}): {err}", From 4221b9d40b9cd6a93e4e150e245d6566be2cba45 Mon Sep 17 00:00:00 2001 From: jakub-tldr <78603704+jakub-tldr@users.noreply.github.com> Date: Fri, 21 Nov 2025 11:00:05 +0100 Subject: [PATCH 3/3] cargo fmt --- crates/defguard_core/src/grpc/enrollment.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/defguard_core/src/grpc/enrollment.rs b/crates/defguard_core/src/grpc/enrollment.rs index d3c8b1edb9..13b0733ea5 100644 --- a/crates/defguard_core/src/grpc/enrollment.rs +++ b/crates/defguard_core/src/grpc/enrollment.rs @@ -631,8 +631,6 @@ impl EnrollmentServer { return Err(Status::invalid_argument("invalid device type")); } - - device.wireguard_pubkey.clone_from(&request.pubkey); device.configured = true; @@ -697,8 +695,10 @@ impl EnrollmentServer { None, true, ); - if device.name.is_empty(){ - return Err(Status::invalid_argument("Cannot add a new device with no name. You may be trying to add a new user device as a network device. Defguard CLI supports only network devices.")); + if device.name.is_empty() { + return Err(Status::invalid_argument( + "Cannot add a new device with no name. You may be trying to add a new user device as a network device. Defguard CLI supports only network devices.", + )); } let device = device.save(&mut *transaction).await.map_err(|err| { error!(