Skip to content

Commit

Permalink
Merge pull request #894 from seanpoulter/executables
Browse files Browse the repository at this point in the history
fix: Prevent overwriting executable when extracting .zip
  • Loading branch information
seanpoulter authored Mar 23, 2024
2 parents 8b3ab5c + 6d0db11 commit 599263c
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 21 deletions.
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.ts text eol=lf
*.js text eol=lf
*.md text eol=lf
16 changes: 12 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,25 @@ on:

jobs:
linux:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: ['12.x', '14.x', '16.x', '18.x', '20.x']
java: ['11']
os: [ubuntu-latest]
node-version: [12, 14, 16, 18, 20]
java-version: [11]
include:
- os: macos-latest
node-version: 20
java-version: 11
- os: windows-latest
node-version: 20
java-version: 11
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: ${{ matrix.java }}
java-version: ${{ matrix.java-version }}
- uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
Expand Down
6 changes: 1 addition & 5 deletions lib/compute-download-urls.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,7 @@ async function computeDownloadUrls(options) {
downloadUrls.edge = opts.drivers.edge.fullURL || getEdgeDriverUrl(opts.drivers.edge.version);
}
if (opts.drivers.chromiumedge) {
await resolveLatestVersion(
opts,
'chromiumedge',
'https://msedgewebdriverstorage.blob.core.windows.net/edgewebdriver/LATEST_STABLE'
);
await resolveLatestVersion(opts, 'chromiumedge', 'https://msedgedriver.azureedge.net/LATEST_STABLE');
downloadUrls.chromiumedge =
opts.drivers.chromiumedge.fullURL ||
util.format(
Expand Down
55 changes: 45 additions & 10 deletions lib/install-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,31 @@ const md5 = require('md5');

const installers = ['selenium', 'chrome', 'ie', 'firefox', 'edge', 'chromiumedge'];

const isBrowserDriver = (fileName) => {
const extensions = ['.exe'];
return extensions.some((ext) => fileName.endsWith(ext)) || !fileName.includes('.');
/**
* @param {import('yauzl').Entry} entry
* @returns {boolean}
*/
const isExecutable = (entry) => {
// Windows .exe files are executables
if (path.extname(entry.fileName) === '.exe') {
return true;
}

// Extract the Unix file permissions.
// See https://github.com/thejoshwolfe/yauzl/issues/102 and https://unix.stackexchange.com/a/14727.
const permissions = entry.externalFileAttributes >>> 16;

// Directories are not executable
if (permissions & fs.constants.S_IFDIR) {
return false;
}

// Return true when the user, group, or other executable bits are set.
return (
!!(permissions & fs.constants.S_IXUSR) ||
!!(permissions & fs.constants.S_IXGRP) ||
!!(permissions & fs.constants.S_IXOTH)
);
};

const basePath = (fullPath) => {
Expand Down Expand Up @@ -113,16 +135,30 @@ async function uncompressDownloadedFile(zipFilePath) {
if (fs.existsSync(entry.fileName) && fs.lstatSync(entry.fileName).isDirectory()) {
return; // ignore folders, i.e. release notes folder in edge driver zip
}
if (!isExecutable(entry)) {
return;
}

zipFile.openReadStream(entry, { autoClose: true }, function onOpenZipFileEntryReadStream(errRead, readStream) {
if (errRead) {
return reject(logError('uncompressDownloadedFile:zipFile.openReadStream', err));
}
const extractPath = path.join(
path.dirname(zipFilePath),
isBrowserDriver(entry.fileName)
? path.basename(zipFilePath, '.zip') + `${process.platform === 'win32' ? '.exe' : ''}`
: path.basename(entry.fileName)
);

// The .zip file usually contain an executable with the same name as the driver.
// For example, we expect to extract "msedgedriver.exe" as "msedgedriver.exe".
//
// There are three known exceptions:
//
// 1. The .zip files from Chrome for Testing have files in a directory.
// For example, we want to extract "chromedriver-mac-arm64/chromedriver" as "chromedriver" from "chromedriver-mac-arm64.zip".
//
// 2. msedgedriver v86 and v87 for mac64 include a second executable file, libc++.dylib, It is also extracted.
//
// 3. The exectuables for geckodriver <= v0.7.1 are called "wires.exe" or "wires-<version>-win.exe".
// These releases are so old we can ignore them.
//
const extractPath = path.join(path.dirname(zipFilePath), path.basename(entry.fileName));

const extractWriteStream = fs
.createWriteStream(extractPath)
.once('error', (errWs) => reject(logError('uncompressDownloadedFile:readStream.pipe', errWs)));
Expand Down Expand Up @@ -224,7 +260,6 @@ async function runInstaller(installerFile, from, to) {
}

module.exports = {
isBrowserDriver,
asyncLogEnd,
createDirs,
setDriverFilePermissions,
Expand Down
28 changes: 28 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
"build": "tsc -p .",
"start": "DEBUG=selenium-standalone:* ./bin/selenium-standalone install && DEBUG=selenium-standalone:* ./bin/selenium-standalone start",
"test": "run-s test:*",
"test:v4": "export SELENIUM_VERSION=4.18.0 && ./bin/selenium-standalone install && nyc --silent mocha --timeout=60000",
"test:v3": "export SELENIUM_VERSION=3.141.59 && ./bin/selenium-standalone install && --silent mocha 'test/programmatic.js' --timeout=60000",
"test:v4": "cross-env-shell SELENIUM_VERSION=4.9.0 \"./bin/selenium-standalone install && nyc --reporter=text --reporter=html mocha --timeout=60000\"",
"test:v3": "cross-env-shell SELENIUM_VERSION=3.141.59 \"./bin/selenium-standalone install && mocha 'test/programmatic.js' --timeout=60000\"",
"docker:build": "run-s docker:build:*",
"docker:build:latest": "docker build -t webdriverio/${npm_package_name}:latest --cache-from webdriverio/${npm_package_name}:latest .",
"docker:build:tag": "docker build -t webdriverio/${npm_package_name}:${npm_package_version} --cache-from webdriverio/${npm_package_name}:${npm_package_version} .",
Expand Down Expand Up @@ -65,6 +65,7 @@
"@types/chai": "^4.3.12",
"@types/mocha": "^10.0.6",
"chai": "^4.4.1",
"cross-env": "^7.0.3",
"doctoc": "2.2.1",
"eslint": "8.57.0",
"eslint-config-prettier": "9.1.0",
Expand Down

0 comments on commit 599263c

Please sign in to comment.