-
Notifications
You must be signed in to change notification settings - Fork 574
fips base image #2310
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fips base image #2310
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,289 @@ | ||
| --- | ||
| title: "Security at Bifrost" | ||
| description: "Overview of security practices across Bifrost's CI/CD pipelines, container images, supply chain, and deployment infrastructure." | ||
| icon: "shield" | ||
| sidebarTitle: "Security" | ||
| --- | ||
|
|
||
| Bifrost applies defense-in-depth across its open-source and enterprise repositories. Every pull request, | ||
| dependency update, and container image goes through multiple layers of automated security checks before | ||
| reaching production. | ||
|
|
||
| | Domain | Tool / Practice | Coverage | | ||
| | --- | --- | --- | | ||
| | Dependency Scanning | Snyk Open Source | Go, Node, Python — all projects | | ||
| | SAST | Snyk Code, CodeQL | Full codebase static analysis | | ||
| | Container Scanning | Docker Scout | Docker Hub auto-scan on push | | ||
| | Artifact Scanning | GCP Artifact Registry | Enterprise container images | | ||
| | Dependency Updates | Dependabot | gomod, npm, Docker, GitHub Actions | | ||
| | Supply Chain | SHA pinning, npm provenance | 100 % of GitHub Actions (OSS) | | ||
| | Container Hardening | FIPS base image, non-root user | Production Dockerfile | | ||
| | Security Hardening | StepSecurity, CODEOWNERS | Workflow hardening, code review gates | | ||
| | Network Security | Tailscale VPN | Enterprise deployments | | ||
|
|
||
| --- | ||
|
|
||
| ## Vulnerability Scanning — Snyk | ||
|
|
||
| Bifrost runs two Snyk scanning jobs on every push and pull request. Results are uploaded as | ||
| [SARIF](https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/sarif-support-for-code-scanning) | ||
| to the GitHub Security tab. | ||
|
|
||
| <Tabs> | ||
| <Tab title="Dependency Scanning (Open Source)"> | ||
| The **Snyk Open Source** job scans all Go, Node, and Python dependencies for known vulnerabilities. | ||
|
|
||
| ```yaml | ||
| snyk test --all-projects --detection-depth=4 --sarif-file-output=snyk.sarif | ||
| ``` | ||
|
|
||
| - Scans every module across `core/`, `framework/`, `transports/`, `plugins/`, `ui/`, and `tests/` | ||
| - Detection depth of 4 catches transitive dependencies | ||
| - Snyk CLI pinned to `v1.1303.2` | ||
|
|
||
| </Tab> | ||
|
|
||
| <Tab title="SAST (Snyk Code)"> | ||
| The **Snyk Code** job performs Static Application Security Testing on the full codebase. | ||
| A complete build is performed first (Go + Node + Python) so Snyk can analyze compiled artifacts. | ||
|
|
||
| ```yaml | ||
| snyk code test --sarif-file-output=snyk-code.sarif | ||
| ``` | ||
|
|
||
| - Detects injection flaws, hardcoded secrets, insecure crypto, and other code-level vulnerabilities | ||
| - Builds the full project before scanning for accurate analysis | ||
| </Tab> | ||
| </Tabs> | ||
|
|
||
| <Note> | ||
| Snyk checks can be skipped by including `--skip-pipeline` in the first line of a commit message. This is | ||
| intended for documentation-only or CI configuration changes. | ||
| </Note> | ||
|
|
||
| --- | ||
|
|
||
| ## Container Image Security | ||
|
|
||
| ### Dockerfile Hardening | ||
|
|
||
| Production containers follow a strict hardening checklist: | ||
|
|
||
| <CardGroup cols={2}> | ||
| <Card title="Multi-stage builds" icon="layer-group"> | ||
| Three stages — UI builder (Node), Go builder, and minimal Alpine runtime — ensure no build tools or | ||
| source code leak into the final image. | ||
| </Card> | ||
| <Card title="FIPS-compliant base image" icon="lock"> | ||
| Production images use a FIPS 140-2 validated Alpine base image with compliant OpenSSL. | ||
| </Card> | ||
| <Card title="Non-root execution" icon="user-shield"> | ||
| The FIPS base image includes a dedicated `appuser`. The container runs as this unprivileged user — | ||
| never as root. | ||
| </Card> | ||
| <Card title="Binary stripping" icon="minimize"> | ||
| Go binaries are compiled with `-ldflags="-w -s"` to strip debug symbols and DWARF information, | ||
| reducing attack surface and image size. | ||
| </Card> | ||
| </CardGroup> | ||
|
|
||
| Additional hardening measures: | ||
|
|
||
| - **Static builds** — Compiled with `-tags "sqlite_static"` and `-extldflags '-static'` for fully static linking | ||
| - **Build verification** — `RUN test -f /app/main || exit 1` ensures the binary exists before proceeding | ||
| - **CVE patching** — Enterprise Dockerfiles include targeted patches (e.g., `apk upgrade --no-cache openssl` for CVE-2026-22796) | ||
| - **Minimal runtime dependencies** — The FIPS base image provides only essential libraries (`musl`, `libgcc`, `ca-certificates`) | ||
|
|
||
| ```dockerfile | ||
| # Runtime stage excerpt (production) | ||
| FROM <fips-validated-alpine-base> | ||
| WORKDIR /app | ||
|
|
||
| COPY --from=builder /app/main . | ||
| COPY --from=builder /app/docker-entrypoint.sh . | ||
|
|
||
| RUN mkdir -p $APP_DIR/logs | ||
| USER appuser | ||
|
|
||
| ENTRYPOINT ["/app/docker-entrypoint.sh"] | ||
| CMD ["/app/main"] | ||
| ``` | ||
|
|
||
| <Frame> | ||
| <img src="/media/security/hardned-base-image.png" alt="FIPS-compliant hardened base image in Dockerfile" /> | ||
| </Frame> | ||
|
|
||
| ### Docker Scout | ||
|
|
||
| [Docker Scout](https://docs.docker.com/scout/) is enabled at the Docker Hub repository level for the | ||
| `maximhq/bifrost` image. Every image pushed to Docker Hub is automatically scanned for CVEs against | ||
| continuously updated vulnerability databases. | ||
|
|
||
| <Frame> | ||
| <img src="/media/security/scout-image-score.png" alt="Docker Scout image score showing vulnerability assessment" /> | ||
| </Frame> | ||
|
|
||
| ### GCP Artifact Registry Scanning | ||
|
|
||
| Enterprise images are pushed to **GCP Artifact Registry** (and AWS ECR for select environments). | ||
| GCP Artifact Registry provides [built-in vulnerability scanning](https://cloud.google.com/artifact-registry/docs/analysis) | ||
| that automatically analyzes container images for OS and language package vulnerabilities. | ||
|
|
||
| --- | ||
|
|
||
| ## Supply Chain Security | ||
|
|
||
| ### GitHub Actions SHA Pinning | ||
|
|
||
| All GitHub Actions in the open-source repository are pinned to exact commit SHAs — not mutable version | ||
| tags. This prevents supply chain attacks where a compromised action maintainer could push malicious code | ||
| to an existing tag. | ||
|
|
||
| ```yaml | ||
| # Every action is pinned to a full SHA with a version comment | ||
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | ||
| - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 | ||
| - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 | ||
| ``` | ||
|
|
||
| **Coverage:** | ||
|
|
||
| | Repository | Pinning Strategy | Actions Pinned | | ||
| | --- | --- | --- | | ||
| | `bifrost` (OSS) | Full SHA with version comment | 103 / 103 (100 %) | | ||
| | `bifrost-enterprise` | Version tags (`@v4`) | Upgrade planned | | ||
|
|
||
| ### NPM Provenance | ||
|
|
||
| Published npm packages include [SLSA provenance attestations](https://docs.npmjs.com/generating-provenance-statements), | ||
| providing a verifiable link between the published package and its source commit. | ||
|
|
||
| ```yaml | ||
| permissions: | ||
| id-token: write # Required for npm provenance | ||
|
|
||
| # ... | ||
| npm publish --provenance --access public | ||
| ``` | ||
|
|
||
| ### Dependency Pinning in CI | ||
|
|
||
| All language runtimes are pinned to specific versions across CI workflows to ensure reproducible builds | ||
| and prevent unexpected behavior from runtime updates. | ||
|
|
||
| | Runtime | Pinned Version | Used For | | ||
| | --- | --- | --- | | ||
| | Go | `1.26.1` | Core build, tests | | ||
| | Node | `25` | UI build, npm packages | | ||
| | Python | `3.11` | Integration and governance tests | | ||
| | uv | SHA-pinned via `astral-sh/setup-uv` | Python package management | | ||
|
|
||
| Python test dependencies are locked via `uv.lock` files for deterministic, reproducible installs: | ||
|
|
||
| ``` | ||
| tests/integrations/uv.lock | ||
| tests/governance/uv.lock | ||
| ``` | ||
|
|
||
| <Frame> | ||
| <img src="/media/security/dep-pinning.png" alt="Pinned dependency versions across CI workflows" /> | ||
| </Frame> | ||
|
|
||
| --- | ||
|
|
||
| ## Dependency Management — Dependabot | ||
|
|
||
| Dependabot monitors four ecosystems on a weekly schedule, automatically opening pull requests for | ||
| outdated or vulnerable dependencies. | ||
|
|
||
| <CardGroup cols={2}> | ||
| <Card title="Go Modules" icon="golang"> | ||
| Covers `/core`, `/framework`, `/transports`, `/plugins/*`, and `/examples/**` | ||
| </Card> | ||
| <Card title="npm Packages" icon="npm"> | ||
| Covers `/ui`, `/npx`, and `/examples/**` | ||
| </Card> | ||
| <Card title="Docker Images" icon="docker"> | ||
| Monitors base images in `/transports` | ||
| </Card> | ||
| <Card title="GitHub Actions" icon="github"> | ||
| Tracks action version updates across all workflows | ||
| </Card> | ||
| </CardGroup> | ||
|
|
||
| A separate **Dependabot Alerts** workflow runs daily and automatically | ||
| creates GitHub issues for any open Dependabot security alerts, categorized by severity and ecosystem. | ||
|
|
||
| --- | ||
|
|
||
| ## Code Analysis — CodeQL | ||
|
|
||
| GitHub's [CodeQL](https://codeql.github.com/) performs semantic code analysis on every push and pull request, | ||
| complementing Snyk's SAST coverage with GitHub-native findings. | ||
|
|
||
| - Analyzes Go and JavaScript/TypeScript codebases | ||
| - Detects security vulnerabilities, bugs, and code quality issues using GitHub's query suites | ||
| - Results appear directly in the GitHub Security tab alongside Snyk findings | ||
|
|
||
| <Frame> | ||
| <img src="/media/security/codeql.png" alt="CodeQL analysis results in GitHub Security tab" /> | ||
| </Frame> | ||
|
|
||
| --- | ||
|
|
||
| ## Workflow & Network Security | ||
|
|
||
| ### Principle of Least Privilege | ||
|
|
||
| All GitHub Actions workflows follow the principle of least privilege. Permissions are set at the | ||
| job level, not the workflow level, and are scoped to the minimum required. | ||
|
|
||
| | Permission | Granted To | Reason | | ||
| | --- | --- | --- | | ||
| | `contents: read` | All jobs (default) | Read repository code | | ||
| | `contents: write` | Tag creation, releases | Create git tags and releases | | ||
| | `security-events: write` | Snyk jobs | Upload SARIF to Security tab | | ||
| | `id-token: write` | Cloud auth, npm publish | OIDC federation, npm provenance | | ||
| | `pull-requests: write` | PR test reporters | Post test results as PR comments | | ||
|
|
||
| ### Tailscale VPN | ||
|
|
||
| Enterprise deployment workflows authenticate through [Tailscale](https://tailscale.com/) before | ||
| accessing any infrastructure. This ensures that CI/CD runners can only reach deployment targets | ||
| through an encrypted, identity-aware network — never over the public internet. | ||
|
|
||
| ```yaml | ||
| - name: Authenticate Tailscale | ||
| uses: tailscale/github-action@v4 | ||
| with: | ||
| oauth-client-id: '${{ secrets.TS_OAUTH_CLIENT_ID }}' | ||
| oauth-secret: '${{ secrets.TS_OAUTH_SECRET }}' | ||
| tags: 'tag:gha-ci' | ||
| version: 1.84.0 | ||
| ``` | ||
|
|
||
| - **OAuth-based authentication** — No long-lived API keys; runners authenticate via OAuth client credentials | ||
| - **Version pinned** — Tailscale `1.84.0` to prevent unexpected behavior from updates | ||
| - **Tagged runners** — `gha-ci` tag enables Tailscale ACL policies scoped to CI/CD access | ||
|
|
||
| ### StepSecurity | ||
|
|
||
| [StepSecurity](https://www.stepsecurity.io/) automatically hardens GitHub Actions workflows by applying | ||
| security best practices across all CI/CD pipelines. | ||
|
|
||
| - Adds `permissions` blocks to workflows that are missing them | ||
| - Pins action versions to full SHAs where mutable tags were used | ||
| - Detects insecure patterns like unquoted interpolations and artifact poisoning risks | ||
|
|
||
| <Frame> | ||
| <img src="/media/security/step-security.png" alt="StepSecurity automated security hardening applied to GitHub Actions workflows" /> | ||
| </Frame> | ||
|
|
||
| ### CODEOWNERS | ||
|
|
||
| Critical paths in the repository are protected by a `CODEOWNERS` file, ensuring that changes to | ||
| security-sensitive areas require review from designated maintainers before merging. | ||
|
|
||
| <Frame> | ||
| <img src="/media/security/codeowners.png" alt="CODEOWNERS file enforcing review gates on security-critical paths" /> | ||
| </Frame> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,19 +44,14 @@ RUN go build \ | |
| -o /app/main \ | ||
| ./bifrost-http | ||
|
|
||
| # Verify build succeeded | ||
| # Verify build succeeded and prepare entrypoint | ||
| RUN test -f /app/main || (echo "Build failed" && exit 1) | ||
| RUN chmod +x /build/transports/docker-entrypoint.sh | ||
|
|
||
| # --- Runtime Stage: Minimal runtime image --- | ||
| FROM alpine:3.23.3@sha256:25109184c71bdad752c8312a8623239686a9a2071e8825f20acb8f2198c3f659 | ||
| FROM bifrosthq/dhi-alpine-base:3.22-fips_bifrost-v27032026 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The original base image was digest-pinned ( Consider pinning to the image digest for reproducible and tamper-resistant builds: FROM bifrosthq/dhi-alpine-base:3.22-fips_bifrost-v27032026@sha256:<digest>The same applies to |
||
| WORKDIR /app | ||
|
|
||
| # Install runtime dependencies for CGO-enabled binary | ||
| # musl: C standard library (required for CGO binaries) | ||
| # libgcc: GCC runtime library | ||
| # ca-certificates: For HTTPS connections | ||
| RUN apk add --no-cache musl libgcc ca-certificates wget | ||
|
|
||
| # Create data directory and set up user | ||
| COPY --from=builder /app/main . | ||
| COPY --from=builder /app/docker-entrypoint.sh . | ||
|
|
@@ -86,21 +81,14 @@ ENV GOGC="" \ | |
| GOMEMLIMIT="" | ||
|
|
||
|
|
||
| RUN mkdir -p $APP_DIR/logs && \ | ||
| adduser -D -s /bin/sh appuser && \ | ||
| chown -R appuser:appuser /app && \ | ||
| chmod +x /app/docker-entrypoint.sh | ||
| RUN mkdir -p $APP_DIR/logs | ||
| USER appuser | ||
|
Comment on lines
+84
to
85
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The previous Dockerfile included The FIPS base image is expected to provide Consider adding the missing ownership fix: RUN mkdir -p $APP_DIR/logs && chown -R appuser:appuser /app
USER appuser |
||
|
|
||
|
|
||
| # Declare volume for data persistence | ||
| VOLUME ["/app/data"] | ||
| EXPOSE $APP_PORT | ||
|
|
||
| # Health check for container status monitoring | ||
| HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ | ||
| CMD wget --no-verbose --tries=1 -O /dev/null http://127.0.0.1:${APP_PORT}/health || exit 1 | ||
|
|
||
| # Use entrypoint script that handles volume permissions and argument processing | ||
| ENTRYPOINT ["/app/docker-entrypoint.sh"] | ||
| CMD ["/app/main"] | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
chmodin builder stageThe builder's
WORKDIRis/appand the transports directory is copied there withCOPY transports/ ./, sodocker-entrypoint.shlands at/app/docker-entrypoint.sh. The path/build/transports/docker-entrypoint.shdoes not exist in this build stage —chmodwill fail with a non-zero exit code, causing the Docker build to fail entirely.This path is correct for
Dockerfile.local(whereWORKDIRis/build), but it was incorrectly copied verbatim here.