mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2025-10-03 01:39:37 +02:00
Check max ZIP uncompressed size
This commit is contained in:
parent
69c851c8e6
commit
473cd4f7ef
4 changed files with 36 additions and 4 deletions
BIN
packages/tests/fixtures/zip-bomb.zip
vendored
Normal file
BIN
packages/tests/fixtures/zip-bomb.zip
vendored
Normal file
Binary file not shown.
|
@ -122,7 +122,8 @@ describe('Test user import API validators', function () {
|
|||
'export-without-videos.zip',
|
||||
'export-bad-structure.zip',
|
||||
'export-bad-structure.zip',
|
||||
'export-crash.zip'
|
||||
'export-crash.zip',
|
||||
'zip-bomb.zip'
|
||||
]
|
||||
|
||||
const tokens: string[] = []
|
||||
|
|
|
@ -7,7 +7,14 @@ import { logger, loggerTagsFactory } from './logger.js'
|
|||
|
||||
const lTags = loggerTagsFactory('unzip')
|
||||
|
||||
export async function unzip (source: string, destination: string) {
|
||||
export async function unzip (options: {
|
||||
source: string
|
||||
destination: string
|
||||
maxSize: number // in bytes
|
||||
maxFiles: number
|
||||
}) {
|
||||
const { source, destination } = options
|
||||
|
||||
await ensureDir(destination)
|
||||
|
||||
logger.info(`Unzip ${source} to ${destination}`, lTags())
|
||||
|
@ -18,9 +25,25 @@ export async function unzip (source: string, destination: string) {
|
|||
|
||||
zipFile.on('error', err => rej(err))
|
||||
|
||||
let decompressedSize = 0
|
||||
let entries = 0
|
||||
|
||||
zipFile.readEntry()
|
||||
|
||||
zipFile.on('entry', async entry => {
|
||||
decompressedSize += entry.uncompressedSize
|
||||
entries++
|
||||
|
||||
if (decompressedSize > options.maxSize) {
|
||||
zipFile.close()
|
||||
return rej(new Error(`Unzipped size exceeds ${options.maxSize} bytes`))
|
||||
}
|
||||
|
||||
if (entries > options.maxFiles) {
|
||||
zipFile.close()
|
||||
return rej(new Error(`Unzipped files count exceeds ${options.maxFiles}`))
|
||||
}
|
||||
|
||||
const entryPath = join(destination, entry.fileName)
|
||||
|
||||
try {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { UserImportResultSummary, UserImportState } from '@peertube/peertube-models'
|
||||
import { getFilenameWithoutExt } from '@peertube/peertube-node-utils'
|
||||
import { getFilenameWithoutExt, getFileSize } from '@peertube/peertube-node-utils'
|
||||
import { saveInTransactionWithRetries } from '@server/helpers/database-utils.js'
|
||||
import { logger, loggerTagsFactory } from '@server/helpers/logger.js'
|
||||
import { unzip } from '@server/helpers/unzip.js'
|
||||
|
@ -20,6 +20,7 @@ import { UserVideoHistoryImporter } from './importers/user-video-history-importe
|
|||
import { VideoPlaylistsImporter } from './importers/video-playlists-importer.js'
|
||||
import { VideosImporter } from './importers/videos-importer.js'
|
||||
import { WatchedWordsListsImporter } from './importers/watched-words-lists-importer.js'
|
||||
import { parseBytes } from '@server/helpers/core-utils.js'
|
||||
|
||||
const lTags = loggerTagsFactory('user-import')
|
||||
|
||||
|
@ -51,7 +52,14 @@ export class UserImporter {
|
|||
const inputZip = getFSUserImportFilePath(importModel)
|
||||
this.extractedDirectory = join(dirname(inputZip), getFilenameWithoutExt(inputZip))
|
||||
|
||||
await unzip(inputZip, this.extractedDirectory)
|
||||
await unzip({
|
||||
source: inputZip,
|
||||
destination: this.extractedDirectory,
|
||||
// Videos that take a lot of space don't have a good compression ratio
|
||||
// Keep a minimum of 1GB if the archive doesn't contain video files
|
||||
maxSize: Math.max(await getFileSize(inputZip) * 2, parseBytes('1GB')),
|
||||
maxFiles: 10000
|
||||
})
|
||||
|
||||
const user = await UserModel.loadByIdFull(importModel.userId)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue