{"record":{"id":"30c589923b6b73cc","repo":"cypress-io/cypress","slug":"refusing-to-extract-symlink-with-target-larger-tha","errorCode":null,"errorMessage":"Refusing to extract symlink with target larger than ${MAX_SYMLINK_TARGET_BYTES} bytes: ${entry.fileName}","messagePattern":"Refusing to extract symlink with target larger than (.+?) bytes: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cli/lib/tasks/extract-with-yauzl.ts","lineNumber":115,"sourceCode":"\n  const unixMode = (entry.externalFileAttributes >>> 16) & 0xffff\n  // Some archivers mark directories by Unix mode bits instead of (or in\n  // addition to) a trailing slash; honor both so we don't extract a\n  // directory entry as a zero-byte file.\n  const isDir = /\\/$/.test(entry.fileName) || (unixMode & S_IFMT) === S_IFDIR\n  const isSymlink = (unixMode & S_IFMT) === S_IFLNK\n\n  if (isDir) {\n    await fsp.mkdir(fileDest, { recursive: true })\n\n    return\n  }\n\n  await fsp.mkdir(path.dirname(fileDest), { recursive: true })\n\n  if (isSymlink) {\n    if (entry.uncompressedSize > MAX_SYMLINK_TARGET_BYTES) {\n      throw new Error(`Refusing to extract symlink with target larger than ${MAX_SYMLINK_TARGET_BYTES} bytes: ${entry.fileName}`)\n    }\n\n    const linkTarget = await readEntryAsString(zipFile, entry, MAX_SYMLINK_TARGET_BYTES)\n    const resolvedTarget = path.resolve(path.dirname(fileDest), linkTarget)\n\n    if (\n      resolvedTarget !== resolvedDest &&\n      !resolvedTarget.startsWith(resolvedDest + path.sep)\n    ) {\n      throw new Error(`Refusing to extract symlink pointing outside of destination: ${entry.fileName} -> ${linkTarget}`)\n    }\n\n    await fsp.rm(fileDest, { recursive: true, force: true })\n    await fsp.symlink(linkTarget, fileDest)\n\n    return\n  }\n","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/cypress-io/cypress/blob/0d85fdc91230885bca0a91df278312800a48b727/cli/lib/tasks/extract-with-yauzl.ts#L97-L133","documentation":"Raised by handleEntry() when a zip entry is a Unix symlink (externalFileAttributes S_IFLNK) whose uncompressedSize exceeds MAX_SYMLINK_TARGET_BYTES (4096, the Linux/macOS PATH_MAX). Targets this large are not legal filesystem paths and would also mean reading an arbitrarily large entry fully into memory, so the extractor refuses up front as a hardening measure.","triggerScenarios":"Extracting a Cypress binary zip (or a custom CYPRESS_INSTALL_BINARY zip) that contains a symlink entry with an absurdly large target. Only reachable with a malformed or malicious archive; the official Cypress zip never contains such entries.","commonSituations":"A hand-crafted or corrupted zip fed via CYPRESS_INSTALL_BINARY; a tampered mirror artifact; a fuzz/penetration test payload.","solutions":["Do not use the failing artifact. Re-download the official cypress.zip from the default CDN after clearing the cache.","Unset CYPRESS_INSTALL_BINARY / CYPRESS_DOWNLOAD_MIRROR to restore the trusted source.","Inspect the archive (`unzip -l`) and remove or fix the offending symlink entry before re-zipping if you maintain a custom artifact."],"exampleFix":"# before: custom zip with oversized symlink entry\n# after:\nunset CYPRESS_INSTALL_BINARY\nrm -rf ~/.cache/Cypress\ncypress install","handlingStrategy":"try-catch","validationCode":"// Reject archives containing oversized symlink entries before extracting:\nasync function assertNoHugeSymlinks(zipPath: string, maxBytes = 4096) {\n  await new Promise<void>((resolve, reject) => {\n    yauzl.open(zipPath, { lazyEntries: true }, (err, zf) => {\n      if (err) return reject(err)\n      zf.on('entry', (entry) => {\n        const mode = (entry.externalFileAttributes >>> 16) & 0xffff\n        const isSymlink = (mode & 0o170000) === 0o120000\n        if (isSymlink && entry.uncompressedSize > maxBytes) {\n          return reject(new Error(`Oversized symlink: ${entry.fileName}`))\n        }\n        zf.readEntry()\n      })\n      zf.on('end', () => resolve())\n      zf.readEntry()\n    })\n  })\n}","typeGuard":null,"tryCatchPattern":"try {\n  await extractWithYauzl(zipPath, destDir, () => {})\n} catch (e) {\n  if (e instanceof Error && /symlink with target larger/.test(e.message)) {\n    // archive is malformed/malicious — discard and re-download from official source\n  }\n  throw e\n}","preventionTips":["Treat any zip that triggers this as untrusted.","Always source the Cypress binary from the official CDN.","Scan custom archives for abnormal entries before installing."],"tags":["install","extract","security","symlink"],"backgroundTag":null,"analyzedSha":"0d85fdc91230885bca0a91df278312800a48b727","analyzedAt":"2026-08-12T16:24:28.056Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}