Skip to content

RaptorCentauri/docsec

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DocSec

A homelab-focused Docker container security auditor.

DocSec connects to a Docker instance via the Docker Engine API, enumerates running containers and images, detects common misconfigurations derived from the container security literature, checks for known CVEs via the OSV vulnerability database, and presents findings through a web-based dashboard. It supports both local Docker connections and secure remote connections to any Docker host on your network.


Quick Start

Prerequisites

  • Go 1.21 or newer (go version to check)
  • Docker running locally or accessible on your network
  • Internet access during the scan (OSV CVE API at osv.dev)
  • curl for downloading frontend assets

Build

# Clone the repository
git clone https://github.com/RaptorCentauri/docsec
cd docsec

# Download vendored frontend assets (required before building)
curl -o assets/static/tailwind.min.css https://cdn.tailwindcss.com/3.4.1
curl -o assets/static/alpine.min.js https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js

# Fetch Go dependencies
go mod tidy

# Build the binary
go build -o docsec .

Run

./docsec --help

Usage

Local Docker (default)

Connects to the Docker daemon on the same machine via the Unix socket.

# Start dashboard only (run a scan from the UI)
./docsec

# Run a scan on startup, then serve the dashboard
./docsec --scan

# Custom port
./docsec --port 9090

# Custom database path
./docsec --db /path/to/docsec.db

Open http://localhost:8080 in your browser.


Remote Docker — Unencrypted TCP (not recommended)

Connects to a remote Docker host over plain TCP. The Docker daemon on the remote host must be configured to accept TCP connections on port 2375.

Security warning: The unencrypted TCP API has no authentication. Anyone on your network can control the Docker daemon. Only use this on a trusted local network, and prefer TLS (see below).

./docsec --host tcp://192.168.1.50:2375 --scan

Enabling the TCP API on the remote host (Linux):

Create or edit /etc/systemd/system/docker.service.d/override.conf:

[Service]
ExecStart=
ExecStart=/usr/bin/dockerd

Then add to /etc/docker/daemon.json:

{
  "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"]
}

Reload and restart:

systemctl daemon-reload
systemctl restart docker

Remote Docker — TLS (recommended)

Connects to a remote Docker host over TCP with mutual TLS authentication. Only clients with a valid certificate signed by your CA can connect. This is the recommended approach for multi-host homelab scanning.

./docsec \
  --host tcp://192.168.1.50:2376 \
  --tlsverify \
  --tlscacert ~/.docker/certs/ca.pem \
  --tlscert ~/.docker/certs/client-cert.pem \
  --tlskey ~/.docker/certs/client-key.pem \
  --scan

TLS Prerequisites

You need three certificate files on your client machine:

File Purpose
ca.pem Certificate Authority — verifies the server
client-cert.pem Client certificate — identifies your client
client-key.pem Client private key — signs your client cert

Generating TLS Certificates

Run the following on the remote Docker host (requires openssl):

mkdir -p ~/.docker/certs && cd ~/.docker/certs

# 1. Generate the Certificate Authority
openssl genrsa -out ca-key.pem 4096
openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem -subj "/CN=docsec-ca"

# 2. Generate the server certificate (replace with your server's IP)
openssl genrsa -out server-key.pem 4096
openssl req -subj "/CN=192.168.1.50" -sha256 -new -key server-key.pem -out server.csr
echo subjectAltName = IP:192.168.1.50,IP:127.0.0.1 > extfile.cnf
openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile extfile.cnf

# 3. Generate the client certificate
openssl genrsa -out client-key.pem 4096
openssl req -subj '/CN=client' -new -key client-key.pem -out client.csr
echo extendedKeyUsage = clientAuth > extfile-client.cnf
openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem -extfile extfile-client.cnf

Copy ca.pem, client-cert.pem, and client-key.pem to your client machine:

# Run from your client machine
mkdir -p ~/.docker/docsec-certs
scp -O [email protected]:~/.docker/certs/ca.pem ~/.docker/docsec-certs/
scp -O [email protected]:~/.docker/certs/client-cert.pem ~/.docker/docsec-certs/
scp -O [email protected]:~/.docker/certs/client-key.pem ~/.docker/docsec-certs/

Configuring the Remote Docker Daemon for TLS

On the remote host, create /etc/systemd/system/docker.service.d/override.conf:

[Service]
ExecStart=
ExecStart=/usr/bin/dockerd

Add to /etc/docker/daemon.json (replace IP with your server's IP):

{
  "tlsverify": true,
  "tlscacert": "/root/.docker/certs/ca.pem",
  "tlscert": "/root/.docker/certs/server-cert.pem",
  "tlskey": "/root/.docker/certs/server-key.pem",
  "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2376"]
}

