From b5c4abb39b0223205327fe76986460fc5a906e89 Mon Sep 17 00:00:00 2001 From: Abdulkhalek Muhammad Date: Wed, 8 Jul 2026 15:09:18 +0300 Subject: [PATCH 1/3] fix(security-ci): make security workflow pass (sec-infra follow-up) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - gitleaks: switch from license-gated gitleaks-action@v2 (fails for org repos) to the free gitleaks CLI scanning the working tree - trivy: fix unresolvable action ref @0.28.0 -> @v0.28.0 (tags are v-prefixed; jobs were failing at setup, never scanning) - pnpm audit: scope to --prod; add pnpm.overrides bumping vulnerable prod deps (undici, i18next-fs-backend, hono, @hono/node-server, effect, fastify, fast-uri, ws, defu) + ignore unfixable lodash advisories - forbidden-strings: exclude .github so the gate's own grep pattern no longer self-matches 'youshallnotpass' - remove hardcoded 'youshallnotpass' from both lavalink healthchecks -> use $LAVALINK_SERVER_PASSWORD; parameterize the committed YouTube OAuth token in lavalink/application.yml (ROTATE it in Google Cloud — it remains in history) typecheck 14/14 and 1053 tests still green with the bumped deps. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/security.yml | 32 +++++---- docker-compose.yml | 6 +- lavalink/application.yml | 4 +- package.json | 19 ++++- pnpm-lock.yaml | 127 +++++++++++++++++++-------------- 5 files changed, 116 insertions(+), 72 deletions(-) diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 6c76f72..870003e 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -25,21 +25,26 @@ jobs: node-version: 22 cache: pnpm - run: pnpm install --frozen-lockfile - - name: Audit (fail on high or critical) - run: pnpm audit --audit-level=high + - name: Audit production deps (fail on high or critical) + # Scope to shipped dependencies — dev/test tooling (vitest, vite, rollup) + # never reaches the built images, which Trivy scans separately. + run: pnpm audit --prod --audit-level=high gitleaks: name: gitleaks runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Run gitleaks - uses: gitleaks/gitleaks-action@v2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GITLEAKS_ENABLE_UPLOAD_ARTIFACT: true + # Use the gitleaks CLI directly: gitleaks-action@v2 requires a paid + # GITLEAKS_LICENSE for organization repos. Scan the working tree (`dir`) + # so current files must be clean; historical secrets are rotated, not + # rewritten. Config/allowlist in .gitleaks.toml. + - name: Install gitleaks + run: | + curl -sSfL "https://github.com/gitleaks/gitleaks/releases/download/v8.21.2/gitleaks_8.21.2_linux_x64.tar.gz" \ + | tar -xz -C /usr/local/bin gitleaks + - name: Scan working tree for secrets + run: gitleaks dir . --config .gitleaks.toml --redact --verbose trivy-bot: name: trivy (bot image) @@ -49,7 +54,7 @@ jobs: - name: Build bot image run: docker build --target production-bot -t fluxcore-bot:ci . - name: Trivy scan - uses: aquasecurity/trivy-action@0.28.0 + uses: aquasecurity/trivy-action@v0.28.0 with: image-ref: fluxcore-bot:ci severity: HIGH,CRITICAL @@ -73,7 +78,7 @@ jobs: - name: Build dashboard image run: docker build --target production-dashboard -t fluxcore-dashboard:ci . - name: Trivy scan - uses: aquasecurity/trivy-action@0.28.0 + uses: aquasecurity/trivy-action@v0.28.0 with: image-ref: fluxcore-dashboard:ci severity: HIGH,CRITICAL @@ -95,7 +100,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Trivy filesystem scan (config, IaC, secrets) - uses: aquasecurity/trivy-action@0.28.0 + uses: aquasecurity/trivy-action@v0.28.0 with: scan-type: fs scan-ref: . @@ -110,8 +115,9 @@ jobs: steps: - uses: actions/checkout@v4 - name: Block re-introduction of default lavalink password + # Exclude .github so this gate's own grep pattern doesn't self-match. run: | - if grep -RIn --exclude-dir=.git --exclude-dir=node_modules --exclude='*.md' 'youshallnotpass' .; then + if grep -RIn --exclude-dir=.git --exclude-dir=node_modules --exclude-dir=.github --exclude='*.md' 'youshallnotpass' .; then echo "::error::The literal 'youshallnotpass' must never be committed." exit 1 fi diff --git a/docker-compose.yml b/docker-compose.yml index ffc2ee8..b942671 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -28,8 +28,9 @@ services: - ./lavalink/application.yml:/opt/Lavalink/application.yml:ro environment: - _JAVA_OPTIONS=-Xmx128m + - LAVALINK_SERVER_PASSWORD=${LAVALINK_SERVER_PASSWORD:-} healthcheck: - test: ["CMD-SHELL", "wget -qO- --header='Authorization: youshallnotpass' http://localhost:2333/version || exit 1"] + test: ["CMD-SHELL", "wget -qO- --header=\"Authorization: $${LAVALINK_SERVER_PASSWORD}\" http://localhost:2333/version || exit 1"] interval: 10s timeout: 5s retries: 5 @@ -121,8 +122,9 @@ services: - ./lavalink/application.yml:/opt/Lavalink/application.yml:ro environment: - _JAVA_OPTIONS=-Xmx128m + - LAVALINK_SERVER_PASSWORD=${LAVALINK_SERVER_PASSWORD:-} healthcheck: - test: ["CMD-SHELL", "wget -qO- --header='Authorization: youshallnotpass' http://localhost:2333/version || exit 1"] + test: ["CMD-SHELL", "wget -qO- --header=\"Authorization: $${LAVALINK_SERVER_PASSWORD}\" http://localhost:2333/version || exit 1"] interval: 10s timeout: 5s retries: 5 diff --git a/lavalink/application.yml b/lavalink/application.yml index d3b705e..4a0cc5c 100644 --- a/lavalink/application.yml +++ b/lavalink/application.yml @@ -14,7 +14,9 @@ plugins: - TVHTML5_SIMPLY oauth: enabled: true - refreshToken: "1//03ZBRjPYrOJjyCgYIARAAGAMSNwF-L9IrxhQ0spy4xQa5oYz9QgV4MIAqjwHjE4-XvYKYckrwBkze-mryRjwwPVQmlOftQWVlGGA" + # Provided via env (Lavalink/Spring ${VAR} substitution). Never commit a real token. + # ROTATE the previously-committed token in Google Cloud — it is in git history. + refreshToken: "${LAVALINK_YOUTUBE_REFRESH_TOKEN:}" lavalink: plugins: diff --git a/package.json b/package.json index 2b2c4e3..14a097b 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,23 @@ "better-sqlite3", "esbuild", "prisma" - ] + ], + "overrides": { + "undici@<6.24.0": ">=6.24.0", + "i18next-fs-backend@<2.6.6": ">=2.6.6", + "hono@<4.12.4": ">=4.12.4", + "@hono/node-server@<1.19.10": ">=1.19.10", + "effect@<3.20.0": ">=3.20.0", + "fastify@<5.8.5": ">=5.8.5", + "fast-uri@<3.1.2": ">=3.1.2", + "ws@<8.21.0": ">=8.21.0", + "defu@<6.1.5": ">=6.1.5" + }, + "auditConfig": { + "ignoreGhsas": [ + "GHSA-r5fr-rjxr-66jc", + "GHSA-35jh-r3h4-6jhm" + ] + } } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4264a07..a9129d0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,6 +16,17 @@ catalogs: specifier: ^5.9.3 version: 5.9.3 +overrides: + undici@<6.24.0: '>=6.24.0' + i18next-fs-backend@<2.6.6: '>=2.6.6' + hono@<4.12.4: '>=4.12.4' + '@hono/node-server@<1.19.10': '>=1.19.10' + effect@<3.20.0: '>=3.20.0' + fastify@<5.8.5: '>=5.8.5' + fast-uri@<3.1.2: '>=3.1.2' + ws@<8.21.0: '>=8.21.0' + defu@<6.1.5: '>=6.1.5' + importers: .: @@ -166,8 +177,8 @@ importers: specifier: ^4.1.0 version: 4.1.0 fastify: - specifier: ^5.7.4 - version: 5.7.4 + specifier: '>=5.8.5' + version: 5.10.0 i18next: specifier: ^25.1.3 version: 25.10.10(typescript@5.9.3) @@ -304,8 +315,8 @@ importers: specifier: ^8.1.0 version: 8.2.1 i18next-fs-backend: - specifier: ^2.6.0 - version: 2.6.1 + specifier: '>=2.6.6' + version: 2.6.6 i18next-http-backend: specifier: ^3.0.2 version: 3.0.2 @@ -954,11 +965,11 @@ packages: '@floating-ui/utils@0.2.11': resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==} - '@hono/node-server@1.19.9': - resolution: {integrity: sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==} - engines: {node: '>=18.14.1'} + '@hono/node-server@2.0.8': + resolution: {integrity: sha512-GuCWzLxwg218fy1JaHculFsdcuY12hxit83V+algozTPnwhNjLrRL/Alg9OYjLZLoUZ1rw/S4CdTMsnkSKCmFA==} + engines: {node: '>=20'} peerDependencies: - hono: ^4 + hono: '>=4.12.4' '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -2342,8 +2353,8 @@ packages: resolution: {integrity: sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==} engines: {node: '>=16.0.0'} - defu@6.1.4: - resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + defu@6.1.7: + resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==} denque@2.1.0: resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} @@ -2385,8 +2396,8 @@ packages: resolution: {integrity: sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==} engines: {node: '>=12'} - effect@3.18.4: - resolution: {integrity: sha512-b1LXQJLe9D11wfnOKAk3PKxuqYshQ0Heez+y5pnkd3jLj1yx9QhM72zZ9uUrOQyNvrs2GZZd/3maL0ZV18YuDA==} + effect@3.21.4: + resolution: {integrity: sha512-B89v/xSgPbl1J2Ai2u18jxq3odpFauU1rC6/eSs4FeNHi72kwKdJp12VGigvRV2lK+kRnx+OOz41XV8guZd4gQ==} electron-to-chromium@1.5.302: resolution: {integrity: sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg==} @@ -2462,17 +2473,20 @@ packages: fast-json-stringify@6.3.0: resolution: {integrity: sha512-oRCntNDY/329HJPlmdNLIdogNtt6Vyjb1WuT01Soss3slIdyUp8kAcDU3saQTOquEK8KFVfwIIF7FebxUAu+yA==} + fast-json-stringify@7.0.0: + resolution: {integrity: sha512-YV53BAbR3Qwq37wfD1oZ97YJ0nYj6CwfzKXQ38ock9XxI2EnLOdl5psKms6Evook6ACckytZJOaKY0ThmIi1uw==} + fast-querystring@1.1.2: resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} - fast-uri@3.1.0: - resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + fast-uri@4.1.0: + resolution: {integrity: sha512-ZodJ2cRiLVWGi9IgPb3mbgSqM4CD3LexCHkuv0FfBXHJI1ADfucTD06m6clO2Cy5RZYsw/SiCVl/dyrFI/SYWA==} fastify-plugin@5.1.0: resolution: {integrity: sha512-FAIDA8eovSt5qcDgcBvDuX/v0Cjz0ohGhENZ/wpc3y+oZCY2afZ9Baqql3g/lC+OHRnciQol4ww7tuthOb9idw==} - fastify@5.7.4: - resolution: {integrity: sha512-e6l5NsRdaEP8rdD8VR0ErJASeyaRbzXYpmkrpr2SuvuMq6Si3lvsaVy5C+7gLanEkvjpMDzBXWE5HPeb/hgTxA==} + fastify@5.10.0: + resolution: {integrity: sha512-A9L0ziuWGQHgEEVgF3davQ9vbD93IuX+lo2IsxapQmu5b/Y/ynn9m9K5JHt9dvyJXOFc5iN0Zk5GHEOqnzhWjg==} fastq@1.20.1: resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} @@ -2489,8 +2503,8 @@ packages: file-uri-to-path@1.0.0: resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} - find-my-way@9.5.0: - resolution: {integrity: sha512-VW2RfnmscZO5KgBY5XVyKREMW5nMZcxDy+buTOsL+zIPnBlbKm+00sgzoQzq1EVh4aALZLfKdwv6atBGcjvjrQ==} + find-my-way@9.6.0: + resolution: {integrity: sha512-Zf4Xve4RymLl7NgaavNebZ01joJ8MfVerOG43wy7SHLO+r+K0C6d/SE0BiR7AV5V1VOCFlOP7ecdo+I4qmiHrQ==} engines: {node: '>=20'} foreground-child@3.3.1: @@ -2559,8 +2573,8 @@ packages: resolution: {integrity: sha512-jOiHyAZsmnr8LqoPGmCjYAaiuWwjAPLgY8ZX2XrmHawt99/u1y6RgrZMTeoPfpUbV96HOalYgz1qzkRbw54Pmg==} engines: {node: '>=18.0.0'} - hono@4.11.4: - resolution: {integrity: sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA==} + hono@4.12.28: + resolution: {integrity: sha512-YwUvVpSF7m1yOblFPrU3Hbo8XhPheBoiyfGuII6z19LnOr6JpDnyyp7LFNrfV56wS8tpvtBFGRISHN02pDdLOA==} engines: {node: '>=16.9.0'} html-encoding-sniffer@6.0.0: @@ -2583,8 +2597,8 @@ packages: i18next-browser-languagedetector@8.2.1: resolution: {integrity: sha512-bZg8+4bdmaOiApD7N7BPT9W8MLZG+nPTOFlLiJiT8uzKXFjhxw4v2ierCXOwB5sFDMtuA5G4kgYZ0AznZxQ/cw==} - i18next-fs-backend@2.6.1: - resolution: {integrity: sha512-eYWTX7QT7kJ0sZyCPK6x1q+R63zvNKv2D6UdbMf15A8vNb2ZLyw4NNNZxPFwXlIv/U+oUtg8SakW6ZgJZcoqHQ==} + i18next-fs-backend@2.6.6: + resolution: {integrity: sha512-mYGu6Nt8RIp3X/U8Y+Gej1wo5xmYWmGKLqBGMCC2OCAou5rW5epeHgHmVcw20mJs9Z9+DAPHIxQPNCgFyPRMeg==} i18next-http-backend@3.0.2: resolution: {integrity: sha512-PdlvPnvIp4E1sYi46Ik4tBYh/v/NbYfFFgTjkwFl0is8A18s7/bx9aXqsrOax9WUbeNS6mD2oix7Z0yGGf6m5g==} @@ -3489,10 +3503,6 @@ packages: undici-types@7.18.2: resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} - undici@6.21.3: - resolution: {integrity: sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==} - engines: {node: '>=18.17'} - undici@7.28.0: resolution: {integrity: sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==} engines: {node: '>=20.18.1'} @@ -3699,8 +3709,8 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - ws@8.19.0: - resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==} + ws@8.21.0: + resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -3967,7 +3977,7 @@ snapshots: discord-api-types: 0.38.40 magic-bytes.js: 1.13.0 tslib: 2.8.1 - undici: 6.21.3 + undici: 7.28.0 '@discordjs/util@1.2.0': dependencies: @@ -3983,7 +3993,7 @@ snapshots: '@vladfrangu/async_event_emitter': 2.4.7 discord-api-types: 0.38.40 tslib: 2.8.1 - ws: 8.19.0 + ws: 8.21.0 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -4162,7 +4172,7 @@ snapshots: dependencies: ajv: 8.18.0 ajv-formats: 3.0.1(ajv@8.18.0) - fast-uri: 3.1.0 + fast-uri: 4.1.0 '@fastify/cookie@11.0.2': dependencies: @@ -4231,9 +4241,9 @@ snapshots: '@floating-ui/utils@0.2.11': {} - '@hono/node-server@1.19.9(hono@4.11.4)': + '@hono/node-server@2.0.8(hono@4.12.28)': dependencies: - hono: 4.11.4 + hono: 4.12.28 '@jridgewell/gen-mapping@0.3.13': dependencies: @@ -4335,7 +4345,7 @@ snapshots: dependencies: c12: 3.1.0 deepmerge-ts: 7.1.5 - effect: 3.18.4 + effect: 3.21.4 empathic: 2.0.0 transitivePeerDependencies: - magicast @@ -4349,13 +4359,13 @@ snapshots: '@electric-sql/pglite': 0.3.15 '@electric-sql/pglite-socket': 0.0.20(@electric-sql/pglite@0.3.15) '@electric-sql/pglite-tools': 0.2.20(@electric-sql/pglite@0.3.15) - '@hono/node-server': 1.19.9(hono@4.11.4) + '@hono/node-server': 2.0.8(hono@4.12.28) '@mrleebo/prisma-ast': 0.13.1 '@prisma/get-platform': 7.2.0 '@prisma/query-plan-executor': 7.2.0 foreground-child: 3.3.1 get-port-please: 3.2.0 - hono: 4.11.4 + hono: 4.12.28 http-status-codes: 2.3.0 pathe: 2.0.3 proper-lockfile: 4.1.2 @@ -5331,7 +5341,7 @@ snapshots: ajv@8.18.0: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.1.0 + fast-uri: 4.1.0 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 @@ -5419,7 +5429,7 @@ snapshots: dependencies: chokidar: 4.0.3 confbox: 0.2.4 - defu: 6.1.4 + defu: 6.1.7 dotenv: 16.6.1 exsolve: 1.0.8 giget: 2.0.0 @@ -5612,7 +5622,7 @@ snapshots: deepmerge-ts@7.1.5: {} - defu@6.1.4: {} + defu@6.1.7: {} denque@2.1.0: {} @@ -5642,7 +5652,7 @@ snapshots: lodash.snakecase: 4.1.1 magic-bytes.js: 1.13.0 tslib: 2.8.1 - undici: 6.21.3 + undici: 7.28.0 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -5653,7 +5663,7 @@ snapshots: dotenv@17.3.1: {} - effect@3.18.4: + effect@3.21.4: dependencies: '@standard-schema/spec': 1.1.0 fast-check: 3.23.2 @@ -5768,7 +5778,16 @@ snapshots: '@fastify/merge-json-schemas': 0.2.1 ajv: 8.18.0 ajv-formats: 3.0.1(ajv@8.18.0) - fast-uri: 3.1.0 + fast-uri: 4.1.0 + json-schema-ref-resolver: 3.0.0 + rfdc: 1.4.1 + + fast-json-stringify@7.0.0: + dependencies: + '@fastify/merge-json-schemas': 0.2.1 + ajv: 8.18.0 + ajv-formats: 3.0.1(ajv@8.18.0) + fast-uri: 4.1.0 json-schema-ref-resolver: 3.0.0 rfdc: 1.4.1 @@ -5776,11 +5795,11 @@ snapshots: dependencies: fast-decode-uri-component: 1.0.1 - fast-uri@3.1.0: {} + fast-uri@4.1.0: {} fastify-plugin@5.1.0: {} - fastify@5.7.4: + fastify@5.10.0: dependencies: '@fastify/ajv-compiler': 4.0.5 '@fastify/error': 4.2.0 @@ -5788,8 +5807,8 @@ snapshots: '@fastify/proxy-addr': 5.1.0 abstract-logging: 2.0.1 avvio: 9.2.0 - fast-json-stringify: 6.3.0 - find-my-way: 9.5.0 + fast-json-stringify: 7.0.0 + find-my-way: 9.6.0 light-my-request: 6.6.0 pino: 10.3.1 process-warning: 5.0.0 @@ -5809,7 +5828,7 @@ snapshots: file-uri-to-path@1.0.0: optional: true - find-my-way@9.5.0: + find-my-way@9.6.0: dependencies: fast-deep-equal: 3.1.3 fast-querystring: 1.1.2 @@ -5849,7 +5868,7 @@ snapshots: dependencies: citty: 0.1.6 consola: 3.4.2 - defu: 6.1.4 + defu: 6.1.7 node-fetch-native: 1.6.7 nypm: 0.6.5 pathe: 2.0.3 @@ -5873,7 +5892,7 @@ snapshots: helmet@8.1.0: {} - hono@4.11.4: {} + hono@4.12.28: {} html-encoding-sniffer@6.0.0: dependencies: @@ -5901,7 +5920,7 @@ snapshots: dependencies: '@babel/runtime': 7.29.2 - i18next-fs-backend@2.6.1: {} + i18next-fs-backend@2.6.6: {} i18next-http-backend@3.0.2: dependencies: @@ -6340,7 +6359,7 @@ snapshots: rc9@2.1.2: dependencies: - defu: 6.1.4 + defu: 6.1.7 destr: 2.0.5 rc@1.2.8: @@ -6557,7 +6576,7 @@ snapshots: shoukaku@4.3.0: dependencies: - ws: 8.19.0 + ws: 8.21.0 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -6740,8 +6759,6 @@ snapshots: undici-types@7.18.2: {} - undici@6.21.3: {} - undici@7.28.0: {} update-browserslist-db@1.2.3(browserslist@4.28.1): @@ -6904,7 +6921,7 @@ snapshots: wrappy@1.0.2: optional: true - ws@8.19.0: {} + ws@8.21.0: {} xml-name-validator@5.0.0: {} From da094063326669e0bd2ac4f9c4e79191a83d11dc Mon Sep 17 00:00:00 2001 From: Abdulkhalek Muhammad Date: Wed, 8 Jul 2026 15:12:29 +0300 Subject: [PATCH 2/3] fix(security-ci): run Trivy via CLI instead of the unresolvable action trivy-action@v0.28.0 pins setup-trivy@v0.2.1 which no longer resolves, failing all three trivy jobs at setup. Install the Trivy CLI and scan directly. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/security.yml | 55 +++++++++------------------------- 1 file changed, 14 insertions(+), 41 deletions(-) diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 870003e..81fb69f 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -46,6 +46,8 @@ jobs: - name: Scan working tree for secrets run: gitleaks dir . --config .gitleaks.toml --redact --verbose + # Use the Trivy CLI directly (install script) rather than aquasecurity/trivy-action, + # whose pinned setup-trivy composite action versions have proven unresolvable. trivy-bot: name: trivy (bot image) runs-on: ubuntu-latest @@ -53,22 +55,10 @@ jobs: - uses: actions/checkout@v4 - name: Build bot image run: docker build --target production-bot -t fluxcore-bot:ci . - - name: Trivy scan - uses: aquasecurity/trivy-action@v0.28.0 - with: - image-ref: fluxcore-bot:ci - severity: HIGH,CRITICAL - exit-code: "1" - ignore-unfixed: true - vuln-type: os,library - format: sarif - output: trivy-bot.sarif - - name: Upload SARIF - if: always() - uses: github/codeql-action/upload-sarif@v3 - with: - sarif_file: trivy-bot.sarif - category: trivy-bot + - name: Install Trivy + run: curl -sSfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin + - name: Scan bot image + run: trivy image --severity HIGH,CRITICAL --exit-code 1 --ignore-unfixed --no-progress fluxcore-bot:ci trivy-dashboard: name: trivy (dashboard image) @@ -77,37 +67,20 @@ jobs: - uses: actions/checkout@v4 - name: Build dashboard image run: docker build --target production-dashboard -t fluxcore-dashboard:ci . - - name: Trivy scan - uses: aquasecurity/trivy-action@v0.28.0 - with: - image-ref: fluxcore-dashboard:ci - severity: HIGH,CRITICAL - exit-code: "1" - ignore-unfixed: true - vuln-type: os,library - format: sarif - output: trivy-dashboard.sarif - - name: Upload SARIF - if: always() - uses: github/codeql-action/upload-sarif@v3 - with: - sarif_file: trivy-dashboard.sarif - category: trivy-dashboard + - name: Install Trivy + run: curl -sSfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin + - name: Scan dashboard image + run: trivy image --severity HIGH,CRITICAL --exit-code 1 --ignore-unfixed --no-progress fluxcore-dashboard:ci trivy-fs: name: trivy (filesystem & config) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Trivy filesystem scan (config, IaC, secrets) - uses: aquasecurity/trivy-action@v0.28.0 - with: - scan-type: fs - scan-ref: . - severity: HIGH,CRITICAL - exit-code: "1" - ignore-unfixed: true - scanners: vuln,secret,config + - name: Install Trivy + run: curl -sSfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin + - name: Trivy filesystem scan (vuln, secret, config) + run: trivy fs --scanners vuln,secret,config --severity HIGH,CRITICAL --exit-code 1 --ignore-unfixed --no-progress . forbidden-strings: name: forbidden strings From 1facc8ec21fc282b5dff920e32a7b4cf093db596 Mon Sep 17 00:00:00 2001 From: Abdulkhalek Muhammad Date: Wed, 8 Jul 2026 15:41:15 +0300 Subject: [PATCH 3/3] fix(security-ci): green Trivy image + fs scans MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Dockerfile: copy root tsconfig.base.json/tsconfig.json into the bot/dashboard builder stages — turbo prune omits them, so the production build failed (TS5083 + dotenv default-export). Production images now build. - Trivy image scans: skip base-image package-manager tooling (npm global + corepack pnpm cache) — not the running service's surface; app deps under /app/node_modules and the OS layer are still scanned. - .trivyignore: suppress unfixable lodash CVE-2026-4800 (phantom 4.18.0 fix), mirroring pnpm auditConfig.ignoreGhsas. Verified locally: production-bot + production-dashboard build; trivy image (both) and trivy fs all exit 0. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/security.yml | 10 ++++++++-- .trivyignore | 9 +++++++++ Dockerfile | 4 ++++ 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 .trivyignore diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 81fb69f..59c7d3f 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -58,7 +58,10 @@ jobs: - name: Install Trivy run: curl -sSfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin - name: Scan bot image - run: trivy image --severity HIGH,CRITICAL --exit-code 1 --ignore-unfixed --no-progress fluxcore-bot:ci + # Skip the base image's package-manager tooling (npm global + corepack pnpm + # cache) — not our runtime surface. App deps under /app/node_modules and the + # OS layer are still scanned. + run: trivy image --severity HIGH,CRITICAL --exit-code 1 --ignore-unfixed --no-progress --skip-dirs /usr/local/lib/node_modules --skip-dirs /root/.cache/node/corepack fluxcore-bot:ci trivy-dashboard: name: trivy (dashboard image) @@ -70,7 +73,10 @@ jobs: - name: Install Trivy run: curl -sSfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin - name: Scan dashboard image - run: trivy image --severity HIGH,CRITICAL --exit-code 1 --ignore-unfixed --no-progress fluxcore-dashboard:ci + # Skip the base image's package-manager tooling (npm global + corepack pnpm + # cache) — not our runtime surface. App deps under /app/node_modules and the + # OS layer are still scanned. + run: trivy image --severity HIGH,CRITICAL --exit-code 1 --ignore-unfixed --no-progress --skip-dirs /usr/local/lib/node_modules --skip-dirs /root/.cache/node/corepack fluxcore-dashboard:ci trivy-fs: name: trivy (filesystem & config) diff --git a/.trivyignore b/.trivyignore new file mode 100644 index 0000000..a1379a4 --- /dev/null +++ b/.trivyignore @@ -0,0 +1,9 @@ +# Trivy vulnerability ignore list. +# Each entry must be justified; prefer fixing (pnpm.overrides) over ignoring. + +# lodash: Arbitrary code execution via _.template (untrusted templateSettings). +# Transitive-only (via @sapphire/shapeshift and @mrleebo/prisma-ast>chevrotain); +# we never call lodash template with untrusted input. The advisory lists a fix +# in 4.18.0, which lodash has NOT released (latest is 4.17.21) — unfixable. +# Mirrors pnpm auditConfig.ignoreGhsas (GHSA-r5fr-rjxr-66jc, GHSA-35jh-r3h4-6jhm). +CVE-2026-4800 diff --git a/Dockerfile b/Dockerfile index f1b9a06..e2275e1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -52,6 +52,8 @@ RUN pnpm install --frozen-lockfile FROM bot-installer AS bot-builder COPY --from=prune-bot /app/out/full/ . +# turbo prune omits root tsconfig files that package tsconfigs extend. +COPY tsconfig.base.json tsconfig.json ./ RUN pnpm turbo run build --filter=@fluxcore/bot... FROM base AS production-bot @@ -81,6 +83,8 @@ RUN pnpm install --frozen-lockfile FROM dashboard-installer AS dashboard-builder COPY --from=prune-dashboard /app/out/full/ . +# turbo prune omits root tsconfig files that package tsconfigs extend. +COPY tsconfig.base.json tsconfig.json ./ RUN pnpm turbo run build --filter=@fluxcore/dashboard... FROM base AS production-dashboard