Skip to content

Security

Path Traversal Protection

The server includes built-in protection against path traversal attacks that attempt to access files outside the root directory.

How It Works

All requests are validated to ensure they don't contain .. path segments that could escape the root directory.

Blocked Requests

These malicious requests are automatically rejected:

http
GET /../../../etc/passwd HTTP/1.1
GET /..%2F..%2F..%2Fetc/passwd HTTP/1.1
GET /%2e%2e/%2e%2e/%2e%2e/etc/passwd HTTP/1.1

Implementation

zig
// Path traversal detection
pub fn hasTraversal(path: []const u8) bool {
    var it = std.mem.splitScalar(u8, path, '/');
    while (it.next()) |part| {
        if (std.mem.eql(u8, part, "..")) {
            return true;
        }
    }
    return false;
}

URL Decoding

All URL-encoded characters are properly decoded before path resolution:

EncodedDecoded
%20Space
%2F/
%3F?
+Space

This ensures that encoded path traversal attempts are also blocked.

Network Security

Host Binding

By default, the server binds to 127.0.0.1 (localhost only), which:

  • Prevents external network access
  • Protects against unauthorized access
  • Is safe for development use

Exposing to Network

When you need network access, use --host 0.0.0.0:

WARNING

Binding to 0.0.0.0 exposes your server to all network interfaces. This allows anyone on your network to access your files.

Best Practices

  1. Use firewall rules - Restrict access to specific IPs
  2. Use a reverse proxy - Add authentication with nginx/Caddy
  3. Run as non-root - Avoid running with elevated privileges
  4. Use HTTPS - Encrypt traffic in production

File System Access

Read-Only Access

The server only reads files and never writes or modifies them:

  • No file uploads
  • No file modifications
  • No file deletions

Symlinks are followed by default. Be cautious with symlinks that point outside the root directory.

Development

bash
# Safe: localhost only
./zserve --root ./public --port 8080

Internal Network

bash
# Use with caution on trusted networks
./zserve --root ./shared --host 192.168.1.100 --port 8080

Production with Reverse Proxy

nginx
# nginx configuration
server {
    listen 80;
    server_name files.example.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        
        # Add basic auth
        auth_basic "Restricted";
        auth_basic_user_file /etc/nginx/.htpasswd;
    }
}

Security Checklist

  • [ ] Server binds to localhost only (default)
  • [ ] No sensitive files in served directory
  • [ ] Running as non-root user
  • [ ] Port > 1024 (no privileges needed)
  • [ ] Symlinks don't point outside root
  • [ ] Reverse proxy configured (production)
  • [ ] HTTPS enabled (production)
  • [ ] Authentication configured (production)

Released under the MIT License.