https://www.millabs.net/blog/openproject-hardened-enclave-deployment/

Every finding in this post is empirical — captured from a real deployment against a Big Bang instance with Istio, Kyverno, cosign image signing, and CycloneDX SBOM attestation enforced.

The application: a Rails deployment to Big Bang

OpenProject 17.7.2 — an open-source project management platform. Ruby 4.0.6 on Rails 8.1.3.1, Angular frontend, PostgreSQL 17 with custom extensions, Redis-compatible cache, S3-compatible object storage, and a Node.js WebSocket service (Hocuspocus) for real-time collaborative editing. Three deployments plus a migration Job.

It is also the project management component of openDesk, the sovereign workplace suite that BWI — the Bundeswehr's IT provider — adopted under a seven-year framework agreement. A NATO member's armed forces already standardize on this application.

On paper, it's ready to deploy. Docker support. Kubernetes documentation. Helm chart.

What I predicted vs. what actually happened

Before deploying, I modeled the expected findings based on architecture analysis. The model predicted 27–32 discrete findings across six failure classes.

Prediction Result Notes
Runs as root Refuted Non-root, uid 1000
Hocuspocus ~900 MB, 150+ CVEs Refuted 492 MB, 14 CVEs — already built on distroless
No managed PostgreSQL Refuted Platform provides managed PostgreSQL 17
Extensions need custom PG build Confirmed partial Extensions trusted but require DBA pre-creation (superuser)
Need Memcached container Refuted Native Redis-compatible cache support
S3 not available Refuted S3-compatible storage available
TLS conflict with mesh Refuted Application does not terminate TLS
Writable rootfs needed Confirmed Three writable paths, plus a Ruby /tmp trap
~800 MB, 200+ CVEs Confirmed — worse 1.5 GB, 670 CVEs
FIPS compatibility Scoped Two code changes identified

The model was wrong in both directions. It overestimated infrastructure problems and underestimated image vulnerability severity. That's the point of deploying instead of modeling.

Total findings: 10

Category Total Resolved Remaining
Configuration 7 7 0
Vulnerability posture 1 1 0
FIPS 2 2 0
Total 10 10 0

All findings resolved. No application code changes required for deployment.

The deployment findings

All workloads passed 39 Kyverno admission policies, cosign signature verification, and CycloneDX SBOM attestation. The application is serving on the platform.

Workload State Notes
openproject-web Running Puma, 2 workers, port 8080
openproject-worker Running GoodJob background processor
openproject-hocuspocus Running Collaborative editing, port 1234
openproject-migrate Completed ~1,500 Rails migrations

Every blocker was configuration. None required application code changes.

Finding 1 — Secrets silently absent at runtime. The entrypoint does not load platform-injected secrets. The injector reports success; the application receives no environment variables. Silent failure — the symptom is a database connection error, not a secrets error.

Finding 2 — Ruby rejects the default temporary directory. Ruby's Dir.tmpdir skips directories with incompatible permissions. Rails fails at boot with no indication of the cause.

Finding 3 — Collaborative editor port mismatch. Hocuspocus listens on port 1234, not the documented 3000. Health checks kill a healthy process.

Finding 4 — Database migrations pending. ~1,500 migrations required. The application will not start without them. The vendor assumes you run them manually — no shell access on a hardened platform.

Finding 5 — Cache key prefix mismatch. Every cache read/write denied. The application's default cache prefix does not match the provisioned credentials.

Finding 6 — Real-time channel prefix hardcoded. ActionCable's channel prefix is a literal string in application config — separate from the cache prefix. Teams fix Finding 5 and miss this one.

Finding 7 — Storage backend crashes at boot without credentials. The S3 backend initializes eagerly, not lazily. The application crashes before reaching the code that uses storage.

Each finding surfaced serially. Each fix revealed the next failure. Without the lab, each would be a separate submission to the target platform's review cadence.

The production blocker: 685 CVEs → 0 on a hardened Ruby image

Image Base Size Critical High Medium Low Unknown Total
openproject:17.7.2-slim ruby:4.0.6-slim-trixie (Debian) 1.5 GB 28 96 171 306 69 670
hocuspocus:17.7.1 distroless/nodejs24:nonroot 492 MB 0 0 7 7 0 14

