[GH-ISSUE #741] Security audit: CI shell injection, potential API key exposure, and XSS patterns #162

Closed
opened 2026-05-06 12:37:45 +02:00 by BreizhHardware · 0 comments

Originally created by @LukePercy on GitHub (Apr 1, 2026).
Original GitHub issue: https://github.com/cloudflare/vinext/issues/741

Summary

A static security scan via repowatch.io identified 18 findings across the repository. The most actionable items are grouped below by priority.

Overall score: 59/100 — strong code quality (95) and test confidence (90), but security hygiene was pulled to 0 by the findings below.

Full scan report: docs/repowatch-scan-2026-04-01.md


🔴 Critical: potential API key in test file

Location: tests/vite-hmr-websocket.test.ts:32

Gitleaks flagged a value matching the generic-api-key pattern. If this is a live credential, it should be rotated immediately and moved to environment-based secrets. If it's a test fixture/dummy value, no action is needed.


🟠 High: GitHub Actions shell injection (4 locations)

All four use ${{ github.event.* }} context data directly inside run: steps. An attacker can craft a PR title or branch name to inject arbitrary shell commands, exfiltrating secrets or writing to the repo.

Locations:

  • .github/workflows/publish.yml:47
  • .github/workflows/nextjs-tracker.yml:42
  • .github/workflows/nextjs-tracker.yml:73
  • .github/workflows/nextjs-tracker.yml:137

Fix pattern: Use an intermediate environment variable instead of inline interpolation:

# Before (vulnerable)
run: echo "${{ github.event.pull_request.title }}"

# After (safe)
env:
  PR_TITLE: ${{ github.event.pull_request.title }}
run: echo "$PR_TITLE"

🟠 High: innerHTML in script shim

Location: packages/vinext/src/shims/script.tsx:159

innerHTML is used with potentially dynamic content. If the input is always developer-controlled (script config), this is acceptable by design. If user-supplied data can reach this path, it's an XSS vector.


🟡 Medium: non-literal RegExp (6 locations)

new RegExp(variable) patterns — potential ReDoS if the variable is user-controlled. In this codebase these appear to be internal config values (pageExtensions, fileNames, etc.), so likely low risk. Worth confirming no user input flows to these.

Locations:

  • packages/vinext/src/shims/head.ts:276
  • packages/vinext/src/shims/image-config.ts:58
  • packages/vinext/src/config/config-matchers.ts:341
  • packages/vinext/src/config/config-matchers.ts:974
  • packages/vinext/src/routing/file-matcher.ts:51
  • packages/vinext/src/routing/file-matcher.ts:54

🟡 Medium: dangerouslySetInnerHTML in example

Location: examples/hackernews/components/comment.jsx:29

Renders API-sourced HTML without sanitization. Consider using DOMPurify if the HN API response is not fully trusted.


🔵 Low: unsafe format strings (2 locations)

Server-side debug logs using string concatenation in console.log. Minimal risk.

  • packages/vinext/src/server/isr-cache.ts:93
  • packages/vinext/src/shims/fetch-cache.ts:679

Report generated by Repo Watch — static risk audit for repositories. Findings are directional signals, not proof of exploitability.

Originally created by @LukePercy on GitHub (Apr 1, 2026). Original GitHub issue: https://github.com/cloudflare/vinext/issues/741 ## Summary A static security scan via [repowatch.io](https://repowatch.io) identified 18 findings across the repository. The most actionable items are grouped below by priority. **Overall score: 59/100** — strong code quality (95) and test confidence (90), but security hygiene was pulled to 0 by the findings below. Full scan report: [docs/repowatch-scan-2026-04-01.md](https://github.com/LukePercy/vinext/blob/main/docs/repowatch-scan-2026-04-01.md) --- ## 🔴 Critical: potential API key in test file **Location:** `tests/vite-hmr-websocket.test.ts:32` Gitleaks flagged a value matching the `generic-api-key` pattern. If this is a live credential, it should be rotated immediately and moved to environment-based secrets. If it's a test fixture/dummy value, no action is needed. --- ## 🟠 High: GitHub Actions shell injection (4 locations) All four use `${{ github.event.* }}` context data directly inside `run:` steps. An attacker can craft a PR title or branch name to inject arbitrary shell commands, exfiltrating secrets or writing to the repo. **Locations:** - `.github/workflows/publish.yml:47` - `.github/workflows/nextjs-tracker.yml:42` - `.github/workflows/nextjs-tracker.yml:73` - `.github/workflows/nextjs-tracker.yml:137` **Fix pattern:** Use an intermediate environment variable instead of inline interpolation: ```yaml # Before (vulnerable) run: echo "${{ github.event.pull_request.title }}" # After (safe) env: PR_TITLE: ${{ github.event.pull_request.title }} run: echo "$PR_TITLE" ``` --- ## 🟠 High: innerHTML in script shim **Location:** `packages/vinext/src/shims/script.tsx:159` `innerHTML` is used with potentially dynamic content. If the input is always developer-controlled (script config), this is acceptable by design. If user-supplied data can reach this path, it's an XSS vector. --- ## 🟡 Medium: non-literal RegExp (6 locations) `new RegExp(variable)` patterns — potential ReDoS if the variable is user-controlled. In this codebase these appear to be internal config values (`pageExtensions`, `fileNames`, etc.), so likely low risk. Worth confirming no user input flows to these. **Locations:** - `packages/vinext/src/shims/head.ts:276` - `packages/vinext/src/shims/image-config.ts:58` - `packages/vinext/src/config/config-matchers.ts:341` - `packages/vinext/src/config/config-matchers.ts:974` - `packages/vinext/src/routing/file-matcher.ts:51` - `packages/vinext/src/routing/file-matcher.ts:54` --- ## 🟡 Medium: dangerouslySetInnerHTML in example **Location:** `examples/hackernews/components/comment.jsx:29` Renders API-sourced HTML without sanitization. Consider using DOMPurify if the HN API response is not fully trusted. --- ## 🔵 Low: unsafe format strings (2 locations) Server-side debug logs using string concatenation in `console.log`. Minimal risk. - `packages/vinext/src/server/isr-cache.ts:93` - `packages/vinext/src/shims/fetch-cache.ts:679` --- *Report generated by [Repo Watch](https://repowatch.io) — static risk audit for repositories. Findings are directional signals, not proof of exploitability.*
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/vinext#162
No description provided.