Skip to content

fix(security): remove Docker socket mount from LocalStack and enforce non-root user in signer images - #14

Open
mertcano wants to merge 1 commit into
circlefin:mainfrom
mertcano:mertcano-patch-1
Open

mertcano wants to merge 1 commit into
circlefin:mainfrom
mertcano:mertcano-patch-1

Conversation

@mertcano

@mertcano mertcano commented Oct 1, 2026

Copy link
Copy Markdown

Summary of Changes

Addresses the Blocker and Medium container security audit findings in arc-remote-signer (Cat 7: Dependency & supply-chain security, Cat 21: IaC & container hardening)[cite: 44, 51]:

  1. Docker Daemon Socket Removal (deployments/docker-compose.yaml - Blocker): Removed /var/run/docker.sock volume mount and unused DOCKER_HOST environment variable from the LocalStack service, eliminating a critical host-level root privilege escalation vulnerability.
  2. Non-Root User Enforcement (docker/Dockerfile, docker/Dockerfile.enclave - Medium): Created dedicated system user circle:circle (UID/GID 1000) and applied USER circle across both signer and enclave Dockerfiles to prevent root execution when handling signing keys.
  3. Loopback Exposure Tightening (deployments/docker-compose.yaml): Bound enclave port 10350 to 127.0.0.1 to restrict access strictly to localhost.

Vulnerability Analysis

  • Docker Socket Host Takeover (Blocker - Cat 7):[cite: 44]

    • /var/run/docker.sock grants arbitrary container creation and root execution over the host daemon[cite: 44].
    • LocalStack runs repository-supplied init scripts (create-kms-keys.sh, create-secret-manager-key.sh) at startup, turning any malicious alteration of these scripts into an immediate host compromise[cite: 44].
    • KMS and Secrets Manager mock services do not require Docker socket access[cite: 44].
  • Root Privilege Execution (Medium - Cat 21):

    • Processes holding encrypted signing keys and interacting with AWS KMS ran as UID 0 (root)[cite: 51].
    • A compromise in the gRPC server or KMS client would yield root access inside the container[cite: 51].

Key Remediations

  • deployments/docker-compose.yaml:

    • Removed Docker socket mount from LocalStack service volumes[cite: 44].
    • Removed DOCKER_HOST: unix:///var/run/docker.sock environment setting.
    • Bound enclave service port to 127.0.0.1:10350:10350.
  • docker/Dockerfile & docker/Dockerfile.enclave:

    • Provisioned system group/user circle with fixed UID/GID 1000[cite: 51].
    • Chowned /usr/local/circle to circle:circle to ensure 0750 executables (app, run_proxy.sh, run_enclave.sh) remain executable[cite: 51].
    • Set USER circle as the execution user for both images[cite: 51].

Verification

  • Parsed docker-compose.yaml via YAML schema validation: successfully parsed with 0 errors; confirmed no docker.sock volume mounts exist.
  • Verified that reproducible build steps in Dockerfile.enclave (touch -hcd "@0") are preserved alongside the circle user creation[cite: 51].

Follow-up Action Required (Section 10 - Blocker)

  • Unauthenticated gRPC Signer (internal/app/public/public.go:New): As noted in Section 8 and Section 10 of the audit report, the gRPC signing service returns Ed25519 signatures without authentication and TLS defaults to disabled[cite: 55, 57]. Once the Go toolchain is installed in the target environment, implement a peer-allowlist or mTLS interceptor and default TLS to enabled[cite: 55, 57].

… non-root user in signer images

### Summary of Changes
Addresses the **Blocker** and **Medium** container security audit findings in `arc-remote-signer` (Cat 7: Dependency & supply-chain security, Cat 21: IaC & container hardening)[cite: 44, 51]:

1. **Docker Daemon Socket Removal (`deployments/docker-compose.yaml` - Blocker):** Removed `/var/run/docker.sock` volume mount and unused `DOCKER_HOST` environment variable from the LocalStack service, eliminating a critical host-level root privilege escalation vulnerability.
2. **Non-Root User Enforcement (`docker/Dockerfile`, `docker/Dockerfile.enclave` - Medium):** Created dedicated system user `circle:circle` (UID/GID 1000) and applied `USER circle` across both signer and enclave Dockerfiles to prevent root execution when handling signing keys.
3. **Loopback Exposure Tightening (`deployments/docker-compose.yaml`):** Bound enclave port `10350` to `127.0.0.1` to restrict access strictly to localhost.

---

### Vulnerability Analysis

- **Docker Socket Host Takeover (Blocker - Cat 7):**[cite: 44]
  - `/var/run/docker.sock` grants arbitrary container creation and root execution over the host daemon[cite: 44].
  - LocalStack runs repository-supplied init scripts (`create-kms-keys.sh`, `create-secret-manager-key.sh`) at startup, turning any malicious alteration of these scripts into an immediate host compromise[cite: 44].
  - KMS and Secrets Manager mock services do not require Docker socket access[cite: 44].

- **Root Privilege Execution (Medium - Cat 21):**
  - Processes holding encrypted signing keys and interacting with AWS KMS ran as UID 0 (`root`)[cite: 51].
  - A compromise in the gRPC server or KMS client would yield root access inside the container[cite: 51].

---

### Key Remediations

- **`deployments/docker-compose.yaml`:**
  - Removed Docker socket mount from LocalStack service volumes[cite: 44].
  - Removed `DOCKER_HOST: unix:///var/run/docker.sock` environment setting.
  - Bound enclave service port to `127.0.0.1:10350:10350`.

- **`docker/Dockerfile` & `docker/Dockerfile.enclave`:**
  - Provisioned system group/user `circle` with fixed UID/GID `1000`[cite: 51].
  - Chowned `/usr/local/circle` to `circle:circle` to ensure `0750` executables (`app`, `run_proxy.sh`, `run_enclave.sh`) remain executable[cite: 51].
  - Set `USER circle` as the execution user for both images[cite: 51].

---

### Verification
- Parsed `docker-compose.yaml` via YAML schema validation: successfully parsed with 0 errors; confirmed no `docker.sock` volume mounts exist.
- Verified that reproducible build steps in `Dockerfile.enclave` (`touch -hcd "@0"`) are preserved alongside the `circle` user creation[cite: 51].

---

### Follow-up Action Required (Section 10 - Blocker)
- **Unauthenticated gRPC Signer (`internal/app/public/public.go:New`):** As noted in Section 8 and Section 10 of the audit report, the gRPC signing service returns Ed25519 signatures without authentication and TLS defaults to disabled[cite: 55, 57]. Once the Go toolchain is installed in the target environment, implement a peer-allowlist or mTLS interceptor and default TLS to enabled[cite: 55, 57].
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant