Skip to content

Commit 37420eb

Browse files
authored
fix(ipsec): reject curly braces in pre-shared keys (#763)
NethServer/nethsecurity#1631
1 parent 655e5cc commit 37420eb

5 files changed

Lines changed: 52 additions & 7 deletions

File tree

src/components/standalone/ipsec_tunnel/CreateOrEditTunnelDrawer.vue

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
MessageBag,
99
validateHost,
1010
validateIp4Cidr,
11+
validateNoCurlyBraces,
1112
validatePositiveInteger,
1213
validateRequired,
1314
validateRequiredOption,
@@ -355,12 +356,10 @@ function validateFormByStep(step: number): boolean {
355356
if (presharedKeyMode.value === 'generate') {
356357
return true
357358
} else {
358-
const validator = validateRequired(presharedKey.value)
359-
if (!validator.valid) {
360-
validationErrorBag.value.set('presharedKey', [t(validator.errMessage as string)])
361-
return false
362-
}
363-
return true
359+
return runValidators(
360+
[validateRequired(presharedKey.value), validateNoCurlyBraces(presharedKey.value)],
361+
'presharedKey'
362+
)
364363
}
365364
} else {
366365
const step3Validators: [validationOutput[], string][] = [
@@ -611,7 +610,15 @@ watch(
611610
v-model="presharedKey"
612611
:invalid-message="validationErrorBag.getFirstFor('presharedKey')"
613612
:label="id ? t('standalone.ipsec_tunnel.pre_shared_key') : ''"
614-
/>
613+
>
614+
<template #tooltip>
615+
<NeTooltip>
616+
<template #content>
617+
{{ t('standalone.ipsec_tunnel.pre_shared_key_invalid_chars_tooltip') }}
618+
</template>
619+
</NeTooltip>
620+
</template>
621+
</NeTextInput>
615622
<NeCopyField v-else :value="generatedPresharedKey" />
616623

617624
<div>

src/i18n/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
"required": "Required",
8585
"unique": "Enter a unique value",
8686
"invalid": "Field has incorrect value",
87+
"curly_braces_not_allowed": "Curly brace characters are not allowed",
8788
"invalid_format": "File is not a valid PEM format",
8889
"expired": "Certificate has expired",
8990
"key_mismatch": "Private key does not match the certificate",
@@ -2182,6 +2183,7 @@
21822183
"choose_wan": "Choose WAN",
21832184
"add_network": "Add network",
21842185
"pre_shared_key": "Pre-shared key",
2186+
"pre_shared_key_invalid_chars_tooltip": "The characters '\\{' and '\\}' are not allowed in the pre-shared key",
21852187
"use_generated_key": "Use generated key",
21862188
"use_custom_key": "Use custom key",
21872189
"dpd_dead_peer_detection": "DPD (dead peer detection)",

src/i18n/it.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
"http_404": "Risorsa non trovata",
8383
"http_500": "Errore del server",
8484
"required": "Obbligatorio",
85+
"curly_braces_not_allowed": "I caratteri di parentesi graffe non sono consentiti",
8586
"invalid_hostname": "Nome host non valido",
8687
"hostname_is_too_long": "Il nome host ha troppi caratteri",
8788
"cannot_save_configuration": "Impossibile salvare la configurazione",
@@ -1563,6 +1564,7 @@
15631564
"wan_ip_address": "Indirizzo IP WAN",
15641565
"enable": "Abilita",
15651566
"pre_shared_key": "Chiave condivisa",
1567+
"pre_shared_key_invalid_chars_tooltip": "I caratteri '\\{' e '\\}' non sono consentiti nella chiave condivisa",
15661568
"remote_ip_address_tooltip": "Inserire l'indirizzo IP pubblico o l'host del server remoto. Se il server remoto ha un indirizzo IP dinamico, è sufficiente inserire 'qualsiasi'",
15671569
"edit_ipsec_tunnel": "Modifica tunnel IPsec",
15681570
"ike_version": "Versione IKE",
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { validateNoCurlyBraces } from '@/lib/validation'
3+
4+
describe('validateNoCurlyBraces', () => {
5+
it('accepts an empty string', () => {
6+
expect(validateNoCurlyBraces('').valid).toBe(true)
7+
})
8+
9+
it('accepts whitespace-only values', () => {
10+
expect(validateNoCurlyBraces(' ').valid).toBe(true)
11+
})
12+
13+
it.each(['{secret', 'secret}', 'sec{ret}', '{}'])('rejects "%s"', (input) => {
14+
const result = validateNoCurlyBraces(input)
15+
16+
expect(result.valid).toBe(false)
17+
expect(result.errMessage).toBeDefined()
18+
})
19+
20+
it('accepts special characters other than curly braces', () => {
21+
expect(validateNoCurlyBraces('p@ssw0rd![]()').valid).toBe(true)
22+
})
23+
})

src/lib/validation.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,17 @@ export function validateNoSpaces(value: string): validationOutput {
733733
return { valid: true }
734734
}
735735

736+
/**
737+
* Validate if the string doesn't have curly braces.
738+
* @param value
739+
*/
740+
export function validateNoCurlyBraces(value: string): validationOutput {
741+
if (value.includes('{') || value.includes('}')) {
742+
return { valid: false, errMessage: 'error.curly_braces_not_allowed' }
743+
}
744+
return { valid: true }
745+
}
746+
736747
/**
737748
* Validate a 6-digit code
738749
*

0 commit comments

Comments
 (0)