Compare commits

..

1 Commits

Author SHA1 Message Date
Paperclip c85c9b12a7 feat(ci): add Trivy image vulnerability scanning to all Docker builds
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-14 15:21:08 +00:00
6 changed files with 48 additions and 76 deletions
+36 -43
View File
@@ -163,20 +163,20 @@ jobs:
cache-from: type=gha cache-from: type=gha
cache-to: type=gha,mode=max cache-to: type=gha,mode=max
- name: Scan frontend image for vulnerabilities - name: Run Trivy vulnerability scanner
uses: anchore/scan-action@v5 uses: aquasecurity/trivy-action@0.28.0
id: scan
with: with:
image: "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:sha-${{ github.sha }}" image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:sha-${{ github.sha }}
fail-build: true format: 'sarif'
severity-cutoff: high output: 'trivy-results-frontend.sarif'
output-format: sarif severity: 'CRITICAL,HIGH'
exit-code: '1'
- name: Upload frontend scan results to GitHub Security - name: Upload Trivy scan results to GitHub Security
uses: github/codeql-action/upload-sarif@v3 uses: github/codeql-action/upload-sarif@v3
if: always() if: always()
with: with:
sarif_file: ${{ steps.scan.outputs.sarif }} sarif_file: 'trivy-results-frontend.sarif'
- name: Push Docker image - name: Push Docker image
if: github.event_name == 'push' if: github.event_name == 'push'
@@ -186,7 +186,6 @@ jobs:
push: true push: true
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
target: prod
cache-from: type=gha cache-from: type=gha
- name: Create git tag - name: Create git tag
@@ -256,23 +255,21 @@ jobs:
load: true load: true
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Scan auth image for vulnerabilities - name: Run Trivy vulnerability scanner
uses: anchore/scan-action@v5 uses: aquasecurity/trivy-action@0.28.0
id: scan
with: with:
image: "${{ env.REGISTRY }}/${{ env.AUTH_IMAGE_NAME }}:sha-${{ github.sha }}" image-ref: ${{ env.REGISTRY }}/${{ env.AUTH_IMAGE_NAME }}:sha-${{ github.sha }}
fail-build: true format: 'sarif'
severity-cutoff: high output: 'trivy-results-auth.sarif'
output-format: sarif severity: 'CRITICAL,HIGH'
exit-code: '1'
- name: Upload auth scan results to GitHub Security - name: Upload Trivy scan results to GitHub Security
uses: github/codeql-action/upload-sarif@v3 uses: github/codeql-action/upload-sarif@v3
if: always() if: always()
with: with:
sarif_file: ${{ steps.scan.outputs.sarif }} sarif_file: 'trivy-results-auth.sarif'
- name: Push Docker image - name: Push Docker image
if: github.event_name == 'push' if: github.event_name == 'push'
@@ -341,23 +338,21 @@ jobs:
load: true load: true
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Scan receiptwitness image for vulnerabilities - name: Run Trivy vulnerability scanner
uses: anchore/scan-action@v5 uses: aquasecurity/trivy-action@0.28.0
id: scan
with: with:
image: "${{ env.REGISTRY }}/${{ env.RECEIPTWITNESS_IMAGE_NAME }}:sha-${{ github.sha }}" image-ref: ${{ env.REGISTRY }}/${{ env.RECEIPTWITNESS_IMAGE_NAME }}:sha-${{ github.sha }}
fail-build: true format: 'sarif'
severity-cutoff: high output: 'trivy-results-receiptwitness.sarif'
output-format: sarif severity: 'CRITICAL,HIGH'
exit-code: '1'
- name: Upload receiptwitness scan results to GitHub Security - name: Upload Trivy scan results to GitHub Security
uses: github/codeql-action/upload-sarif@v3 uses: github/codeql-action/upload-sarif@v3
if: always() if: always()
with: with:
sarif_file: ${{ steps.scan.outputs.sarif }} sarif_file: 'trivy-results-receiptwitness.sarif'
- name: Push Docker image - name: Push Docker image
if: github.event_name == 'push' if: github.event_name == 'push'
@@ -426,23 +421,21 @@ jobs:
load: true load: true
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Scan api image for vulnerabilities - name: Run Trivy vulnerability scanner
uses: anchore/scan-action@v5 uses: aquasecurity/trivy-action@0.28.0
id: scan
with: with:
image: "${{ env.REGISTRY }}/${{ env.API_IMAGE_NAME }}:sha-${{ github.sha }}" image-ref: ${{ env.REGISTRY }}/${{ env.API_IMAGE_NAME }}:sha-${{ github.sha }}
fail-build: true format: 'sarif'
severity-cutoff: high output: 'trivy-results-api.sarif'
output-format: sarif severity: 'CRITICAL,HIGH'
exit-code: '1'
- name: Upload api scan results to GitHub Security - name: Upload Trivy scan results to GitHub Security
uses: github/codeql-action/upload-sarif@v3 uses: github/codeql-action/upload-sarif@v3
if: always() if: always()
with: with:
sarif_file: ${{ steps.scan.outputs.sarif }} sarif_file: 'trivy-results-api.sarif'
- name: Push Docker image - name: Push Docker image
if: github.event_name == 'push' if: github.event_name == 'push'
+6 -12
View File
@@ -4,23 +4,17 @@ import pg from "pg";
const { Pool } = pg; const { Pool } = pg;
const pool = new Pool({
connectionString:
process.env.DATABASE_URL ??
"postgresql://cartsnitch:cartsnitch@localhost:5432/cartsnitch",
});
const secret = process.env.BETTER_AUTH_SECRET; const secret = process.env.BETTER_AUTH_SECRET;
if (!secret) { if (!secret) {
throw new Error("BETTER_AUTH_SECRET environment variable is required"); throw new Error("BETTER_AUTH_SECRET environment variable is required");
} }
const databaseUrl = process.env.DATABASE_URL;
if (!databaseUrl) {
console.warn(
"WARNING: DATABASE_URL is not set — using default localhost connection. " +
"Set DATABASE_URL for production deployments."
);
}
export const pool = new Pool({
connectionString: databaseUrl ?? "postgresql://cartsnitch:cartsnitch@localhost:5432/cartsnitch",
});
export const auth = betterAuth({ export const auth = betterAuth({
database: pool, database: pool,
basePath: "/auth", basePath: "/auth",
+3 -17
View File
@@ -1,6 +1,6 @@
import { createServer } from "node:http"; import { createServer } from "node:http";
import { toNodeHandler } from "better-auth/node"; import { toNodeHandler } from "better-auth/node";
import { auth, pool } from "./auth.js"; import { auth } from "./auth.js";
const port = parseInt(process.env.PORT ?? "3001", 10); const port = parseInt(process.env.PORT ?? "3001", 10);
@@ -9,22 +9,8 @@ const handler = toNodeHandler(auth);
const server = createServer(async (req, res) => { const server = createServer(async (req, res) => {
// Health check // Health check
if (req.url === "/health" && req.method === "GET") { if (req.url === "/health" && req.method === "GET") {
try { res.writeHead(200, { "Content-Type": "application/json" });
const client = await pool.connect(); res.end(JSON.stringify({ status: "ok" }));
try {
await Promise.race([
client.query("SELECT 1"),
new Promise((_, reject) => setTimeout(() => reject(new Error("DB timeout")), 2000)),
]);
} finally {
client.release();
}
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ status: "ok", db: "connected" }));
} catch {
res.writeHead(503, { "Content-Type": "application/json" });
res.end(JSON.stringify({ status: "error", db: "unreachable" }));
}
return; return;
} }
Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Submodule cartsnitch deleted from a53daddb9a
+3 -3
View File
@@ -9805,9 +9805,9 @@
} }
}, },
"node_modules/vite": { "node_modules/vite": {
"version": "6.4.2", "version": "6.4.1",
"resolved": "https://registry.npmjs.org/vite/-/vite-6.4.2.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz",
"integrity": "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==", "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
"devOptional": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {