Skip to content

Commit 543e42d

Browse files
authored
Merge branch 'dev' into test/oversized-test-split-plan-3983
2 parents 204b0bf + 20cf94f commit 543e42d

19 files changed

Lines changed: 705 additions & 18 deletions

.github/CODEOWNERS

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Code owners.
2+
#
3+
# Every file is owned by the maintainer, so that when branch protection has
4+
# "Require review from Code Owners" turned on, no pull request can be merged
5+
# without the maintainer's review. This is the human gate that backs up the
6+
# automated security checks. See docs/security-ci.md for how to turn it on.
7+
8+
* @pewdiepie-archdaemon

.github/dependabot.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Dependabot keeps dependencies and pinned action versions current.
2+
#
3+
# Why this matters for security: every workflow in this repo pins its GitHub
4+
# Actions to an exact commit (a SHA), which is safe but freezes them in time.
5+
# Dependabot opens a small, reviewable pull request whenever a newer version
6+
# exists -- for Python packages, npm packages, the Docker base image, and the
7+
# pinned Actions themselves -- so staying patched does not require manual work.
8+
# Updates are grouped so a week's bumps arrive as one PR per ecosystem, not a
9+
# flood of separate ones.
10+
11+
version: 2
12+
updates:
13+
# Python dependencies (requirements.txt + requirements-optional.txt).
14+
- package-ecosystem: pip
15+
directory: "/"
16+
schedule:
17+
interval: weekly
18+
open-pull-requests-limit: 5
19+
groups:
20+
python:
21+
patterns: ["*"]
22+
23+
# Frontend / tooling npm packages (package.json).
24+
- package-ecosystem: npm
25+
directory: "/"
26+
schedule:
27+
interval: weekly
28+
open-pull-requests-limit: 5
29+
groups:
30+
npm:
31+
patterns: ["*"]
32+
33+
# The pinned action SHAs used across .github/workflows.
34+
- package-ecosystem: github-actions
35+
directory: "/"
36+
schedule:
37+
interval: weekly
38+
open-pull-requests-limit: 5
39+
groups:
40+
actions:
41+
patterns: ["*"]
42+
43+
# The Docker base image in the Dockerfile.
44+
- package-ecosystem: docker
45+
directory: "/"
46+
schedule:
47+
interval: weekly
48+
open-pull-requests-limit: 5

.github/workflows/codeql.yml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# CodeQL code scanning
2+
#
3+
# Purpose: GitHub's own static analysis engine reads the application source
4+
# (Python backend + the JavaScript frontend) and looks for real
5+
# vulnerabilities -- SQL/command injection, path traversal, auth mistakes,
6+
# unsafe deserialization. Findings appear in the repo's Security tab. This is
7+
# the deepest check in the suite and the most valuable for a high-profile
8+
# target.
9+
#
10+
# It runs on every push to main and on a weekly schedule (to catch newly
11+
# disclosed query patterns against unchanged code). It deliberately does NOT
12+
# run on pull requests: most PRs here come from forks, whose read-only token
13+
# cannot publish results, which would produce confusing failures. To scan pull
14+
# requests too, a maintainer can instead enable CodeQL "default setup" in
15+
# Settings -> Security -> Code scanning (one toggle, no file needed) -- see
16+
# docs/security-ci.md.
17+
18+
name: CodeQL
19+
20+
on:
21+
push:
22+
branches: [main]
23+
schedule:
24+
# Weekly, Monday 06:00 UTC.
25+
- cron: '0 6 * * 1'
26+
workflow_dispatch:
27+
28+
permissions: {}
29+
30+
concurrency:
31+
group: codeql-${{ github.workflow }}-${{ github.ref }}
32+
cancel-in-progress: true
33+
34+
jobs:
35+
analyze:
36+
name: Analyze (${{ matrix.language }})
37+
runs-on: ubuntu-latest
38+
permissions:
39+
contents: read
40+
security-events: write # publish results to the Security tab
41+
strategy:
42+
fail-fast: false
43+
matrix:
44+
# Both are interpreted, so CodeQL needs no build step (build-mode none).
45+
language: [python, javascript-typescript]
46+
steps:
47+
- name: Checkout repository
48+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
49+
with:
50+
persist-credentials: false
51+
52+
- name: Initialize CodeQL
53+
uses: github/codeql-action/init@03e4368ac7daa2bd82b3e85262f3bf87ee112f57 # v3.36.0
54+
with:
55+
languages: ${{ matrix.language }}
56+
build-mode: none
57+
58+
- name: Perform CodeQL analysis
59+
uses: github/codeql-action/analyze@03e4368ac7daa2bd82b3e85262f3bf87ee112f57 # v3.36.0
60+
with:
61+
category: "/language:${{ matrix.language }}"
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Container security: Dockerfile lint
2+
#
3+
# Purpose: the Docker image is how most people run Odysseus, so it is part of
4+
# the attack surface. hadolint lints the Dockerfile for mistakes and insecure
5+
# patterns (running as root longer than needed, unpinned base image, bad apt
6+
# usage). Blocking.
7+
#
8+
# The image vulnerability scan (Trivy, advisory) lives in its own file,
9+
# container-trivy.yml. Keeping it separate lets that advisory scan be
10+
# path-filtered and held to a read-only token on pull requests without
11+
# weakening this blocking gate, which must always report so a required check
12+
# never hangs.
13+
#
14+
# Note: a separate open PR (#120) proposes a local `scripts/scan_image.py`.
15+
# This job is complementary -- it is a CI gate, not a script a contributor has
16+
# to remember to run.
17+
18+
name: Container scan
19+
20+
on:
21+
pull_request:
22+
push:
23+
branches: [main]
24+
workflow_dispatch:
25+
26+
permissions: {}
27+
28+
concurrency:
29+
group: container-scan-${{ github.workflow }}-${{ github.ref }}
30+
cancel-in-progress: true
31+
32+
jobs:
33+
hadolint:
34+
name: hadolint (Dockerfile lint)
35+
runs-on: ubuntu-latest
36+
permissions:
37+
contents: read
38+
steps:
39+
- name: Checkout repository
40+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
41+
with:
42+
persist-credentials: false
43+
44+
- name: Lint Dockerfile
45+
uses: hadolint/hadolint-action@2332a7b74a6de0dda2e2221d575162eba76ba5e5 # v3.3.0
46+
with:
47+
dockerfile: Dockerfile
48+
# DL3008: pinning apt package versions is impractical on a -slim base
49+
# image. Debian purges old package versions from its repos, so a
50+
# pinned version breaks future rebuilds. The base image itself is
51+
# what should be pinned (tracked by Dependabot's docker ecosystem).
52+
ignore: DL3008
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# Container image vulnerability scan (advisory)
2+
#
3+
# Trivy builds the application image and scans it for known-vulnerable OS and
4+
# Python packages. Advisory only -- it reports findings to the repo's Security
5+
# tab without blocking a merge, because the image inevitably contains
6+
# already-known CVEs in upstream packages that are not this project's bug.
7+
#
8+
# Split from the Dockerfile lint (container-scan.yml) for two reasons:
9+
#
10+
# - Least privilege. The image build runs Dockerfile instructions, which on a
11+
# pull request are attacker-influenceable. That path (the `scan` job) is
12+
# held to a read-only token and never publishes results. Only `publish`,
13+
# which runs on push to main (curated, fast-forwarded from reviewed dev),
14+
# gets security-events:write to upload SARIF.
15+
# - Cost. Docs-only changes do not rebuild the image (paths-ignore below),
16+
# matching docker-publish.yml. hadolint stays on the broad trigger in
17+
# container-scan.yml so the blocking gate always reports.
18+
19+
name: Container scan (Trivy)
20+
21+
on:
22+
pull_request:
23+
paths-ignore:
24+
- '**.md'
25+
- 'docs/**'
26+
- '.github/ISSUE_TEMPLATE/**'
27+
push:
28+
branches: [main]
29+
paths-ignore:
30+
- '**.md'
31+
- 'docs/**'
32+
- '.github/ISSUE_TEMPLATE/**'
33+
workflow_dispatch:
34+
35+
permissions: {}
36+
37+
concurrency:
38+
group: container-trivy-${{ github.workflow }}-${{ github.ref }}
39+
cancel-in-progress: true
40+
41+
jobs:
42+
# Pull requests and manual runs: build and scan under a read-only token.
43+
# The build executes PR-supplied Dockerfile instructions, so this job must
44+
# not hold any write scope, and it does not upload to the Security tab.
45+
scan:
46+
name: Trivy (image scan, advisory)
47+
if: github.event_name != 'push'
48+
runs-on: ubuntu-latest
49+
# Advisory: a CVE in an upstream package must not block a PR.
50+
continue-on-error: true
51+
permissions:
52+
contents: read
53+
steps:
54+
- name: Checkout repository
55+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
56+
with:
57+
persist-credentials: false
58+
59+
- name: Set up Buildx
60+
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
61+
62+
# Build without pushing so a broken Dockerfile is caught here, and the
63+
# exact image we ship is what gets scanned.
64+
- name: Build image
65+
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
66+
with:
67+
context: .
68+
push: false
69+
load: true
70+
tags: odysseus:ci
71+
72+
- name: Scan image with Trivy
73+
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
74+
with:
75+
image-ref: odysseus:ci
76+
format: table
77+
ignore-unfixed: true
78+
env:
79+
# Pin the vuln DB source to GHCR to avoid rate-limited Docker Hub
80+
# mirrors that flake on shared runners.
81+
TRIVY_DB_REPOSITORY: ghcr.io/aquasecurity/trivy-db:2
82+
83+
# Push to main only: build, scan, and publish SARIF to the Security tab.
84+
# This is the only path that runs trusted code, so it is the only one granted
85+
# security-events:write.
86+
publish:
87+
name: Trivy (image scan + SARIF upload)
88+
if: github.event_name == 'push'
89+
runs-on: ubuntu-latest
90+
continue-on-error: true
91+
permissions:
92+
contents: read
93+
security-events: write # upload SARIF to the Security tab
94+
steps:
95+
- name: Checkout repository
96+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
97+
with:
98+
persist-credentials: false
99+
100+
- name: Set up Buildx
101+
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
102+
103+
- name: Build image
104+
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
105+
with:
106+
context: .
107+
push: false
108+
load: true
109+
tags: odysseus:ci
110+
111+
- name: Scan image with Trivy
112+
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
113+
with:
114+
image-ref: odysseus:ci
115+
format: sarif
116+
output: trivy-results.sarif
117+
ignore-unfixed: true
118+
env:
119+
TRIVY_DB_REPOSITORY: ghcr.io/aquasecurity/trivy-db:2
120+
121+
- name: Upload Trivy results
122+
uses: github/codeql-action/upload-sarif@03e4368ac7daa2bd82b3e85262f3bf87ee112f57 # v3.36.0
123+
with:
124+
sarif_file: trivy-results.sarif
125+
category: trivy-image
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Supply-chain review
2+
#
3+
# Purpose: defend against "side-chain" / supply-chain attacks -- a pull request
4+
# that adds (or bumps) a dependency to a version with a known vulnerability or a
5+
# disallowed license. Two layers:
6+
#
7+
# - dependency-review: runs ONLY on pull requests. It compares the
8+
# dependencies before and after the PR and blocks the merge if the change
9+
# pulls in a package with a known security advisory. This is the gate.
10+
# - pip-audit: scans the project's current Python requirements against the
11+
# advisory database. Advisory only (it never blocks a merge), because it can
12+
# flag a pre-existing issue in an already-shipped dependency.
13+
14+
name: Dependency review
15+
16+
on:
17+
pull_request:
18+
push:
19+
branches: [main]
20+
workflow_dispatch:
21+
22+
# Default-deny token; jobs grant only read access.
23+
permissions: {}
24+
25+
concurrency:
26+
group: dependency-review-${{ github.workflow }}-${{ github.ref }}
27+
cancel-in-progress: true
28+
29+
jobs:
30+
dependency-review:
31+
name: dependency-review (PR gate)
32+
# Only meaningful on a pull request -- it needs a base..head diff to review.
33+
if: github.event_name == 'pull_request'
34+
runs-on: ubuntu-latest
35+
permissions:
36+
contents: read
37+
steps:
38+
- name: Checkout repository
39+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
40+
with:
41+
persist-credentials: false
42+
43+
- name: Review dependency changes
44+
uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
45+
with:
46+
# Fail the PR on any newly introduced moderate-or-worse advisory.
47+
fail-on-severity: moderate
48+
49+
pip-audit:
50+
name: pip-audit (advisory)
51+
runs-on: ubuntu-latest
52+
# Advisory: report known-vulnerable Python deps without blocking the merge.
53+
continue-on-error: true
54+
permissions:
55+
contents: read
56+
steps:
57+
- name: Checkout repository
58+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
59+
with:
60+
persist-credentials: false
61+
62+
- name: Set up Python
63+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
64+
with:
65+
python-version: '3.12'
66+
67+
- name: Run pip-audit on requirements
68+
run: |
69+
set -euo pipefail
70+
pip install pip-audit==2.10.0
71+
pip-audit -r requirements.txt -r requirements-optional.txt --strict

0 commit comments

Comments
 (0)