Summary
The version parameter passed to HttpSourceDownloader.downloadAndExtract() is interpolated directly into a GitHub URL with no validation:
// src/infrastructure/source/http_source_downloader.ts:42-43
const tag = version.startsWith("v") ? version : `v${version}`;
return `${HttpSourceDownloader.GITHUB_BASE}/tags/${tag}.tar.gz`;
There is no check that version contains only safe URL characters. Characters such as #, ?, /, .., or URL-encoded sequences (e.g. %2F) could cause the constructed URL to resolve unexpectedly within the GitHub URL space.
Risk
The base URL is hardcoded to https://github.com/systeminit/swamp/archive/refs, so no SSRF to arbitrary hosts is possible. However, a crafted version string could:
- Escape the
/tags/ path segment (e.g. version = "1.0/../../heads/main")
- Hit unintended GitHub archive endpoints
Recommended Fix
Add a validation guard at the top of downloadAndExtract() (or inside getArchiveUrl()) that rejects any version string not matching a safe pattern:
if (!/^[a-zA-Z0-9._-]+$/.test(version)) {
throw new UserError(
`Invalid version string "${version}": must contain only alphanumeric characters, dots, hyphens, and underscores.`,
);
}
Add a test that calling downloadAndExtract with "../malicious" throws a UserError before any network request is made.
References
src/infrastructure/source/http_source_downloader.ts — getArchiveUrl()