mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-05-19 16:28:28 +00:00
fix(installer): tighten verifier base-url + clarify test helper
Three small refinements from the second review pass: - normalizeHttpsBaseUrl rejects everything except https, since real release URLs are always HTTPS. Accepting http previously would let an operator silently target a stale or attacker-controlled mirror. - Drop EXPECTED_RELEASE_ASSET_NAMES from the public exports; it was only used internally for the verification log line. - Rename the test helper standaloneChecksumContent to placeholderChecksumContent and document that the hashes in its output are placeholders — the remote verifier does not download archives or compare hashes, it only validates that SHA256SUMS lists the expected names and that each archive URL is reachable. The non-https rejection test now also covers `http://` in addition to the existing `file://` case.
This commit is contained in:
parent
4100b8e239
commit
362bf588f8
2 changed files with 25 additions and 11 deletions
|
|
@ -789,7 +789,7 @@ describe('standalone release packaging', () => {
|
|||
it('verifies release asset URLs from SHA256SUMS', async () => {
|
||||
const { EXPECTED_STANDALONE_ARCHIVE_NAMES, verifyReleaseBaseUrl } =
|
||||
await import(installationReleaseVerificationScriptUrl);
|
||||
const checksumContent = standaloneChecksumContent(
|
||||
const checksumContent = placeholderChecksumContent(
|
||||
EXPECTED_STANDALONE_ARCHIVE_NAMES,
|
||||
);
|
||||
const fetchedUrls = [];
|
||||
|
|
@ -827,7 +827,7 @@ describe('standalone release packaging', () => {
|
|||
it('falls back to ranged GET when remote HEAD is unavailable', async () => {
|
||||
const { EXPECTED_STANDALONE_ARCHIVE_NAMES, verifyReleaseBaseUrl } =
|
||||
await import(installationReleaseVerificationScriptUrl);
|
||||
const checksumContent = standaloneChecksumContent(
|
||||
const checksumContent = placeholderChecksumContent(
|
||||
EXPECTED_STANDALONE_ARCHIVE_NAMES,
|
||||
);
|
||||
const observedMethods = [];
|
||||
|
|
@ -856,7 +856,7 @@ describe('standalone release packaging', () => {
|
|||
it('rejects a release base URL with no archives reachable', async () => {
|
||||
const { EXPECTED_STANDALONE_ARCHIVE_NAMES, verifyReleaseBaseUrl } =
|
||||
await import(installationReleaseVerificationScriptUrl);
|
||||
const checksumContent = standaloneChecksumContent(
|
||||
const checksumContent = placeholderChecksumContent(
|
||||
EXPECTED_STANDALONE_ARCHIVE_NAMES,
|
||||
);
|
||||
|
||||
|
|
@ -872,14 +872,22 @@ describe('standalone release packaging', () => {
|
|||
).rejects.toThrow(/Release asset URL is not available/);
|
||||
});
|
||||
|
||||
it('rejects a release base URL that is not http(s)', async () => {
|
||||
it('rejects a release base URL that is not https', async () => {
|
||||
const { verifyReleaseBaseUrl } = await import(
|
||||
installationReleaseVerificationScriptUrl
|
||||
);
|
||||
|
||||
// file:// must be rejected as a URL the verifier cannot reach safely.
|
||||
await expect(verifyReleaseBaseUrl('file:///tmp/release/')).rejects.toThrow(
|
||||
/--base-url must use http or https/,
|
||||
/--base-url must use https/,
|
||||
);
|
||||
|
||||
// Plain http must also be rejected even though it is technically a valid
|
||||
// URL — release URLs are always HTTPS, and accepting http would let an
|
||||
// operator silently target a stale or attacker-controlled mirror.
|
||||
await expect(
|
||||
verifyReleaseBaseUrl('http://example.com/release/'),
|
||||
).rejects.toThrow(/--base-url must use https/);
|
||||
});
|
||||
|
||||
it('rejects a runtime archive without a Node executable', () => {
|
||||
|
|
@ -2091,7 +2099,11 @@ function writeStandaloneReleaseChecksums(outDir, archiveNames) {
|
|||
writeFileSync(path.join(outDir, 'SHA256SUMS'), `${lines.join('\n')}\n`);
|
||||
}
|
||||
|
||||
function standaloneChecksumContent(archiveNames) {
|
||||
// Generates a SHA256SUMS-formatted string for the given archive names. The
|
||||
// hash values are placeholders — the remote verifier (verifyReleaseBaseUrl)
|
||||
// only checks that SHA256SUMS lists the expected entries and that each
|
||||
// archive URL is reachable; it does not download archives or compare hashes.
|
||||
function placeholderChecksumContent(archiveNames) {
|
||||
return `${archiveNames
|
||||
.map(
|
||||
(assetName) =>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue