Skip to content

Commit

Permalink
fix(lib): Adds a 10 MiB cap to manifest size
Browse files Browse the repository at this point in the history
This should help prevent an avenue for DoSes
  • Loading branch information
dmihalcik-virtru committed Sep 19, 2024
1 parent 6eb70c1 commit 40838a8
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 1 deletion.
7 changes: 7 additions & 0 deletions lib/tdf3/src/utils/zip-reader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ const CD_SIGNATURE = 0x02014b50;
const CENTRAL_DIRECTORY_RECORD_FIXED_SIZE = 46;
const LOCAL_FILE_HEADER_FIXED_SIZE = 30;
const VERSION_NEEDED_TO_EXTRACT_ZIP64 = 45;
const manifestMaxSize = 1024 * 1024 * 10; // 10 MB

const cp437 =
'\u0000☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼ !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~⌂ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ ';

Expand Down Expand Up @@ -92,6 +94,11 @@ export class ZipReader {
throw new Error('Unable to retrieve CD manifest');
}
const byteStart = cdObj.relativeOffsetOfLocalHeader + cdObj.headerLength;
if (cdObj.uncompressedSize > manifestMaxSize) {
throw new Error(
`manifest file too large: ${(cdObj.uncompressedSize >> 10).toLocaleString()} KiB`
);
}
const byteEnd = byteStart + cdObj.uncompressedSize;
const manifest = await this.getChunk(byteStart, byteEnd);

Expand Down
31 changes: 30 additions & 1 deletion lib/tests/mocha/unit/zip.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { expect } from 'chai';

import { encodeArrayBuffer } from '../../../src/encodings/base64.js';
import { parseCDBuffer, readUInt64LE } from '../../../tdf3/src/utils/zip-reader.js';
import {
CentralDirectory,
parseCDBuffer,
readUInt64LE,
ZipReader,
} from '../../../tdf3/src/utils/zip-reader.js';
import { ZipWriter, dateToDosDateTime, writeUInt64LE } from '../../../tdf3/src/utils/zip-writer.js';

describe('zip utilities', () => {
Expand Down Expand Up @@ -170,3 +175,27 @@ describe('zip utilities', () => {
});
});
});

describe('reader', () => {
it('fails on bad manifest size', async () => {
const reader = new ZipReader(async () => new Uint8Array([]));
const fileName = '0.manifest.json';
try {
expect(
await reader.getManifest(
[
{
fileName,
relativeOffsetOfLocalHeader: 0,
headerLength: 1024,
uncompressedSize: 1024 * 1024 * 128,
} as CentralDirectory,
],
fileName
)
).to.be.undefined;
} catch (e) {
expect(e.message).to.contain('too large');
}
});
});

0 comments on commit 40838a8

Please sign in to comment.