GitHub Security Advisory: GHSA-rfx7-4xw3-gh4m
Package: @appium/support (NPM)
Severity: MODERATE (CVSS 6.5)
CWE: CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
Vulnerable versions: <= 7.0.5
Patched in: 7.0.6

Summary: @appium/support has a Zip Slip arbitrary file write in its ZIP extraction

Details:
## Summary

`@appium/support` contains a ZIP extraction implementation (`extractAllTo()` via `ZipExtractor.extract()`) with a path traversal (Zip Slip) check that is non-functional. The check at line 88 of `packages/support/lib/zip.js` creates an `Error` object but never throws it, allowing malicious ZIP entries with `../` path components to write files outside the intended destination directory. This affects all JS-based extractions (the default code path), not only those using the `fileNamesEncoding` option.

## Severity

**Medium** (CVSS 3.1: 6.5)

`CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N`

- **Attack Vector:** Network — malicious ZIP files can be supplied over the network (e.g., app packages via URL)
- **Attack Complexity:** Low — no special conditions required beyond providing a crafted ZIP
- **Privileges Required:** None — no authentication needed to supply a malicious archive
- **User Interaction:** Required — a user or automation system must initiate extraction of the attacker's archive
- **Scope:** Unchanged — impact stays within the file system permissions of the Appium process
- **Confidentiality Impact:** None — the vulnerability enables file writes, not reads
- **Integrity Impact:** High — arbitrary file write to any location writable by the process
- **Availability Impact:** None — no direct availability impact

## Affected Component

- `packages/support/lib/zip.js` — `ZipExtractor.extract()` (line 88) and `ZipExtractor.extractEntry()` (lines 111-145)

## CWE

- **CWE-22**: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

## Description

### Missing `throw` renders Zip Slip protection non-functional

The `ZipExtractor.extract()` method contains a path traversal check intended to prevent Zip Slip attacks. However, the check creates an `Error` object as a bare expression without the `throw` keyword, making it a no-op:

```javascript
// packages/support/lib/zip.js, lines 80-93
const destDir = path.dirname(path.join(dir, fileName));
try {
    await fs.mkdir(destDir, {recursive: true});

    const canonicalDestDir = await fs.realpath(destDir);
    const relativeDestDir = path.relative(dir, canonicalDestDir);

    if (relativeDestDir.split(path.sep).includes('..')) {
        new Error(                                          // <-- BUG: missing `throw`
            `Out of bound path "${canonicalDestDir}" found while processing file ${fileName}`
        );
    }

    await this.extractEntry(entry);   // extraction proceeds unconditionally
```

The presence of a well-formatted error message and surrounding try/catch block (lines 95-99) strongly suggests the `throw` keyword was accidentally omitted.

### yauzl does not provide its own traversal protection

The upstream `yauzl` library explicitly [does not offer path traversal protection](https://github.com/thejoshwolfe/yauzl#no-path-traversal-protection) regardless of the `decodeStrings` setting. This means the vulnerability affects **all** JS-based extra