diff --git a/cmd/internal/pages/assets/js/containers.js b/cmd/internal/pages/assets/js/containers.js
index ee2f61867f..61e45d9abf 100644
--- a/cmd/internal/pages/assets/js/containers.js
+++ b/cmd/internal/pages/assets/js/containers.js
@@ -14,6 +14,12 @@
google.charts.load('current', {packages: ['corechart', 'gauge', 'default', 'format', 'ui', 'table']});
+// Escape HTML special characters to prevent XSS when rendering in tables with allowHtml.
+function escapeHtml(str) {
+ if (typeof str !== 'string') return str;
+ return str.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, ''');
+}
+
function humanize(num, size, units) {
var unit;
for (unit = units.pop(); units.length && num >= size; unit = units.pop()) {
@@ -622,10 +628,10 @@ function drawProcesses(isRoot, rootDir, processInfo) {
var data = [];
for (var i = 0; i < processInfo.length; i++) {
var elements = [];
- elements.push(processInfo[i].user);
+ elements.push(escapeHtml(processInfo[i].user));
elements.push(processInfo[i].pid);
elements.push(processInfo[i].parent_pid);
- elements.push(processInfo[i].start_time);
+ elements.push(escapeHtml(processInfo[i].start_time));
elements.push({
v: processInfo[i].percent_cpu,
f: processInfo[i].percent_cpu.toFixed(2)
@@ -639,15 +645,16 @@ function drawProcesses(isRoot, rootDir, processInfo) {
v: processInfo[i].virtual_size,
f: humanizeIEC(processInfo[i].virtual_size)
});
- elements.push(processInfo[i].status);
- elements.push(processInfo[i].running_time);
- elements.push(processInfo[i].cmd);
+ elements.push(escapeHtml(processInfo[i].status));
+ elements.push(escapeHtml(processInfo[i].running_time));
+ elements.push(escapeHtml(processInfo[i].cmd));
elements.push(processInfo[i].psr);
if (isRoot) {
var cgroup = processInfo[i].cgroup_path;
// Use the raw cgroup link as it works for all containers.
- var cgroupLink = '' +
- cgroup.substr(0, 30) + ' ';
+ var escapedCgroup = escapeHtml(cgroup);
+ var cgroupLink = '' +
+ escapedCgroup.substr(0, 30) + ' ';
elements.push({v: cgroup, f: cgroupLink});
}
data.push(elements);
diff --git a/manager/container.go b/manager/container.go
index 5020e945b2..f1ff86a746 100644
--- a/manager/container.go
+++ b/manager/container.go
@@ -261,6 +261,10 @@ func (cd *containerData) ReadFile(filepath string, inHostNamespace bool) ([]byte
}
for _, pid := range pids {
filePath := path.Join(rootfs, "/proc", pid, "/root", filepath)
+ expectedPrefix := path.Join(rootfs, "/proc", pid, "/root") + "/"
+ if !strings.HasPrefix(filePath, expectedPrefix) {
+ return nil, fmt.Errorf("invalid file path %q: resolves outside container root", filepath)
+ }
klog.V(3).Infof("Trying path %q", filePath)
data, err := os.ReadFile(filePath)
if err == nil {