Skip to content

Commit 6394f27

Browse files
committed
feat: add checksum verification
1 parent d1e8ca3 commit 6394f27

2 files changed

Lines changed: 65 additions & 3 deletions

File tree

packages/browser/src/download.ts

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,17 @@
1616
import { constants, chmodSync, createWriteStream, existsSync, mkdirSync } from 'node:fs'
1717
import https from 'node:https'
1818
import { arch, exit, platform } from 'node:process'
19-
import { DEFAULT_CACHE_FOLDER, DEFAULT_EXECUTABLE_PATH, USER_EXECUTABLE_PATH } from './utils'
19+
import {
20+
DEFAULT_CACHE_FOLDER,
21+
DEFAULT_EXECUTABLE_PATH,
22+
USER_EXECUTABLE_PATH,
23+
checksumFile,
24+
} from './utils'
25+
26+
type GH_ASSET = {
27+
name: string
28+
digest: string
29+
}
2030

2131
const PLATFORMS = {
2232
darwin: {
@@ -66,18 +76,47 @@ export const download = async (): Promise<void> => {
6676
return new Promise((resolve, reject) => get(url, resolve, reject))
6777
}
6878

79+
const getGithubHash = async (path: string) => {
80+
try {
81+
const f = await fetch(path)
82+
const data = await f.json()
83+
84+
const asset: GH_ASSET = data.assets.find(
85+
(a: GH_ASSET) => a.name === `lightpanda-${platformPath}`,
86+
)
87+
88+
if (asset) {
89+
return asset.digest
90+
}
91+
92+
return ''
93+
} catch (e) {
94+
throw new Error(e)
95+
}
96+
}
97+
6998
if (platformPath) {
7099
if (USER_EXECUTABLE_PATH) {
71100
console.info('$LIGHTPANDA_EXECUTABLE_PATH found, skipping binary download…')
72101
exit(0)
73102
}
74103

75104
try {
76-
console.info('⏳ Downloading latest version of Lightpanda browser…')
77-
105+
console.info('⏳ Downloading latest version of Lightpanda browser…', '\n')
78106
await downloadBinary(
79107
`https://github.com/lightpanda-io/browser/releases/download/nightly/lightpanda-${platformPath}`,
80108
)
109+
110+
console.info('🔐 Getting and comparing checksums…', '\n')
111+
const ghChecksum = await getGithubHash(
112+
'https://api.github.com/repos/lightpanda-io/browser/releases/tags/nightly',
113+
)
114+
const lpChecksum = await checksumFile(DEFAULT_EXECUTABLE_PATH)
115+
116+
if (ghChecksum !== lpChecksum) {
117+
throw new Error("🚫 Checksums don't match!")
118+
}
119+
81120
chmodSync(DEFAULT_EXECUTABLE_PATH, constants.S_IRWXU)
82121

83122
console.info('✅ Done!')

packages/browser/src/utils.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16+
17+
import crypto, { type BinaryToTextEncoding } from 'node:crypto'
18+
import fs from 'node:fs'
1619
import os from 'node:os'
1720

1821
export const DEFAULT_CACHE_FOLDER = `${os.homedir()}/.cache/lightpanda-node`
@@ -61,3 +64,23 @@ export const validatePort = (port: number): void => {
6164
export const getExecutablePath = () => {
6265
return USER_EXECUTABLE_PATH ?? DEFAULT_EXECUTABLE_PATH
6366
}
67+
68+
/**
69+
* Get checksum from file
70+
*/
71+
export const checksumFile = (
72+
filePath: string,
73+
algorithm = 'sha256',
74+
encoding: BinaryToTextEncoding = 'hex',
75+
) => {
76+
return new Promise((resolve, reject) => {
77+
fs.readFile(filePath, (err, data) => {
78+
if (err) {
79+
reject(err)
80+
}
81+
82+
const hash = crypto.createHash(algorithm).update(data).digest(encoding)
83+
resolve(`${algorithm}:${hash}`)
84+
})
85+
})
86+
}

0 commit comments

Comments
 (0)