28 criticals blocked the Rails image from production — no override. 96 highs required explicit recorded acceptance. All CVEs were in the Debian base and Ruby/Node.js toolchain, not in application code.

After hardening

Image Base Size Critical High Total Delta
Rails (slim-dev) cgr.dev/chainguard/ruby:latest-dev (wolfi) 2.6 GB 0 0 0 −670
Rails (slim) cgr.dev/chainguard/ruby:latest (wolfi, distroless) 1.28 GB 0 0 0 −670
Hocuspocus cgr.dev/chainguard/node:latest (wolfi, distroless) 539 MB 0 0 0 −15

685 CVEs eliminated. 0 residual. Both images pass the production vulnerability gate.

The Dockerfile provides two runtime targets for Rails:

  • slim-dev — has bash, supports entrypoint scripts that source secrets. 2.6 GB. Verified end-to-end.
  • slim — distroless, no shell, no package manager. 1.28 GB. Verified end-to-end.

Both targets scan identically at 0 CVEs. Both verified with PostgreSQL, Redis-compatible cache, migrations (~1,500), database seed, and HTTP serving.

FIPS 140: two bounded code changes

Most of OpenProject's cryptography is already FIPS-compatible — AES-256-CBC/GCM for encryption, HMAC-SHA256 for tokens and sessions, PBKDF2 for key derivation, OpenSSL 3.x for TLS.

Two operations break under FIPS enforcement:

Component Was Now Status
Password hashing bcrypt (Blowfish) — not FIPS-approved PBKDF2-HMAC-SHA256 (600,000 iterations) Done — in fork, verified
Attachment checksum MD5 — not FIPS-approved SHA-256 Done — single call site

Both are implemented in the assessment fork. Existing bcrypt passwords migrate transparently on next login — same pattern as the existing SHA-1 → bcrypt migration already in production.

Code quality

Scanner Findings Notes
Semgrep 986 Output-escaping patterns typical of large Rails applications
Brakeman 55 (1 high-confidence, 2 RCE) Vendor maintains a suppression file for known false positives

Documented for acknowledgement. Remediation is the vendor's responsibility. The high-confidence and RCE findings warrant review for platform admission.

What was eliminated

Work that didn't need to happen

Planned work Why unnecessary Days avoided Cost avoided (GSA $175/hr)
Rebuild image to run non-root Already non-root, uid 1000 2–3 $2,800–$4,200
Rebuild Hocuspocus on hardened base Already hardened, 0 criticals 1–2 $1,400–$2,800
Containerize PostgreSQL Platform provides managed PostgreSQL 17 3–5 $4,200–$7,000
Build cache sidecar Native Redis-compatible support 1–2 $1,400–$2,800
Design TLS passthrough for mesh Application does not terminate TLS 0.5–1 $700–$1,400
Total 8–13 days $11,000–$18,000

These figures use the GSA Alliant 3 / OASIS+ midpoint for cleared DevSecOps engineers ($175/hr). On the commercial market, cleared engineers with this profile bill $200–$325/hr — pushing the wasted spend to $16,000–$34,000.

Work that only deployment revealed

Finding Why invisible without deployment
Secrets silently absent Injector and application both correct in isolation; gap is between them
Ruby rejects default temp directory Language-specific runtime behavior, not documented
Hocuspocus on undocumented port Only visible in the container's startup log
Migrations not in deployment manifests Application assumes separate execution
Cache prefix outside credential scope Correct for the app, wrong for the platform
Channel prefix hardcoded Separate from cache prefix — teams fix one and miss the other
Storage crashes without credentials Eager initialization, fails before the code that uses storage

Authorization lifecycle cost

Without the image hardening, each of 685 CVEs requires a security impact statement — approximately 1 hour each for initial writing, then re-validation on a severity-driven schedule:

Severity CVEs Re-validation window 5-year hours Cost at $175/hr
Critical 28 30 days ~840 ~$147,000
High 96 90 days ~2,880 ~$504,000
Medium 171 180 days ~860 ~$150,000
New CVEs (~20/yr) On discovery ~100 ~$17,500
Initial statements 685 One-time ~685 ~$120,000
5-year total ~5,365 ~$938,500

That's nearly $1M in CVE documentation labor at GSA rates — and GSA rates are the floor. Cleared cybersecurity analysts on the commercial market command $200–$325/hr, which pushes the 5-year obligation past $1.3M. With 0 residual CVEs, this entire obligation is eliminated — not deferred, eliminated.

What the study delivered

Every item below is working code or a tested configuration — not a recommendation.

Deliverable Description
Hardened Dockerfiles Both images rebuild at 0 CVEs. Multi-stage, Chainguard wolfi.
FIPS code changes bcrypt → PBKDF2-HMAC-SHA256, MD5 → SHA-256. In fork, verified.
CI/CD pipeline Builds hardened images, pushes through the image gate automatically.
Operational manifests 12 files (840 lines). Seed Job, break-glass credential reset, migration Job.
Configuration playbook 7 findings, each with the exact resolution.
Egress profile 8 destination categories. Minimum allow-list: disable Gravatar for zero egress.
Code quality baseline Semgrep + Brakeman scans for platform admission.

Remaining effort to deploy on a target platform

Phase Engineering effort Notes
Platform provisioning 1–2 days Namespace, database, cache, secrets, image mirroring
Configuration + deployment 1–2 days Apply the 7 documented configurations
OIDC + SMTP 1 day Enterprise license required for OIDC
Operational verification 1 day Seed, break-glass, multi-replica

4–6 days of engineering. Calendar time depends on the target platform's review cadence.

Build your own environment or deploy to an existing one?

Your own enclave from scratch Existing accredited platform
Infrastructure Build and maintain hardened K8s, Istio, Kyverno, monitoring, logging, storage Already exists, already authorized
Authorization Full ATO from zero: 12–18 months, $500K–$2M+ in documentation and process Inherit platform authorization, application-level CtF/ATO in weeks to months
Staffing Cleared DevSecOps team to build and operate Application hardening only
Ongoing You own patching, continuous monitoring, incident response, re-authorization Platform operator handles infrastructure security
First-year cost $2–5M+ $50–200K for application hardening + platform fees

OpenProject's requirements — PostgreSQL, Redis-compatible cache, S3-compatible storage, OIDC — are standard managed services on existing platforms. A dedicated enclave for a single project management application would be disproportionate.

Existing platforms here means Platform One's Party Bus, Second Front's Game Warden, or a program-office Big Bang environment. Millabs has taken a commercial application through Game Warden to IL-4 and TOP SECRET on JWICS. Second Front is also bringing Game Warden to AWS European Sovereign Cloud, with ten customers prepared to deploy — relevant to any program with a coalition or OCONUS footprint.

The takeaway

  • "Runs in Docker" and "runs in a hardened enclave" are separated by 10 findings and 4–6 days of engineering — not the 27–32 findings and 6–10 weeks the model predicted
  • Architecture analysis overestimated by 8–13 days ($11,000–$18,000 at GSA rates) of unnecessary work and underestimated image vulnerability severity by 3x
  • 685 → 0 CVEs with a base image swap — eliminating ~$940,000 in authorization maintenance over 5 years ($1.3M+ at commercial cleared rates)
  • The 7 runtime findings were invisible without deployment — every one of them would have been a separate rejection cycle on a live platform
  • The study delivered working code, not recommendations. The only remaining gate is procurement (Enterprise license for OIDC and antivirus)

Robert Burckner is the founder of Millabs Corporation. This deployment was performed in a privately operated, unaccredited Big Bang instance. No government data was used. OpenProject is open-source software licensed under GPL-3.0.

If your product needs to deploy into a hardened DoW enclave, contact Millabs for a fit screen.

If you are a program office weighing OpenProject for your own enclave, the deployment above is reproducible and the findings transfer. Millabs scopes that work, and will operate the result at any impact level — CUI at IL-4/IL-5, Secret at IL-6, Top Secret on JWICS — for programs that would rather not staff it.

Share this post
Email LinkedIn
GET IN TOUCH WITH US

Find out what the gap between your product and an authorized environment actually looks like.