diff --git a/ui/src/config/section/compute.js b/ui/src/config/section/compute.js
index 3b483c19b74..9940c118efe 100644
--- a/ui/src/config/section/compute.js
+++ b/ui/src/config/section/compute.js
@@ -18,6 +18,7 @@
import { shallowRef, defineAsyncComponent } from 'vue'
import store from '@/store'
import { isZoneCreated } from '@/utils/zone'
+import { escapeHtml } from '@/utils/util'
export default {
name: 'compute',
@@ -377,7 +378,7 @@ export default {
show: (record) => { return ['Stopped'].includes(record.state) && record.passwordenabled },
response: (result) => {
return {
- message: result.virtualmachine && result.virtualmachine.password ? `The password of VM ${result.virtualmachine.displayname} is ${result.virtualmachine.password}` : null,
+ message: result.virtualmachine && result.virtualmachine.password ? `The password of VM ${escapeHtml(result.virtualmachine.displayname)} is ${result.virtualmachine.password}` : null,
copybuttontext: result.virtualmachine.password ? 'label.copy.password' : null,
copytext: result.virtualmachine.password ? result.virtualmachine.password : null
}
diff --git a/ui/src/config/section/infra/routers.js b/ui/src/config/section/infra/routers.js
index e52bcd7a829..6079f4a44f2 100644
--- a/ui/src/config/section/infra/routers.js
+++ b/ui/src/config/section/infra/routers.js
@@ -17,6 +17,7 @@
import { shallowRef, defineAsyncComponent } from 'vue'
import store from '@/store'
+import { escapeHtml } from '@/utils/util'
export default {
name: 'router',
@@ -226,7 +227,7 @@ export default {
options: ['ping', 'ping6', 'traceroute', 'traceroute6', 'arping']
}
},
- response: (result) => { return result && result.diagnostics ? `Output:
${result.diagnostics.stdout}
Error: ${result.diagnostics.stderr}
Exit Code: ${result.diagnostics.exitcode}` : 'Invalid response' }
+ response: (result) => { return result && result.diagnostics ? `Output:
${escapeHtml(result.diagnostics.stdout)}
Error: ${escapeHtml(result.diagnostics.stderr)}
Exit Code: ${result.diagnostics.exitcode}` : 'Invalid response' }
},
{
api: 'getDiagnosticsData',
diff --git a/ui/src/config/section/infra/systemVms.js b/ui/src/config/section/infra/systemVms.js
index 6e135ccdd36..9a9910a6610 100644
--- a/ui/src/config/section/infra/systemVms.js
+++ b/ui/src/config/section/infra/systemVms.js
@@ -17,6 +17,7 @@
import { shallowRef, defineAsyncComponent } from 'vue'
import store from '@/store'
+import { escapeHtml } from '@/utils/util'
export default {
name: 'systemvm',
@@ -145,7 +146,7 @@ export default {
options: ['ping', 'traceroute', 'arping']
}
},
- response: (result) => { return result && result.diagnostics ? `Output:
${result.diagnostics.stdout}
Error: ${result.diagnostics.stderr}
Exit Code: ${result.diagnostics.exitcode}` : 'Invalid response' }
+ response: (result) => { return result && result.diagnostics ? `Output:
${escapeHtml(result.diagnostics.stdout)}
Error: ${escapeHtml(result.diagnostics.stderr)}
Exit Code: ${result.diagnostics.exitcode}` : 'Invalid response' }
},
{
api: 'getDiagnosticsData',
diff --git a/ui/src/config/section/network.js b/ui/src/config/section/network.js
index fbc044ff500..408df8147cd 100644
--- a/ui/src/config/section/network.js
+++ b/ui/src/config/section/network.js
@@ -20,6 +20,7 @@ import store from '@/store'
import tungsten from '@/assets/icons/tungsten.svg?inline'
import { isAdmin } from '@/role'
import { isZoneCreated } from '@/utils/zone'
+import { escapeHtml } from '@/utils/util'
export default {
name: 'network',
@@ -681,7 +682,7 @@ export default {
show: (record) => { return ['Stopped'].includes(record.state) && record.passwordenabled },
response: (result) => {
return {
- message: result.virtualmachine && result.virtualmachine.password ? `The password of VM ${result.virtualmachine.displayname} is ${result.virtualmachine.password}` : null,
+ message: result.virtualmachine && result.virtualmachine.password ? `The password of VM ${escapeHtml(result.virtualmachine.displayname)} is ${result.virtualmachine.password}` : null,
copybuttontext: result.virtualmachine.password ? 'label.copy.password' : null,
copytext: result.virtualmachine.password ? result.virtualmachine.password : null
}
diff --git a/ui/src/config/section/user.js b/ui/src/config/section/user.js
index d26901aecca..4c6f198a990 100644
--- a/ui/src/config/section/user.js
+++ b/ui/src/config/section/user.js
@@ -17,6 +17,7 @@
import { shallowRef, defineAsyncComponent } from 'vue'
import store from '@/store'
+import { escapeHtml } from '@/utils/util'
export default {
name: 'accountuser',
@@ -111,7 +112,7 @@ export default {
api: 'lockUser',
icon: 'LockOutlined',
label: 'label.action.lock.user',
- message: (record) => ['message.lock.user', { user: record.username }],
+ message: (record) => ['message.lock.user', { user: escapeHtml(record.username) }],
successMessage: (record) => ['message.lock.user.success', { user: record.username }],
dataView: true,
popup: true,
diff --git a/ui/src/utils/util.js b/ui/src/utils/util.js
index 8773f07446e..d64f3a13764 100644
--- a/ui/src/utils/util.js
+++ b/ui/src/utils/util.js
@@ -64,6 +64,15 @@ export function removeLoadingAnimate (id = '', timeout = 1500) {
}, timeout)
}
+export function escapeHtml (value) {
+ return String(value)
+ .replace(/&/g, '&')
+ .replace(//g, '>')
+ .replace(/"/g, '"')
+ .replace(/'/g, ''')
+}
+
export function sanitizeReverse (value) {
return value
.replace(/&/g, '&')