-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add missing security workflows (dependency-review, trivy, zizmor) #56
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
base: master
Are you sure you want to change the base?
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,26 @@ | ||
| name: Dependency diff review | ||
|
|
||
| on: | ||
| pull_request: | ||
| branches: | ||
| - master | ||
| - work | ||
|
|
||
| # Restrict to the minimum permissions needed for checkout and dependency review. | ||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| dependency-review: | ||
| name: Dependency diff review | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | ||
| with: | ||
| persist-credentials: false | ||
|
|
||
| - name: Dependency diff review | ||
| uses: actions/dependency-review-action@da24556b548a50705dd671f47852072ea4c105d9 # v4.7.1 | ||
| with: | ||
| fail-on-severity: high | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| name: Trivy repository scan | ||
|
|
||
| on: | ||
| push: | ||
| branches: | ||
| - master | ||
| - work | ||
| pull_request: | ||
| branches: | ||
| - master | ||
|
Comment on lines
+6
to
+10
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 Trivy workflow is scoped to Useful? React with 👍 / 👎. |
||
| - work | ||
|
|
||
| # Restrict to minimum required permissions. | ||
| # security-events: write is required only for SARIF upload to code scanning. | ||
| permissions: | ||
| contents: read | ||
| security-events: write | ||
|
|
||
| jobs: | ||
| trivy: | ||
| name: Trivy filesystem scan | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | ||
| with: | ||
| persist-credentials: false | ||
|
|
||
| - name: Run Trivy filesystem scan | ||
| uses: aquasecurity/trivy-action@6e7b7d1fd3e4fef0c5fa8cce1229c54b2c9bd0d8 # v0.30.0 | ||
|
Comment on lines
+15
to
+30
|
||
| with: | ||
| scan-type: fs | ||
| scan-ref: "." | ||
| severity: HIGH,CRITICAL | ||
| ignore-unfixed: true | ||
| format: sarif | ||
| output: trivy-results.sarif | ||
|
|
||
| - name: Upload Trivy SARIF to code scanning | ||
| # Skip on forked PRs — GitHub does not grant security-events: write to | ||
| # untrusted fork tokens, so SARIF upload would fail with a permissions error. | ||
| if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }} | ||
| uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 | ||
| with: | ||
| sarif_file: trivy-results.sarif | ||
| category: trivy | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| name: zizmor advisory audit | ||
|
|
||
| on: | ||
| pull_request: | ||
| paths: | ||
| - ".github/workflows/**" | ||
|
|
||
| # Restrict to minimum required permissions. | ||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| zizmor: | ||
| name: zizmor workflow audit | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | ||
| with: | ||
| persist-credentials: false | ||
|
|
||
| - name: Install zizmor | ||
| run: pip install zizmor==1.5.0 | ||
|
|
||
| - name: Run zizmor workflow audit | ||
| # Advisory mode — findings are reported but do not fail the job. | ||
| # Maintainers should review and address findings before merging workflow changes. | ||
| run: | | ||
| EXIT_CODE=0 | ||
| zizmor --format plain .github/workflows/ || EXIT_CODE=$? | ||
| if [ $EXIT_CODE -ne 0 ]; then | ||
| echo "::warning::zizmor found workflow security findings (advisory). Review the output above before merging." | ||
| fi | ||
| exit 0 | ||
|
Comment on lines
+28
to
+34
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| import { readFileSync } from 'node:fs'; | ||
| import path from 'node:path'; | ||
|
|
||
| import dotenv from 'dotenv'; | ||
|
|
||
| let envLoaded = false; | ||
|
|
||
| export function loadRuntimeEnv(envPathCandidates?: string[]): void { | ||
| if (envLoaded) return; | ||
|
|
||
| const candidates = | ||
| envPathCandidates ?? | ||
| [ | ||
| path.resolve(process.cwd(), '.env.local'), | ||
| path.resolve(process.cwd(), '.env'), | ||
| path.resolve(process.cwd(), '../../.env.local'), | ||
| path.resolve(process.cwd(), '../../.env') | ||
|
Comment on lines
+16
to
+17
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.
These fallback candidates walk two directories up from the current working directory; when the API is started from the repository root, they resolve to Useful? React with 👍 / 👎. |
||
| ]; | ||
|
|
||
| for (const envPath of candidates) { | ||
| dotenv.config({ path: envPath, override: false }); | ||
| } | ||
|
|
||
| envLoaded = true; | ||
| } | ||
|
|
||
| export function resolveDatabaseUrl(env: NodeJS.ProcessEnv = process.env): string | null { | ||
| const direct = (env.DATABASE_URL || '').trim(); | ||
| if (direct) return direct; | ||
|
|
||
| const candidates = [env.SUPABASE_DB_URL, env.SUPABASE_POOLER_URL, env.SUPABASE_DIRECT_URL]; | ||
|
|
||
| for (const candidate of candidates) { | ||
| const value = (candidate || '').trim(); | ||
| if (value) { | ||
| env.DATABASE_URL = value; | ||
| return value; | ||
| } | ||
| } | ||
|
|
||
| const supabasePassword = (env.SUPABASE_DB_PASSWORD || '').trim(); | ||
| if (supabasePassword) { | ||
| const poolerCandidates = [ | ||
| path.resolve(process.cwd(), 'supabase/.temp/pooler-url'), | ||
| path.resolve(process.cwd(), '../../supabase/.temp/pooler-url'), | ||
| path.resolve(process.env.HOME || '', 'supabase/.temp/pooler-url') | ||
| ]; | ||
|
|
||
| for (const poolerPath of poolerCandidates) { | ||
| try { | ||
| const rawPoolerUrl = readFileSync(poolerPath, 'utf-8').trim(); | ||
| if (!rawPoolerUrl) continue; | ||
|
|
||
| const parsed = new URL(rawPoolerUrl); | ||
| if (!parsed.password) { | ||
| parsed.password = encodeURIComponent(supabasePassword); | ||
|
Comment on lines
+55
to
+56
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.
In the Useful? React with 👍 / 👎. |
||
| } | ||
| parsed.searchParams.set('sslmode', 'require'); | ||
|
|
||
| const resolved = parsed.toString(); | ||
| env.DATABASE_URL = resolved; | ||
| return resolved; | ||
| } catch { | ||
| // Continue searching candidate pooler URLs. | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
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.
This trigger only matches PRs into
master/work, so PRs targetingmainwill never execute the blocking dependency diff check. Given the repository’s branch-protection guidance and required-check setup are defined formain, this leaves the intended high/critical dependency gate inactive on the branch where merges are expected; includemain(or remove the branch filter) so the control actually enforces there.Useful? React with 👍 / 👎.