diff --git a/.github/workflows/trivy_security_scans.yml b/.github/workflows/trivy_security_scans.yml index 43ecfcbe..3e3d01f5 100644 --- a/.github/workflows/trivy_security_scans.yml +++ b/.github/workflows/trivy_security_scans.yml @@ -1,7 +1,9 @@ name: Trivy Security Scans permissions: - contents: read # Minimal permissions needed for scanning source and images + contents: read + # Needed if you later add SARIF upload to GitHub Security + # security-events: write on: push: @@ -13,7 +15,7 @@ on: - main - development schedule: - - cron: "0 8 * * 1" # Weekly scan on Mondays at 8 AM UTC + - cron: "0 8 * * 1" # Weekly on Mondays at 8 AM UTC jobs: filesystem-scan: @@ -33,6 +35,8 @@ jobs: exit-code: 1 ignore-unfixed: true severity: CRITICAL,HIGH + # Use .trivyignore to suppress known false positives + trivyignores: .trivyignore image-scan: name: Trivy Docker Image Scan (Backend & Frontend) @@ -66,6 +70,7 @@ jobs: exit-code: 1 ignore-unfixed: true severity: CRITICAL,HIGH + trivyignores: .trivyignore - name: Scan frontend Docker image with Trivy uses: aquasecurity/trivy-action@master @@ -75,3 +80,4 @@ jobs: exit-code: 1 ignore-unfixed: true severity: CRITICAL,HIGH + trivyignores: .trivyignore diff --git a/.trivyignore b/.trivyignore new file mode 100644 index 00000000..b38cf485 --- /dev/null +++ b/.trivyignore @@ -0,0 +1,10 @@ +# Node.js / npm ecosystem + +# glob CLI command injection (CVE-2025-64756) +# Only affects glob -c/--cmd; we only use glob as a library in Vite/SvelteKit. +CVE-2025-64756 + +# Go stdlib false positives in esbuild binary +# esbuild doesn't use the vulnerable archive/tar or crypto/x509 paths in a way that's exploitable. +CVE-2025-58183 +CVE-2025-61729 diff --git a/backend/server/adventures/geocoding.py b/backend/server/adventures/geocoding.py index feb9a9d4..fb80c32f 100644 --- a/backend/server/adventures/geocoding.py +++ b/backend/server/adventures/geocoding.py @@ -20,8 +20,7 @@ def search_google(query): headers = { 'Content-Type': 'application/json', 'X-Goog-Api-Key': api_key, - 'X-Goog-FieldMask': 'places.displayName.text,places.formattedAddress,places.location,places.types,places.rating,places.userRatingCount', - 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + 'X-Goog-FieldMask': 'places.displayName.text,places.formattedAddress,places.location,places.types,places.rating,places.userRatingCount' } payload = { @@ -29,8 +28,7 @@ def search_google(query): "maxResultCount": 20 # Adjust as needed } - response = requests.post(url, json=payload, headers=headers, timeout=(2, 5), proxies={"http": None, "https": None}, # Disable proxy - ) + response = requests.post(url, json=payload, headers=headers, timeout=(2, 5)) response.raise_for_status() data = response.json()