> For the complete documentation index, see [llms.txt](https://quantumwing.gitbook.io/quantumwing/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://quantumwing.gitbook.io/quantumwing/deployment/security.md).

# Security Hardening

Operator hardening — keys, network, processes, audit

This page is the operator-side checklist. The chain's *protocol* security model is in [../architecture/trust-boundaries.md](/quantumwing/architecture/trust-boundaries.md); this document covers what an operator does on the host to avoid weakening that model.

## Threat model

QuantumWing assumes:

* The host is owned by the operator, not multi-tenant.
* The validator's Dilithium private key is the highest-value secret; loss → slashing, theft → double-sign attack.
* The faucet wallet is the second-highest-value secret on a public testnet (anyone with the key drains the faucet).
* Public RPC endpoints (8545, 8546) are read-mostly. Engine API (`/api/v1/engine/*`) is internal and MUST NOT be exposed.

## Key custody

```
Validator wallet:   /wallets/production-validators/validator-N/validator.json
                    Mode: 0400 (root-owned)
                    Encrypted with operator passphrase (Argon2id + AES-GCM)
                    NEVER commit to git, NEVER store unencrypted

Faucet wallet:      /etc/quantumwing/keys/faucet.json
                    Same protections as validator

Backup keys:        /secure/quantumwing-backup-2026.key  (age private key)
                    Mode: 0400, on a different host than backups
                    Rotated annually (see operations/backup.md)

Bridge committee:   /etc/quantumwing/keys/bridge-committee/<member-id>.json
                    Mode: 0400, encrypted, hardware-backed when available
```

Validator wallets MUST be backed by the v2 BIP-39 wallet format — seed-phrase recoverability is a hard requirement before mainnet:

```bash
./build/quantum-wing-blockchain wallet generate-v2 \
  --output validator.json --mode 3 --words 24
```

## Process hardening

systemd unit (`ops/systemd/quantum-wing-blockchain.service`):

```ini
[Service]
User=quantumwing
Group=quantumwing
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
PrivateDevices=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
RestrictNamespaces=true
LockPersonality=true
SystemCallFilter=@system-service
SystemCallErrorNumber=EPERM
ReadWritePaths=/var/lib/quantumwing
```

The chain process never needs root after the initial directory setup. Drop privileges before `ExecStart`.

## Network exposure

```
Layer            Port    Public?    Bind to
─────────────────────────────────────────────────────────────────────
JSON-RPC         8545    yes (TLS)  0.0.0.0  (behind nginx + cert)
REST execution   8546    yes (TLS)  0.0.0.0  (behind nginx + cert)
REST beacon      8080    yes (TLS)  0.0.0.0  (behind nginx + cert)
Engine API       same    NO         loopback only — firewall block
P2P              9000    yes        0.0.0.0  (NAT-traversed)
Metrics          9090    NO         loopback only — Prometheus scrape
```

Engine endpoints (`/api/v1/engine/*`) MUST be reachable ONLY from the beacon's localhost. An external caller with engine access can rewrite the chain head.

Sample nginx fragment (loopback-only metrics, public RPC):

```nginx
location /metrics {
  allow 127.0.0.1;
  deny  all;
  proxy_pass http://localhost:9090;
}

location /api/v1/engine/ {
  return 404;   # never expose
}

location / {
  proxy_pass http://localhost:8546;
  proxy_set_header X-Real-IP $remote_addr;
  client_max_body_size 1m;
}
```

The `client_max_body_size 1m` matches the chain's `LimitRequestBody` middleware — anything larger is dropped at the edge before reaching the application.

## CORS

Set `CORS_ORIGIN` explicitly in production:

```bash
export CORS_ORIGIN="https://explorer.example.com"
./build/quantum-wing-blockchain start ...
```

The default (`*`) is acceptable for dev workflows but flagged by the audit (Session 80) as a finding for any production deploy.

## Rate limits

Inbuilt:

* Faucet: 1 claim per address / 24 h
* Bridge attestation: 10/min/peer, 3/address, 10/block
* JSON-RPC body: 1 MiB hard cap
* REST body: 1 MiB hard cap

Front the chain with an additional WAF (CloudFlare, AWS WAF) for per-IP rate limiting — the chain itself does not authenticate external IPs.

## TLS

Terminate TLS at nginx with Let's Encrypt or a managed cert. The chain process speaks plain HTTP — public exposure without a TLS proxy is a hard no.

```bash
# Test cert
curl -v https://rpc.example.com/api/v1/execution/status
```

Quantum-safe TLS migration (Dilithium certs) is on the Q1 2026 roadmap — see [../EVM\_INTEGRATION\_ROADMAP.md](https://github.com/dolfrin/QuantumWing/blob/master/docs/EVM_INTEGRATION_ROADMAP.md).

## Audit log

Every block, attestation, slashing event, bridge BID transition, and authorization-tx submission is on-chain and indexed. For host-side audit:

```bash
journalctl -u quantum-wing-blockchain.service --since "2026-04-29 00:00"
journalctl -u quantum-wing-validator.service --since "2026-04-29 00:00"
```

`/var/log/auth.log` and the systemd journal are subject to standard host audit policy. Forward to a SIEM with a 90-day retention floor.

## Updates

```bash
# Always read the changelog first
git fetch
git log v$(./build/quantum-wing-blockchain version)..origin/master --oneline

# Build new binary
make build

# Test on a non-validator first
./build/quantum-wing-blockchain start --mode rpc
```

NEVER auto-update validators. A bad release that double-signs costs 50% of stake.

## Recent fixes worth knowing about

From the audit-fix sessions (Sessions 80 + 81):

* **CORS** is now configurable. Default `*` flagged as a finding.
* **Body limit** of 1 MiB enforced on JSON-RPC.
* **CGO** use-after-free fix in Dilithium FFI (`runtime.KeepAlive`).
* **Bridge** attestation now Dilithium-verified — was a no-op.
* **chainID** validation tightened at every layer.
* **ECDSA** signature verification was previously stubbed; now real.

Operators on releases older than December 2025 should upgrade.

## Code paths

* `ops/systemd/quantum-wing-blockchain.service` — unit file
* `blockchain/api/server.go::LimitRequestBody` — body cap
* `blockchain/api/rate_limiter.go` — bridge rate limits
* `blockchain/api/faucet_handlers.go` — faucet cooldown
* `cmd/blockchain/wallet.go` — v2 wallet flow

## Related

* [../architecture/trust-boundaries.md](/quantumwing/architecture/trust-boundaries.md)
* [../networking/security.md](/quantumwing/networking/security.md) — P2P-side hardening
* [../operations/backup.md](/quantumwing/operations/backup.md) — key custody
* [../operations/disaster-recovery.md](/quantumwing/operations/disaster-recovery.md)
* [production-setup.md](/quantumwing/deployment/production-setup.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://quantumwing.gitbook.io/quantumwing/deployment/security.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `build a script that syncs our docs to a CMS` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
