Path traversal in ReadFile() via container label escapes proc namespace boundary
- Dominant language
- Go
- Stars
- 19.4k
- Forks
- 2.5k
- Avg merge
- 9h 7m
- Merged PRs (30d)
- 1
Description
## Summary
In `manager/container.go`, the `ReadFile()` function uses `path.Join` with a user-controlled `filepath` parameter derived from Docker container labels, without any prefix validation. This enables path traversal from within a container's namespace to arbitrary files on the host.
## Vulnerable Code
**File: cadvisor/manager/container.go:250-272**
```go
func (cd *containerData) ReadFile(filepath string, inHostNamespace bool) ([]byte, error) {
pids, err := cd.getContainerPids(inHostNamespace)
rootfs := "/"
if !inHostNamespace {
rootfs = "/rootfs"
}
for _, pid := range pids {
filePath := path.Join(rootfs, "/proc", pid, "/root", filepath)
// ↑ NO prefix check: path.Join resolves ".." → escapes proc/PID/root/ boundary
data, err := os.ReadFile(filePath)
```
The `filepath` comes from the `io.cadvisor.metric.*` container label. With a label value of `../../../../etc/shadow`, `path.Join` resolves to `/etc/shadow` on the host.
**Proof:**
```go
path.Join("/", "/proc", "1234", "/root", "../../../../etc/shadow")
// → "/etc/shadow" ← host shadow file, not container's
path.Join("/rootfs", "/proc", "1234", "/root", "../../../../proc/1/environ")
// → "/proc/1/environ" ← host init process environment (may contain secrets)
```
## Attack Scenario
1. Attacker deploys container with label: `io.cadvisor.metric.steal=../../../../etc/shadow`
2. cAdvisor calls `ReadFile("../../../../etc/shadow", inHostNamespace)` for that container
3. `path.Join` resolves to host `/etc/shadow` — file is read by cAdvisor (running as root in a DaemonSet)
4. Contents leak into cAdvisor logs or error messages
## Suggested Fix
After `path.Join`, validate that `filePath` still starts with the expected prefix (`rootfs + "/proc/" + pid + "/root/"`). Reject any path that escapes the container's root namespace.
Contributor guide
Assessment
This issue has not been assessed yet.