Introduction
The Docker/LocalCluster.s3.yaml file defines the local development cluster used to spin up supporting services — including opensearch, which backs search and logging functionality for the stack. But a flaw in how that service was configured created a security risk: the opensearch container was allowed to run with a fully writable root filesystem, with no read_only restriction in place.
That might sound like a minor detail, but for anyone who has debugged a container compromise, it's a big deal. A writable root filesystem means that if an attacker ever gets code execution inside the opensearch container — through a vulnerable plugin, a deserialization bug, or a supply-chain compromise in a dependency — they don't just get a foothold, they get a durable one. They can drop tools, rewrite startup scripts, or tamper with application files, and those changes can persist for the life of the container.
The Vulnerability Explained
Semgrep's yaml.docker-compose.security.writable-filesystem-service rule flagged this exact pattern in Docker/LocalCluster.s3.yaml:
services:
opensearch:
image: opensearchproject/opensearch:2.11.0
container_name: opensearch
environment:
- discovery.type=single-node
ports:
- "9200:9200"
volumes:
- opensearch-data:/usr/share/opensearch/data
Notice what's missing here: there is no read_only key at all. By default, Docker Compose services run with a fully writable filesystem unless you explicitly lock it down. That means every directory inside the container — /bin, /etc, /usr/share/opensearch, temp directories, everything — is writable by the OpenSearch process at runtime.
Why this matters in practice: OpenSearch, like most JVM-based services, exposes a large attack surface — REST APIs, plugin loading, script execution in some configurations, and JSON/YAML parsing of untrusted data. If any of that surface is ever exploited (for example, via a malicious query, a vulnerable plugin, or a poisoned dependency pulled in at build time), the attacker doesn't just get to read data — they get a container where they can:
- Download and execute additional payloads (a second-stage backdoor, a cryptominer, a reverse shell binary).
- Modify OpenSearch's own configuration or startup scripts so the compromise survives a container restart.
- Tamper with logs or data files to cover their tracks.
Because the root filesystem is writable, none of this requires privilege escalation inside the container — the attacker already has write access to everything the OpenSearch process can reach.