harden code: geo_ip download

Massimo Melina committed May 20, 2026 at 15:18 UTC 35a902137279797abce2ff305f2feff45646955f
2 files changed +8 -8
src/geo.ts
+7 -6
@@ -1,6 +1,6 @@
1 import { defineConfig } from './config'
2 import { CFG, DAY, httpStream, isIpLan, isLocalHost, statWithTimeout, unzip } from './misc'
3 -import { rename, unlink } from 'node:fs/promises'
3 +import { rename } from 'node:fs/promises'
4 import { IP2Location } from 'ip2location-nodejs'
5 import _ from 'lodash'
6 import { Middleware } from 'koa'
@@ -36,8 +36,8 @@ function isOpen() {
36
37 async function checkFiles() {
38 if (!enabled.get()) return
39 - const ZIP_FILE = 'IP2LOCATION-LITE-DB1.IPV6.BIN'
40 - const URL = `https://download.ip2location.com/lite/${ZIP_FILE}.ZIP`
39 + const BIN_FILE = 'IP2LOCATION-LITE-DB1.IPV6.BIN'
40 + const URL = `https://download.ip2location.com/lite/${BIN_FILE}.ZIP`
41 const LOCAL_FILE = 'geo_ip.bin'
42 const TEMP = LOCAL_FILE + '.downloading'
43 const { mtime=0 } = await statWithTimeout(LOCAL_FILE).catch(() => ({ mtime: 0 }))
@@ -47,11 +47,12 @@ async function checkFiles() {
47 try {
48 const req = await httpStream(URL)
49 console.log(`Downloading ${name}`)
50 - await unzip(req, path => path.toUpperCase().endsWith(ZIP_FILE) && TEMP)
51 - await statWithTimeout(TEMP) // check existence
50 + await unzip(req, path => path.toUpperCase().endsWith(BIN_FILE) && TEMP) // give a temp name
51 + const s = await statWithTimeout(TEMP) // check existence
52 + if (s.size < 1E6)
53 + throw `Bad size for geo_ip: ${s.size}`
54 if (isOpen())
55 ip2location.close()
54 - await unlink(LOCAL_FILE).catch(() => {})
56 await rename(TEMP, LOCAL_FILE)
57 ip2country.cache.clear?.()
58 console.log(`${name} download completed`)
src/perm.ts
+1 -2
@@ -1,11 +1,10 @@
1 // This file is part of HFS - Copyright 2021-2023, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
2
3 import _ from 'lodash'
4 -import { HTTP_BAD_REQUEST, objRenameKey, objSameKeys, setHidden, typedEntries, wantArray } from './misc'
4 +import { objRenameKey, objSameKeys, setHidden, typedEntries, wantArray } from './misc'
5 import { defineConfig, saveConfigAsap } from './config'
6 import { createVerifierAndSalt, SRPParameters, SRPRoutines } from 'tssrp6a'
7 import events from './events'
8 -import { ApiError } from './apiMiddleware'
8 import { getCurrentUsername } from './auth'
9 import Koa from 'koa'
10