GitHub Security Advisory: GHSA-8qm8-g55h-xmqr
Package: wwbn/avideo (COMPOSER)
Severity: MODERATE (CVSS 5.4)
CWE: CWE-352: Cross-Site Request Forgery (CSRF)
Vulnerable versions: <= 29.0
Patched in: unpatched

Summary: WWBN AVideo is missing CSRF protection in objects/commentDelete.json.php enables mass comment deletion against moderators and content creators

Details:
## Summary

`objects/commentDelete.json.php` is a state-mutating JSON endpoint that deletes comments but performs no CSRF validation. It does not call `forbidIfIsUntrustedRequest()`, does not verify a CSRF/global token, and does not check `Origin`/`Referer`. Because AVideo intentionally sets `session.cookie_samesite=None` (to support cross-origin embed players), a cross-site request from any attacker-controlled page automatically carries the victim's `PHPSESSID`. Any authenticated victim who has authority to delete one or more comments (site moderators, video owners, and comment authors) can be tricked into deleting comments en masse simply by visiting an attacker page.

## Details

### Vulnerable endpoint: `objects/commentDelete.json.php`

```php
// objects/commentDelete.json.php:1-35
<?php
header('Content-Type: application/json');
global $global, $config;
if (!isset($global['systemRootPath'])) {
    require_once '../videos/configuration.php';
}
require_once $global['systemRootPath'] . 'objects/comment.php';

$obj = new stdClass();
$obj->error = true;
$obj->msg = '';
$obj->id = intval(@$_REQUEST['id']);      // <-- GET or POST
$obj->status = false;

if (empty($obj->id)) {
    $obj->id = intval(@$_REQUEST['comments_id']);
}

if (empty($obj->id)) {
    $obj->msg = __("ID can not be empty");
    die(_json_encode($obj));
}

$objC = new Comment("", 0, $obj->id);
$obj->videos_id = $objC->getVideos_id();
$obj->status = $objC->delete();           // <-- destructive action, no CSRF check
...
```

No `forbidIfIsUntrustedRequest()`, no `verifyToken()`, no token/nonce parameter, no `Origin`/`Referer` validation. The handler accepts `$_REQUEST`, so the request may be delivered as `GET` (e.g. via `<img src>`) or `POST` (e.g. via an auto-submitting form / `fetch`).

### Authorization inside `Comment::delete()` does not stop CSRF

```php
// objects/comment.php:147-159
public function delete() {
    if (!self::userCanAdminComment($this->id)) {
        return false;
    }
    ...
    $sql = "DELETE FROM comments WHERE id = ?";
    ...
    return sqlDAL::writeSql($sql, "i", [$this->id]);
}

// objects/comment.php:316-332
public static function userCanAdminComment($comments_id) {
    if (!User::isLogged()) { return false; }
    if (Permissions::canAdminComment()) { return true; }   // site moderator
    $obj = new Comment("", 0, $comments_id);
    if ($obj->users_id == User::getId()) { return true; }  // comment owner
    $video = new Video("", "", $obj->videos_id);
    if ($video->getUsers_id() == User::getId()) { return true; } // video owner
    return false;
}
```

This check is exactly what CSRF abuses: it asks "is the session user allowed to delete this comment?" In a CSRF attack, the session user is the victim, and yes — the victim is allowed. So the check grants the request.

### Site-wide cookie policy makes cross-site delivery reliable

```php
// objects/include_config.php:139-146
if ($isHTTPS) {
    // SameSite=None is intentional: AVideo supports cross-