| Name | Modified | Size | Downloads / Week |
|---|---|---|---|
| Parent folder | |||
| e107_v2.x_to_2.3.7_upgrade.zip | 2026-06-14 | 12.3 MB | |
| e107_v2.x_to_2.3.7_upgrade.tar.xz | 2026-06-14 | 8.3 MB | |
| e107_v2.x_to_2.3.7_upgrade.tar.gz | 2026-06-14 | 11.5 MB | |
| e107_v1.x_to_2.3.7_upgrade.zip | 2026-06-14 | 14.8 MB | |
| e107_v1.x_to_2.3.7_upgrade.tar.xz | 2026-06-14 | 10.2 MB | |
| e107_v1.x_to_2.3.7_upgrade.tar.gz | 2026-06-14 | 13.7 MB | |
| e107_2.3.7_full.zip | 2026-06-14 | 14.7 MB | |
| e107_2.3.7_full.tar.xz | 2026-06-14 | 10.2 MB | |
| e107_2.3.7_full.tar.gz | 2026-06-14 | 13.6 MB | |
| e107 v2.3.7 source code.tar.gz | 2026-06-14 | 15.7 MB | |
| e107 v2.3.7 source code.zip | 2026-06-14 | 17.0 MB | |
| README.md | 2026-06-14 | 11.6 kB | |
| Totals: 12 Items | 142.0 MB | 2 | |
[!CAUTION] v2.3.7 is a security release for sites on v2.3.6 or earlier. Upgrade from any 2.x at or below v2.3.6. If your site tracks the
masterbranch, you are already past v2.3.7, so installing it would be a downgrade. v2.4.x is planned to be the next forward step.[!IMPORTANT] Upgrade immediately. v2.3.7 closes two unauthenticated, network-reachable, Critical vulnerabilities. Neither requires authentication, user interaction, or any special privilege, and every public-facing site on v2.3.6 or earlier is exposed.
- Remote code execution via
install.php(GHSA-c8h6-wpj3-4cr8, CVSS 9.8). Reachable on a default installation:install.phpstays live and exploitable after setup.Mitigation: Delete
install.php. - SQL injection throughout the e107 core (GHSA-5f75-c25x-59wx, CVSS 10.0). Request data is interpolated into SQL across ordinary, unauthenticated front-end request handling, including code an anonymous visitor triggers with a single page view (online-presence tracking writes the request URI into the database after a sanitizer that still permits the closing quote). It is not confined to any one plugin or feature, so no configuration change mitigates it. The only protection short of upgrading is to keep the site off the public Internet.Treat this as an emergency upgrade.
Highlights
- [Security] Remote code execution through the installer (GHSA-c8h6-wpj3-4cr8, CVSS 9.8). On a normal site,
install.phpstayed reachable after setup and could be tricked into running an attacker's code, with no login. It now refuses to run once the site is installed, and the information the setup wizard carries between steps can no longer be used to smuggle in code. (https://github.com/e107inc/e107/commit/6c40429521, https://github.com/e107inc/e107/commit/5d6d649e8c) - [Security] Database break-in through ordinary pages (GHSA-5f75-c25x-59wx, CVSS 10.0). Many everyday pages passed details from the web request into database queries without making them safe, so an attacker could run their own database commands, with no login and often just by visiting a crafted web address. This is now fixed throughout the core. No setting protects an unpatched site: you have to upgrade (or keep the site off the public Internet). (https://github.com/e107inc/e107/commit/120bd4bdbe)
- [Security] A database-safety function that did nothing. One of e107's built-in functions for making a value safe to use in a database query was handing it back unchanged, so any code that relied on it had no protection. It now works as documented. (#5749, https://github.com/e107inc/e107/commit/b467b74f72)
For Administrators
Changed
- The installer locks itself after setup (security). Once your site is installed, the setup wizard refuses to run again, so it can no longer be reached or misused on a live site. e107 decides this from the configuration file alone, so a database outage cannot accidentally reopen it. If you ever need to reinstall on purpose, delete
e107_config.phpfirst. Automated ("unattended") installs are only accepted on a site that is not already set up. Ref GHSA-c8h6-wpj3-4cr8. (https://github.com/e107inc/e107/commit/5d6d649e8c) - Database queries protected across the site (security). Many parts of e107 (including who's-online tracking, the ban list, ratings, comments, login, and registration) took information from the web request and used it in database queries without making it safe first. That has been corrected everywhere it was found, including the
alt_authexternal-database login that the report originally came in on. There is nothing for you to configure and the site behaves exactly as before; installing this release is what protects you. Ref GHSA-5f75-c25x-59wx. (https://github.com/e107inc/e107/commit/120bd4bdbe) - The website-address header is checked before use (hardening). e107 builds some links from the
Hostheader a visitor's browser sends; it now rejects a malformed value and uses the server's own hostname instead. On a correctly configured site the existing host check already turns away mismatched hosts, so this is an extra safety net, and it also makes sure a non-standard port is kept in the links e107 generates. Ref [#5734]. (https://github.com/e107inc/e107/commit/a2f386b27f)
Fixed
- Welcome Message creation date. A rewrite had dropped the automatic creation date when a Welcome Message menu item is created; it is restored, so the date is available for themes that choose to show it. Fixes [#5739]. (https://github.com/e107inc/e107/commit/bdb6c35116)
- Media-category create page on PHP 8.
media_cat_ui::createPage()calledcount()on an unset writeParms value when every category owner is restricted, throwing aTypeErrorunder PHP 8. It now uses a null-safe check and keeps the same "category creation not available" behavior. Fixes [#5741]. (https://github.com/e107inc/e107/commit/d5e0d07814) - Enter advances the install wizard. The buttons bar emitted Back before Continue, so an implicit submit (Enter in a text field) sent the wizard back a step. The forward control is emitted first and the bar laid out
row-reverse, so the visible order is unchanged and only the Enter behavior is fixed. (https://github.com/e107inc/e107/commit/2865e98f96)
For Developers
Added
- Test coverage.
installStateTestbuilds the real guzzlehttp/psr7 POP chain and asserts the new JSON codec rejects it while round-tripping scalars;SqlInjectionFixesTestpins the core SQL-injection remediations; and acceptance coverage exercises the installer reinstall guard, paste-to-resume, and the unattended-install path end to end. (https://github.com/e107inc/e107/commit/6c40429521, https://github.com/e107inc/e107/commit/892758085c) eShims::setcookie()options-array shim. BackportedSetcookieTrait(the PHP 7.3+ options-array form with a pre-7.3SameSite-into-path fallback) so the installer can set a hardened (HttpOnly,Secure,SameSite=Strict) resume cookie with one call across every supported runtime. Existingsetcookie()callers are untouched. (https://github.com/e107inc/e107/commit/1063102678)
Changed
- Installer wizard state is now signed JSON, and the installer fails closed.
install.phppreviouslyunserialize()d base64-encoded$_POST['previous_steps']with noallowed_classes, at file scope on every request and again in thee_installconstructor; the bundled guzzlehttp/psr7PumpStreamPOP chain reached arbitrary callable execution once the decoded value flowed intosite_pathand was coerced to a string. Wizard state now travels asbase64(JSON).hex(HMAC), verified in constant time on every request against a per-install CSPRNG signing token, andjson_decode()only yields arrays and scalars, so object injection (CWE-502) is impossible by construction.e107_config.phpis read as one of three positive states (fresh, install-pending, installed) instead of an emptiness check; the unattended?create_tablespath compares credentials withhash_equals()and refuses a database that already holds an e107 schema; and the finished config is written last, so a half-finished install never looks installed. (https://github.com/e107inc/e107/commit/6c40429521, https://github.com/e107inc/e107/commit/5d6d649e8c) - Core SQL-injection remediation techniques. Because the 2.3.x line predates the
e_dbprepared-statement API, tainted values are escaped inside their SQL quotes, numeric /LIMIT/OFFSETpositions are(int)cast, and dynamic table/column identifiers are confined to a strict[A-Za-z0-9_]allowlist (escaping cannot protect identifiers). Import providers are fixed at the root inbase_import_class::database(). Many sinks are reachable without a login: the online-presence tracker, for example, wrotee_REQUEST_URIintoonline_locationafter onlyFILTER_SANITIZE_URL, which keeps the single quote, so a crafted address reached the query directly. If you maintain a plugin that builds raw SQL from request input, mirror these. (https://github.com/e107inc/e107/commit/120bd4bdbe) e_db_pdo::escape()now escapes. The sharedtestEscape()expectation that codified the pass-through is updated, which makes thee_db_mysqloverride redundant. One caller (social_setup.php) usedescape()on a value interpolated into an unquoted numeric context and is cast tointinstead. (#5749, https://github.com/e107inc/e107/commit/b467b74f72)Hostresolution helper (hardening). The request host is resolved through a sharedresolveHttpHost()backported from master: it accepts the clientHostonly when it matches ahost[:port]shape and otherwise falls back toSERVER_NAME, preserving the visited port. On a configured site theisAllowedHost()killswitch (added in v2.3.6) already rejects a mismatchedHostbefore it reaches a URL, so this is defense-in-depth (covering an unset or misconfiguredsiteurl, and partial-bootstrap entry points that skip the killswitch) plus a regression lock: the accompanyinge107HostValidationTestpins port preservation so a future sync from master cannot silently reintroduce the port-strip. (https://github.com/e107inc/e107/commit/a2f386b27f)- GitHub contribution templates revamped.
CONTRIBUTING.mdis now a policy document (backwards compatibility as the primary constraint, AI-assisted contributions welcome on the same quality bar, explicit rejection criteria for low-effort output), with matchingPULL_REQUEST_TEMPLATE.md, issue forms,FUNDING.yml, and a newSECURITY.md. (https://github.com/e107inc/e107/commit/2b49a62ce8)
Fixed
- Install log moved out of the document root.
e107Install.logwas written into the docroot, where the shipped.htaccesshas no rule for.logfiles, so its install diagnostics (DB host, table prefix, pref dumps on failure) were fetchable over HTTP. It now lives under the deny-by-defaulte107_system/. (https://github.com/e107inc/e107/commit/c1ef5bab81) - Installer reads its own config past opcache. With opcache on, a same-second rewrite of
e107_config.phpcould be served from the prior compile, hiding the freshly written provisioning lock. The installer nowopcache_invalidate()s the file around each read and write. (https://github.com/e107inc/e107/commit/72b333107e) - Non-destructive test isolation.
GitPreparer's rollback usedgit reset --hard && git clean -fdx, which destroyed uncommitted work on a crashed run. It now runs each suite inside a disposable git worktree withflock()-based orphan cleanup, never touching the main tree. (https://github.com/e107inc/e107/commit/aac93f1791)
Acknowledgements
Both vulnerabilities were responsibly disclosed through GitHub Security Advisories. Our thanks to @baozongwi (GHSA-c8h6-wpj3-4cr8) and @Jimmi08 (GHSA-5f75-c25x-59wx) for the reports.