Skip to content

fix: filter() uses values instead of keys, strips extension capabilities#147

Open
daifma wants to merge 1 commit intoinstaclick:masterfrom
daifma:fix/w3c-filter-capabilities
Open

fix: filter() uses values instead of keys, strips extension capabilities#147
daifma wants to merge 1 commit intoinstaclick:masterfrom
daifma:fix/w3c-filter-capabilities

Conversation

@daifma
Copy link

@daifma daifma commented Feb 8, 2026

Problem

The filter() method in WebDriver.php has three bugs:

Bug 1: Callback receives values instead of keys

The current code:

array_filter($capabilities, function ($capability) {
    return self::$w3cCapabilities[$capability] ?? 0;
})

array_filter passes values to the callback by default. When a capability value is an array
(e.g. goog:chromeOptions['args' => ['--no-sandbox']]), PHP tries to use the array as
an array key in self::$w3cCapabilities[$capability], causing a TypeError crash.

Bug 2: Extension capabilities are stripped

Even if Bug 1 were fixed, the filter only allows keys present in $w3cCapabilities. This strips
all extension capabilities like
goog:chromeOptions, moz:firefoxOptions, ms:edgeOptions, etc. Per the W3C spec, extension
capabilities are identified by containing a : in the key name and MUST be allowed through.

Bug 3: array_values destroys key-value pairs

The original code wraps the result in array_values(), which reindexes the array numerically.
This destroys the capability name → value mapping, turning
{"browserName": "chrome"} into ["chrome"].

Fix

- return $capabilities ? array_values(array_filter($capabilities, function ($capability) {
-     return self::$w3cCapabilities[$capability] ?? 0;
- })) : null;
+ return $capabilities ? array_filter($capabilities, function ($key) {
+     return isset(self::$w3cCapabilities[$key]) || str_contains($key, ':');
+ }, ARRAY_FILTER_USE_KEY) : null;

Changes:

  1. Use ARRAY_FILTER_USE_KEY so the callback receives keys not values
  2. Allow extension capabilities (keys containing :) per W3C spec
  3. Remove array_values() to preserve the key-value mapping

How to reproduce

  1. Configure capabilities with goog:chromeOptions:
    $capabilities = ['goog:chromeOptions' => ['args' => ['--no-sandbox']]];
  2. Call $webDriver->session('chrome', $capabilities)
  3. Observe: TypeError because array(['args' => ...]) is used as array key

References

The filter() method had three bugs:

1. array_filter callback received values instead of keys, causing
   TypeError when capability values are arrays (e.g. goog:chromeOptions)

2. Extension capabilities (keys containing ':') were stripped, but
   W3C spec requires them to be allowed through

3. array_values() destroyed the key-value mapping, turning
   {"browserName": "chrome"} into ["chrome"]

Fix by using ARRAY_FILTER_USE_KEY, allowing extension capabilities
per W3C spec, and removing array_values() wrapper.

References:
- https://www.w3.org/TR/webdriver2/#dfn-extension-capability
- https://www.php.net/array_filter
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant