fix: validate RAW_BASE URL in update-check to prevent future injection (#1533)

Agent: security-auditor

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
A 2026-02-20 09:52:02 -08:00 committed by GitHub
parent 2bb1b82bc3
commit c69c12c8db
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 7 additions and 1 deletions

View file

@ -56,7 +56,7 @@ export interface Manifest {
// ── Constants ──────────────────────────────────────────────────────────────────
const REPO = "OpenRouterTeam/spawn";
const RAW_BASE = `https://raw.githubusercontent.com/${REPO}/main`;
const RAW_BASE = `https://raw.githubusercontent.com/${REPO}/main` as const;
// Dynamic getters so tests can override XDG_CACHE_HOME at runtime
function getCacheDir(): string {
return join(process.env.XDG_CACHE_HOME || join(homedir(), ".cache"), "spawn");

View file

@ -16,6 +16,12 @@ export const executor = {
const FETCH_TIMEOUT = 5000; // 5 seconds
// Validate RAW_BASE matches expected GitHub raw content URL pattern (defense-in-depth, CWE-78)
const GITHUB_RAW_URL_PATTERN = /^https:\/\/raw\.githubusercontent\.com\/[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
if (!GITHUB_RAW_URL_PATTERN.test(RAW_BASE)) {
throw new Error(`RAW_BASE URL does not match expected GitHub raw URL pattern: ${RAW_BASE}`);
}
// Use ASCII-safe symbols when unicode is disabled (SSH, dumb terminals)
const isAscii = process.env.TERM === "linux";
const CHECK_MARK = isAscii ? "*" : "\u2713";