preview-netlify and preview-cloudflare share ~150 lines of near-identical logic (trust gate, change detection, PR comment), so bugs must be fixed twice. Consolidate, then harden once.
Related: #14 (cloudflare PR-comment URL).
Filed from the 2026-06-16 technical review.
preview-netlifyandpreview-cloudflareshare ~150 lines of near-identical logic (trust gate, change detection, PR comment), so bugs must be fixed twice. Consolidate, then harden once.scripts/(or a small composite sub-action) reused by both. Reduces drift.lectures-diris interpolated raw into a bash regex: preview-netlify/action.yml:74, preview-cloudflare/action.yml:77. Today every repo useslecturesso it's latent; a value with./+/spaces misbehaves. Useprintf '%q'or a whitelist.github-scriptJS body:const changedFiles = `${{ steps.detect-changes.outputs.changed-files }}`;(preview-netlify:159, preview-cloudflare:173). A filename containing a backtick or${...}can break out of the template literal and run arbitrary JS holdinggithub.token. Mitigated by thecheck-trustgate (forks/dependabot are skipped, so exploitation needs repo push access), but it's the canonical anti-pattern. Fix: pass values viaenv:and readprocess.env.Related: #14 (cloudflare PR-comment URL).
Filed from the 2026-06-16 technical review.