VYPR
High severityNVD Advisory· Published Mar 7, 2026· Updated Mar 9, 2026

node-tar: Hardlink Path Traversal via Drive-Relative Linkpath

CVE-2026-29786

Description

node-tar is a full-featured Tar for Node.js. Prior to version 7.5.10, tar can be tricked into creating a hardlink that points outside the extraction directory by using a drive-relative link target such as C:../target.txt, which enables file overwrite outside cwd during normal tar.x() extraction. This issue has been patched in version 7.5.10.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
tarnpm
< 7.5.107.5.10

Affected products

1

Patches

1
7bc755dd85e6

parse root off paths before sanitizing .. parts

https://github.com/isaacs/node-tarisaacsMar 4, 2026via ghsa
3 files changed · +20 10
  • src/strip-absolute-path.ts+1 1 modified
    @@ -8,7 +8,7 @@ const { isAbsolute, parse } = win32
     // explicitly if it's the first character.
     // drive-specific relative paths on Windows get their root stripped off even
     // though they are not absolute, so `c:../foo` becomes ['c:', '../foo']
    -export const stripAbsolutePath = (path: string) => {
    +export const stripAbsolutePath = (path: string): [string, string] => {
       let r = ''
     
       let parsed = parse(path)
    
  • src/unpack.ts+3 3 modified
    @@ -277,7 +277,9 @@ export class Unpack extends Parser {
         const { type } = entry
         if (!p || this.preservePaths) return true
     
    -    const parts = p.split('/')
    +    // strip off the root
    +    const [root, stripped] = stripAbsolutePath(p)
    +    const parts = stripped.replace(/\\/g, '/').split('/')
     
         if (
           parts.includes('..') ||
    @@ -318,8 +320,6 @@ export class Unpack extends Parser {
           }
         }
     
    -    // strip off the root
    -    const [root, stripped] = stripAbsolutePath(p)
         if (root) {
           // ok, but triggers warning about stripping root
           entry[field] = String(stripped)
    
  • test/ghsa-8qq5-rm4j-mr97.ts+16 6 modified
    @@ -70,6 +70,14 @@ const getExploitTar = () => {
       }).encode(absWithDotDotHeader, 0)
       chunks.push(absWithDotDotHeader)
     
    +  const winAbsWithDotDotHeader = Buffer.alloc(512)
    +  new Header({
    +    path: 'a/winrootdotslink',
    +    type: 'SymbolicLink',
    +    linkpath: 'c:..\\foo\\bar',
    +  }).encode(winAbsWithDotDotHeader, 0)
    +  chunks.push(winAbsWithDotDotHeader)
    +
       chunks.push(Buffer.alloc(1024))
       return Buffer.concat(chunks)
     }
    @@ -83,9 +91,9 @@ const dir = t.testdir({
     const out = resolve(dir, 'out')
     const tarFile = resolve(dir, 'exploit.tar')
     
    -t.test('hardlink escape does not clobber target', async t => {
    -  await x({ cwd: out, file: tarFile })
    +t.before(() => x({ cwd: out, file: tarFile }))
     
    +t.test('writefile exploits fail', async t => {
       writeFileSync(resolve(out, 'exploit_hard'), 'OVERWRITTEN')
       t.equal(
         readFileSync(resolve(dir, 'secret.txt'), 'utf8'),
    @@ -100,20 +108,22 @@ t.test('hardlink escape does not clobber target', async t => {
     })
     
     t.test('symlink escapes are sanitized', async t => {
    -  await x({ cwd: out, file: tarFile })
    -
       t.not(readlinkSync(resolve(out, 'exploit_sym')), targetSym)
       t.throws(() => lstatSync(resolve(out, 'secret.txt')), {
         code: 'ENOENT',
       })
     })
     
     t.test('absolute symlink with .. has prefix stripped', async t => {
    -  await x({ cwd: out, file: tarFile })
    -
       t.equal(
         readlinkSync(resolve(out, 'a/link')),
         '../a/target',
         'symlink target should be normalized',
       )
    +
    +  t.equal(
    +    readlinkSync(resolve(out, 'a/winrootdotslink')),
    +    '..\\foo\\bar',
    +    'symlink target should be normalized',
    +  )
     })
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.