-
Notifications
You must be signed in to change notification settings - Fork 0
P1: Proxy checksum verification robustness (deterministic source) #38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,7 +4,6 @@ import crypto from 'crypto'; | |||||||||||||||||||||||||||||||
| import path from 'path'; | ||||||||||||||||||||||||||||||||
| import { PATHS } from '../system/paths.js'; | ||||||||||||||||||||||||||||||||
| import { logger } from './logger.js'; | ||||||||||||||||||||||||||||||||
| import { escapeRegExp } from './utils.js'; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| const GITHUB_REPO = 'GoogleCloudPlatform/cloud-sql-proxy'; | ||||||||||||||||||||||||||||||||
| const ASSET_NAME = 'cloud-sql-proxy.x64.exe'; | ||||||||||||||||||||||||||||||||
|
|
@@ -39,23 +38,20 @@ export async function downloadProxy(version: string, targetPath: string = PATHS. | |||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||
| const releaseUrl = `https://api.github.com/repos/${GITHUB_REPO}/releases/tags/${version}`; | ||||||||||||||||||||||||||||||||
| const response = await axios.get(releaseUrl); | ||||||||||||||||||||||||||||||||
| await axios.get(releaseUrl); | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| // Google Cloud SQL Proxy v2 binaries are hosted on GCS | ||||||||||||||||||||||||||||||||
| downloadUrl = `https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/${version}/${ASSET_NAME}`; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| // Extract checksum from release body | ||||||||||||||||||||||||||||||||
| const { body } = response.data; | ||||||||||||||||||||||||||||||||
| // Regex to match: | [cloud-sql-proxy.x64.exe](...) | <hash> | | ||||||||||||||||||||||||||||||||
| const escapedAssetName = escapeRegExp(ASSET_NAME); | ||||||||||||||||||||||||||||||||
| const checksumRegex = new RegExp(`\\| \\[${escapedAssetName}\\]\\(.*?\\) \\| ([a-f0-9]{64}) \\|`); | ||||||||||||||||||||||||||||||||
| const match = body.match(checksumRegex); | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| if (match && match[1]) { | ||||||||||||||||||||||||||||||||
| expectedChecksum = match[1]; | ||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||
| logger.warn(`Could not extract checksum for ${ASSET_NAME} from release notes.`); | ||||||||||||||||||||||||||||||||
| // Fetch checksum from deterministic GCS sidecar file | ||||||||||||||||||||||||||||||||
| const checksumUrl = `${downloadUrl}.sha256`; | ||||||||||||||||||||||||||||||||
| const checksumResponse = await axios.get(checksumUrl, { responseType: 'text' }); | ||||||||||||||||||||||||||||||||
| const checksumText = String(checksumResponse.data).trim(); | ||||||||||||||||||||||||||||||||
| const checksumMatch = checksumText.match(/[a-f0-9]{64}/i); | ||||||||||||||||||||||||||||||||
| if (!checksumMatch) { | ||||||||||||||||||||||||||||||||
| throw new Error(`Checksum file did not contain a valid SHA256 hash (${checksumUrl})`); | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| expectedChecksum = checksumMatch[0]; | ||||||||||||||||||||||||||||||||
|
Comment on lines
+49
to
+54
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion (bug_risk): Tighten checksum regex to reduce risk of picking up an unintended hash when the file has additional content.
Suggested change
|
||||||||||||||||||||||||||||||||
| expectedChecksum = checksumMatch[0]; | |
| expectedChecksum = checksumMatch[0].toLowerCase(); |
Copilot
AI
Dec 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new checksum fetching logic from the GCS sidecar file lacks test coverage. The codebase has tests for similar functions (e.g., selfUpdate.test.ts tests checkForUpdates and fetchSha256Sums). Consider adding tests to verify the behavior when the checksum file is missing, contains invalid format, or has uppercase/mixed-case hashes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (performance): Re-evaluate the need for the GitHub release fetch now that the checksum is sourced from GCS only.
This call no longer uses the response and now just adds an extra network round trip per download. If it’s only meant to validate that the GitHub tag exists, consider making that explicit (e.g., distinct handling/logging for "unknown version" vs generic network errors). If that validation isn’t needed anymore, removing the call would simplify the flow and reduce latency.
Suggested implementation:
axiosimport at the top ofsrc/core/updater.ts(e.g.,import axios from 'axios';) if present.