archive.test.mjs 1.4 KB

1234567891011121314151617181920212223242526272829
  1. import { test } from 'node:test'
  2. import assert from 'node:assert/strict'
  3. import fs from 'node:fs'
  4. import path from 'node:path'
  5. import os from 'node:os'
  6. import zlib from 'node:zlib'
  7. import { packageFiles } from '../tar.mjs'
  8. function entry(name, type = '0', body = 'example') {
  9. const header = Buffer.alloc(512)
  10. header.write(name)
  11. header.write(Buffer.byteLength(body).toString(8).padStart(11, '0'), 124)
  12. header.write(type, 156)
  13. return Buffer.concat([header, Buffer.from(body), Buffer.alloc((512 - Buffer.byteLength(body) % 512) % 512)])
  14. }
  15. function withArchive(data, callback) {
  16. const root = fs.mkdtempSync(path.join(os.tmpdir(), 'scriptor-archive-'))
  17. const file = path.join(root, 'package.tgz')
  18. try { fs.writeFileSync(file, zlib.gzipSync(Buffer.concat([data, Buffer.alloc(1024)]))); callback(file) }
  19. finally { fs.unlinkSync(file); fs.rmdirSync(root) }
  20. }
  21. test('archive inspection reads regular files without extracting', () => {
  22. withArchive(entry('package/README.md'), file => assert.equal(packageFiles(file).get('README.md').toString(), 'example'))
  23. })
  24. test('archive inspection rejects traversal, links, absolute paths and duplicate entries', () => {
  25. for (const data of [entry('package/../../secret'), entry('package/link', '2'), entry('/package/file'), Buffer.concat([entry('package/x'), entry('package/x')])]) {
  26. withArchive(data, file => assert.throws(() => packageFiles(file)))
  27. }
  28. })