Guarding the Supply Chain: The Four Automated Security Gates of the InfraOrcinus Control Plane

By Chirag Panchal · Founder & Lead Architect · · 8 min read

How InfraOrcinus secures its own control plane before code merges: race-detected tests against real PostgreSQL, Semgrep OWASP rules, OSV-Scanner and Trivy for dependencies and images, and full-history gitleaks with local hooks. Plus the gates that once looked green without checking anything, and how we fixed them.

Development Status & Architectural Evolution: InfraOrcinus is in active development. Architecture specifications, internal interfaces, and operational protocols described herein reflect our current engineering design and are continuously refined to make InfraOrcinus robust, resilient, and enterprise-grade.

A platform that holds cloud credentials and applies infrastructure changes is itself a high-value target. An insecure dependency, an unquoted shell argument or a leaked key in the control plane puts every environment it manages at risk.

So every change to InfraOrcinus passes a set of automated gates before it merges, defined in .github/workflows/ci.yml and documented in SECURITY_GATES.md. The pipeline runs on every pull request to main and on every push to main and develop.


1. One Required Check

The pipeline runs many jobs in parallel, then ends in a single job named Security Gates. It depends on every gate that can fail: Go tests, the frontend build, code quality, the server build, OSV-Scanner, Semgrep, gitleaks and both Trivy scans. If any of them fails, Security Gates fails, so it is the one status check a branch rule needs to require.

That list is written down for a reason. A job that runs but is not listed there cannot block a merge. Our two Trivy scans were once in exactly that state: they ran, they could find HIGH and CRITICAL issues, and nothing stopped the merge when they did. They are now listed.

InfraOrcinus Four Automated Security Build Gates
Figure 1: The four security gates: code quality and race-detected tests, Semgrep SAST, dependency and container vulnerability scanning with OSV-Scanner and Trivy, and full-history secret scanning with gitleaks.

2. Gate 1: Correctness, Race Detection and Code Quality

Tests run against real PostgreSQL, with the race detector on. InfraOrcinus's most important guarantees are concurrency guarantees: only one runner may claim a job, and only one run may hold an environment. So the test job starts a PostgreSQL 16 service, applies every migration, and runs the whole suite with go test -race.

A skipped test must not look like a pass. CI once provisioned the wrong database, so every PostgreSQL-backed test, including the atomic job-claim test, skipped silently and the job stayed green. The pipeline now runs the claim tests on their own and fails if any of them reports SKIP.

Formatting and vet block the merge. gofmt and go vet must be clean. The formatting check also had a quiet failure: gofmt -l ./... is not a valid invocation, so for months it checked nothing and passed. It now lists real paths.

golangci-lint is advisory for now. The linter's config used an outdated schema, so the step failed on loading its config and never reported a real finding. After the migration, its first real run surfaced 117 existing issues, mostly unchecked errors. It reports on every run but does not block until that backlog is cleared. We would rather say so than show a gate that is not enforced.

The frontend is type-checked, linted and built on every change too.

# Run Gate 1 locally
go test -race ./...
gofmt -l cmd internal pkg
go vet ./...
golangci-lint run --timeout=5m

3. Gate 2: Static Application Security Testing with Semgrep

Semgrep 2.0.0 scans the Go and TypeScript/JavaScript source with these rule packs:

  • p/owasp-top-ten: injection, broken authentication, sensitive data exposure.
  • p/security-audit: risky crypto, randomness and file permission patterns.
  • p/ci: risky patterns in CI definitions.
  • auto: the rules Semgrep recommends for the languages it detects.

It runs with --error, so any finding fails the build.

This gate had its own silent failure. Two rule packs in the original configuration had been renamed or retired in the Semgrep registry. Semgrep aborts when any configured pack cannot be loaded, so the step failed before scanning a single line, on every run. The configuration now lists only packs that load.


4. Gate 3: Vulnerable Dependencies and Images

Two scanners cover two different questions.

OSV-Scanner v2: are our dependencies known to be vulnerable? It scans the source tree recursively, including Go modules and the frontend's npm lockfile, against the Open Source Vulnerabilities database. Any known vulnerability fails the build. The only way past a finding is a reviewed entry in osv-scanner.toml, with a reason and an expiry date, used only when no fix exists and the vulnerable code is not reachable. Results are uploaded as SARIF to GitHub code scanning.

Trivy: is anything we ship vulnerable?

  • Filesystem scan of the repository, for dependency and configuration issues.
  • Image scan of the actual InfraOrcinus container image, built in CI, including its base image.

Both fail on HIGH or CRITICAL issues that have a fix available. Issues with no fix yet are reported but do not block.

The static-analysis image used to check AI-drafted blueprints is also built in CI, and its tools are run against real broken drafts. If a linter changes its output format, CI fails, instead of the check quietly skipping on customers' runners.


5. Gate 4: Secret Leakage with gitleaks

In CI, the full history is scanned. The checkout uses fetch-depth: 0, and gitleaks scans every commit, not just the latest change. A secret committed in one commit and deleted in the next is still in history and still caught.

On developers' machines, before anything is pushed. The repository ships two git hooks, installed once per clone with ./scripts/install-git-hooks.sh:

  • pre-commit scans the staged changes and refuses the commit on a finding.
  • pre-push scans every commit being pushed, which also catches commits made with --no-verify.

Both fail closed: if gitleaks is not installed, the hook refuses rather than letting the commit through unchecked.

The allowlist is deliberately small. .gitleaks.toml extends gitleaks' default rules and allowlists only the built-in development placeholders, such as the default JWT signing key. Those are not live credentials, and the server refuses to start in production while any of them is still in effect. A real leaked secret is never allowlisted. It is rotated and removed from history.


6. What the Gates Do Not Cover

  • Branch protection is a repository setting. The pipeline makes Security Gates fail when any gate fails. Requiring that check before merge is configured in GitHub, not in the workflow file.
  • Some tools float. OSV-Scanner is installed at its latest version and Semgrep's auto rules come from its registry, so a run can find something new on unchanged code. We treat that as a feature, but it means a green build is a point in time.
  • These gates protect InfraOrcinus's own code. The blueprints you deploy go through InfraOrcinus's run-time controls instead: policy evaluation, the named approval gate, and static analysis of AI-drafted blueprints.

Summary

Every change to InfraOrcinus must pass tests against real PostgreSQL with the race detector, formatting and vet checks, Semgrep's OWASP rules, OSV-Scanner and Trivy for dependencies and the shipped image, and a full-history gitleaks scan, all collected into one required check. Local hooks stop secrets before they are pushed. Several of these gates once passed without checking anything. Each of those was found and fixed, and the one gate that is still advisory, golangci-lint, is labeled as advisory.