Reload and restart:

systemctl daemon-reload
systemctl restart docker

Verify TLS is working from your client machine:

curl --tlsv1.2 \
  --cacert ~/.docker/docsec-certs/ca.pem \
  --cert ~/.docker/docsec-certs/client-cert.pem \
  --key ~/.docker/docsec-certs/client-key.pem \
  https://192.168.1.50:2376/version

Configuration File

Create ~/.docsec/config.toml for persistent settings:

[docker]
host = "tcp://192.168.1.50:2376"
tls_verify = true
tls_ca_cert = "/home/user/.docker/docsec-certs/ca.pem"
tls_cert = "/home/user/.docker/docsec-certs/client-cert.pem"
tls_key = "/home/user/.docker/docsec-certs/client-key.pem"

[server]
port = 8080

[database]
path = "~/.docsec/docsec.db"

[scan]
enabled_checks = [
  "MC-001", "MC-002", "MC-003", "MC-004",
  "MC-005", "MC-006", "MC-007", "MC-008"
]

CLI flags override config file values. Config file values override built-in defaults.


CLI Reference

Flag Default Description
--host unix:///var/run/docker.sock Docker host URI
--port 8080 Dashboard port
--db ~/.docsec/docsec.db Database path
--config ~/.docsec/config.toml Config file path
--scan false Run scan on startup
--tlsverify false Enable TLS for remote connection
--tlscacert Path to CA certificate
--tlscert Path to client certificate
--tlskey Path to client private key

Misconfiguration Checks

ID Check Severity Literature Source
MC-001 Privileged mode enabled CRITICAL De Giorgi (2022), Mahajan & Mane (2022)
MC-002 Docker socket mounted CRITICAL De Giorgi (2022), Rajyashree et al. (2024)
MC-003 Container running as root HIGH De Giorgi (2022), Ahamed et al. (2021)
MC-004 Excessive Linux capabilities HIGH De Giorgi (2022)
MC-005 Sensitive ports exposed MEDIUM De Giorgi (2022)
MC-006 No CPU resource limit MEDIUM De Giorgi (2022), Ahamed et al. (2021)
MC-007 No memory resource limit MEDIUM De Giorgi (2022), Ahamed et al. (2021)
MC-008 Unpinned image tag LOW De Giorgi (2022)

Architecture

docsec/
├── main.go                        # Entry point, wires components together
├── embed.go                       # Embeds assets/ directory into binary
├── internal/
│   ├── config/                    # TOML + CLI flag configuration
│   ├── docker/                    # Docker Engine API client (local + TLS remote)
│   ├── scanner/
│   │   ├── scanner.go             # Scan orchestration
│   │   ├── misconfig/             # 8 misconfiguration check implementations
│   │   └── cve/                   # CVE provider interface + OSV implementation
│   ├── db/                        # SQLite persistence layer
│   └── web/                       # HTTP server, handlers, templates
├── assets/
│   ├── templates/                 # Go HTML templates (embedded in binary)
│   └── static/                    # Alpine.js, Tailwind CSS (embedded in binary)
└── scripts/
    └── testenv/                   # Intentionally misconfigured test environment

Key Design Decisions

Single binary. All assets are embedded at compile time via Go's embed package. No runtime filesystem dependencies — download and run.

Not containerized. DocSec requires access to /var/run/docker.sock. Running it as a Docker container would require mounting the socket, which is itself MC-002 — a critical misconfiguration DocSec is designed to detect.

TLS for remote connections. Remote Docker connections use mutual TLS on port 2376. Both client and server must present certificates signed by the same CA, preventing unauthorized access to the Docker API.

CVE provider pattern. CVE sources implement a common Provider interface. OSV is the default. Additional sources (NVD, GitHub Advisory) can be added by implementing the interface without modifying the scanner.


Running Tests

go test ./...

Tests use in-memory SQLite and do not require a live Docker connection.


Test Environment

A Docker Compose file with intentionally misconfigured containers is provided:

cd scripts/testenv
docker compose up -d
cd ../..
./docsec --scan

CVE Data Source

CVE data is sourced from OSV (Open Source Vulnerabilities), maintained by Google. OSV aggregates from NVD, GitHub Advisory, and 15+ ecosystem-specific sources. No API key is required.


Exporting Results

The dashboard provides a JSON export of the most recent scan. Click Export JSON on the overview page, or access it directly at http://localhost:8080/export.


Research Context

DocSec was developed as part of a research project examining container security in homelab and small-team environments. The tool demonstrates that a lightweight, accessible auditor built around the Docker API can surface critical vulnerabilities and misconfigurations without the overhead of enterprise tooling.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors