| Name | Modified | Size | Downloads / Week |
|---|---|---|---|
| Parent folder | |||
| v1.7.2.zip | 2026-08-28 | 27.9 MB | |
| README.md | 2026-08-27 | 28.5 kB | |
| v1.7.2 source code.tar.gz | 2026-08-27 | 1.5 MB | |
| v1.7.2 source code.zip | 2026-08-27 | 1.8 MB | |
| Totals: 4 Items | 31.2 MB | 1 | |
InvoicePlane v1.7.2
| Hash Format | Hash |
|---|---|
| MD5 | a9db07ea6511c7cf9988706277b375d7 |
| SHA-256 | 5d70ca0c437e9a35bdadddb4bb98dc89f5cc19527d1dad214579db7d6292f2b8 |
Thank you
Special thanks to code contributors @drewangell, @mpldr, @snajafov, @PatrickGTR, and @Kapmeister for their feature, infrastructure, and bug-fix contributions.
Enormous thanks to our security researchers who reported vulnerabilities. All changes are listed in the CHANGELOG.md (github.com). Please read the CHANGELOG — there are some things you need to do if you have custom Invoice and Quote templates (instead of the default ones).
@0raN9ewww, @5ud0er, @akgul7990, @alanturing881, @alham-rizvi, @ali-iltizar, @ashrexon, @baozongwi, @capt-bl4ck0ut, @chakrapani150, @Char0n1507, @Chittu13, @cyabell, @de3erve-hunter, @EvidentObscurity, @FelipeSilvany, @FORIMOC, @geo-chen, @HuajiHD, @iiihaiii, @kitu232, @lighthousekeeper1212, @mattmumford-git, @0xMoError-22, @PLpaPLpa, @polybjorn, @QiaoNPC, @radoi-teodor, @Santoshkumarpuppala, @snajafov, @tikket1, @tonghuaroot, @udaypali, @venkatesh2003631, @vicrypter, @Vijay-raghav7
Security & Stability
InvoicePlane 1.7.2 is a security-focused release. It resolves every vulnerability responsibly disclosed against v1.7.0 / v1.7.1, plus everything found in follow-up review since. If you run v1.7.0 or v1.7.1, upgrade immediately — this release fixes a critical (CVSSv3 9.9) Remote Code Execution vulnerability among ~40 other issues.
Critical
- PR-1505, PR-1506 Remote Code Execution via the writable templates directory: replaced the filesystem-scanning template whitelist with static allowlist constants in
ipconfig.php, and fixed five related open-redirect instances. Reported by @Vijay-raghav7 (GHSA-v735-2x3r-gwpp). See CUSTOM_TEMPLATES.md (github.com) for the resulting custom-template setup. - PR-1514 Broken authentication: password-reset tokens never expired. Reported by @ali-iltizar (GHSA-5r28-6rw3-25c2).
High
- PR-1512, PR-1510 Arbitrary file deletion via path traversal in the invoice-logo setting. Reported by @ali-iltizar, @iiihaiii (GHSA-65v2-4g37-rxjw, GHSA-45vj-9p52-f8mq).
- PR-1494 Weak PRNG in password-reset token generation; replaced with
random_bytes(32). Reported by @tikket1 (GHSA-jfgr-778p-m943). - PR-1481, PR-1488 SQL/DDL injection via the tax-rate decimal-places setting. Reported by @tikket1, @udaypali, @FelipeSilvany, @akgul7990 (GHSA-x6rh-cr7q-5w7j and 3 more).
- PR-1513 Configuration injection in the database setup wizard (
db_hostname). Reported by @akgul7990 (GHSA-ffq5-mw9f-mv6j). - PR-1659 Unauthenticated database upgrade via an incompletely locked setup wizard. Reported by @FelipeSilvany (GHSA-pp5w-98m2-gvc8).
- PR-1471, PR-1482, PR-1487 IDOR + CSRF on guest quote approve/reject. Reported by @HuajiHD, @lighthousekeeper1212, @Santoshkumarpuppala, @cyabell.
- PR-1630 SQL injection via string concatenation in the Ajax
having()clause. Reported by @PLpaPLpa (GHSA-g7f2-mj3r-xx88). - PR-1615 Arbitrary local file read via mPDF
file://in the Sales-by-Year report. Reported by @tonghuaroot (GHSA-j89p-m59x-86r9). - PR-1616 Unauthenticated PayPal payment forgery — capture endpoint didn't validate currency/amount against the invoice. Reported by @tonghuaroot (GHSA-35qh-94hc-hm2w).
- PR-1560 Path traversal risk. Reported by @venkatesh2003631 (GHSA-9248-qccw-7x7j).
- PR-1556 Sensitive financial data exposure via unauthenticated public invoice access. Reported by @chakrapani150 (GHSA-9hx6-6h6f-2wq3).
- PR-1555 Authentication bypass via MD5 magic-hash type juggling. Reported by @geo-chen (GHSA-x66r-7wf6-wgv7).
- PR-1545 Guest attachment access bypass — missing authorization on the Get controller. Reported by @QiaoNPC (GHSA-phh5-3jc3-pm6w).
- PR-1621 Disabled users could still authenticate. Reported by @mattmumford-git (GHSA-jw57-6692-jh2q).
- PR-1620, PR-1623 Sensitive SUMEX XML / import CSV disclosure via web-accessible temp directories. Reported by @mattmumford-git (GHSA-583r-4pw9-6rc9, GHSA-wv2c-c285-9hrq).
- PR-1626 Authorization bypass (IDOR) through a user-controlled key. Reported by @0raN9ewww (GHSA-h4xh-4jwc-485r).
- PR-1559, PR-1561, PR-1622, PR-1624 Missing CSRF protection on state-changing delete / logo-removal actions. Reported by @mattmumford-git, @venkatesh2003631.
- PR-1567 XSS session hijack via
cookie_httponly=false— session cookies are nowHttpOnlyby default. Found in an internal audit. - PR-1668 Permanent account lockout: a bug in the failed-login counter made the 12-hour auto-unlock unreachable, so locked-out accounts stayed locked forever. Reported by @polybjorn (GHSA-cjwm-qx8w-hrq2).
- PR-1670, PR-1671 Password-reset token expiry wasn't enforced on the password-change POST (incomplete fix of GHSA-5r28-6rw3-25c2). Reported by @baozongwi (GHSA-fwj7-c84x-jvjq).
- PR-1681 Privilege revocation failure: a downgraded administrator retained administrative access via a stale session. Sessions are now invalidated the moment a user's role or active status changes. Reported by @0xMoError-22.
- PR-1684 Login rate limiting was session-scoped: an attacker omitting the session cookie got a fresh attempt counter on every request, defeating the anti-brute-force IP limit with zero prerequisites. Moved to the same database-backed counter already used for password-reset limiting. Reported by @Char0n1507 (GHSA-hcxg-3465-jc8m).
- PR-1684 GET-routable auth bypass:
Sessions::authenticate()was apubliccontroller method, so CI3 routed it directly at/sessions/sessions/authenticate/<email>/<password>via a bare GET — bypassing the login form, CSRF, and POST entirely, with credentials landing in the URL, server logs, and browser history. Now made unroutable (private) with a defense-in-depth POST check. Reported by @Char0n1507 (GHSA-x2m4-962x-cphw, GHSA-mwjf-mrp3-8r4x — duplicate report of the same issue). - PR-1684 Arbitrary
mkdir()via a mistakenly-public helper:Upload::create_dir()had the identical directly-routable shape as theauthenticate()finding above — reachable at/upload/upload/create_dir/<path>/<chmod>with an attacker-controlled path and permission bits passed straight tomkdir(). Found in an internal audit for other instances of that bug class; now made unroutable (private).
Medium
- PR-1658 Password-reset email flood: IP/email rate limits lived only in the PHP session, so omitting the session cookie bypassed them entirely; moved to persistent database-backed counters. Reported by @Char0n1507 (GHSA-p7w2-hmm5-qw7m).
- PR-1517, PR-1537 Auth bypass in guest invoice/payment endpoints. Reported by @FelipeSilvany.
- PR-1491, PR-1511, PR-1518 Setup wizard accessible post-installation. Reported by @HuajiHD, @iiihaiii, @kitu232.
- PR-1492 SSRF via admin-stored PDF footer HTML. Reported by @radoi-teodor (GHSA-vgq9-469p-q7j3).
- PR-1505 Open redirect via raw
HTTP_REFERERuse; fixed alongside the RCE work above. Reported by @Vijay-raghav7. - PR-1515 Payment gateway credentials in plaintext — Stripe/PayPal API keys no longer render into HTML source. Reported by @ali-iltizar (GHSA-8543-x4j8-jj4q).
- PR-1635 Stored XSS via client email in the invoice/quote mailer forms. Reported by @capt-bl4ck0ut (GHSA-477r-xmgc-vcvj).
- PR-1573, PR-1632 Second-order SQL injection via the unvalidated
custom_field_tablefield. Reported by @5ud0er, @capt-bl4ck0ut. - PR-1487 Unauthenticated GET-based quote approval/rejection — exploitable via email link prefetching. Reported by @de3erve-hunter (GHSA-7r3g-fppx-2p79).
- PR-1574 Stored XSS via CSV import (payment method name). Reported by @EvidentObscurity (GHSA-vm87-2qmm-rhg8).
- PR-1557 Invoice PDF passwords stored in plaintext. Reported by @chakrapani150 (GHSA-vphv-wmr3-68fp).
- PR-1516 Stored XSS in online payment settings. Reported by @ali-iltizar (GHSA-xvrc-hv8j-8v8w).
- PR-1547 Vulnerability report (InvoicePlane_001). Reported by @FORIMOC (GHSA-wj6q-j965-2w2v).
- PR-1567 Clickjacking, session fixation, and password-reset log injection — default
X-Frame-Options: SAMEORIGIN,SESS_REGENERATE_DESTROY=true, log sanitization, and aReferrer-Policyheader. Found in an internal audit. - PR-1640 Loose type comparison in the core
user_type/required_keyauth check (defense-in-depth). Reported by @Char0n1507 (GHSA-346c-gqqq-mrm2). - PR-1639 Log injection via unsanitized
cron_keyinCron::recur(). Reported by @Char0n1507 (GHSA-g53q-v2pv-xr83). - PR-1638, PR-1658 IDOR: any admin could change any other user's password; now restricted to the account owner or the primary administrator. Reported by @Char0n1507.
- PR-1637 CSRF on seven
delete()-style endpoints missing token validation. Reported by @Char0n1507, @vicrypter (GHSA-9372-vj68-hmc3). - PR-1636 CSRF bypass in
Recurring::stop()via a bare GET request. Reported by @Char0n1507 (GHSA-qf9q-2hxm-4wh9). - PR-1651 Guest invoice/quote access keys and the CRON authentication key now use cryptographically secure token generation instead of
random_string()/str_shuffle()/ Mersenne Twister; password-reset token comparison now useshash_equals(). Reported by @alham-rizvi (GHSA-chqc-v432-8pj8, GHSA-wcqc-qqv5-65ph). - PR-1660 Sensitive user fields exposed through email-template placeholders; templates now resolve only a documented allowlist of tags, and invoice/quote queries no longer select password hashes, salts, or reset tokens. Reported by @Char0n1507.
- PR-1661 SSRF via unescaped report PDF date parameters. Reported by @Char0n1507.
- PR-1663 SSRF via unrestricted
SUMEX_URLscheme, plus residual XML control-character/attribute injection and patient-PII exposure inSumex.php. Reported by @Char0n1507. - PR-1664 Missing CSRF protection on the bulk
recalculate_all_invoices()/recalculate_all_quotes()endpoints. Found in an internal audit. - PR-1674 CSRF:
generate_pdfmarked a draft invoice/quote as sent and assigned its official number via a plain GET request. Reported by @ashrexon (Yash Shendge). - PR-1684 Recurring-invoice cron race condition (TOCTOU): concurrent cron runs could double-generate the same recurring invoice and duplicate the customer email; the invoice is now claimed atomically before any side effects run. Reported by @Char0n1507 (GHSA-hvvh-fjx5-9j55).
- PR-1684 No rate limiting on wrong
cron_keyattempts against the unauthenticated cron endpoint; now IP-rate-limited. Reported by @Char0n1507 (GHSA-28fh-2656-wc63). - PR-1684 Stored XSS in the quote-status notification email:
email_quote_status()(fired when a guest approves/rejects a quote) built the email as unescaped HTML, so an admin-set client name containing HTML/JS would execute in a web-based email client. The same function also forceddisplay_errors/E_ALLon, risking leakage of SMTP credentials or stack traces into the response on a later mailer failure. Reported by @Char0n1507 (GHSA-prmc-vrjx-5hxc).
Low
- PR-1496 Duplicate payment processing (Stripe callback replay); a unique
payment_external_idindex now prevents it. Reported by @HuajiHD (GHSA-6cpc-hr8h-xgr2). - PR-1486, PR-1500, PR-1516 Email template preview XSS. Reported by @Vijay-raghav7 (GHSA-4wqv-84px-8jc6).
- PR-1507 EXIF metadata in uploaded images; optional stripping added (
SEC_STRIP_EXIF_FROM_IMAGES). Reported by @Vijay-raghav7 (GHSA-7j67-2v6p-275v). - PR-1583 Non-constant-time
cron_keycomparison in the recurring-invoice cron endpoint. Reported by @alanturing881 (GHSA-jg68-6mqc-hxcr). - PR-1495 PHPMailer debug output leaking into AJAX responses; now routed to the CI log with sanitization. Found in an internal audit.
- PR-1684 PayPal
order_idpath injection: an unvalidatedorder_idwas interpolated directly into the PayPal API request path incaptureOrder()/showOrderDetails(); now validated against a strict alphanumeric format. Reported by @Char0n1507 (GHSA-rf9w-hm5h-4gr2). - PR-1664 Unescaped logo filename in the PDF invoice header, and log injection via an unsanitized
checkout_session_idin the Stripe guest-payment callback. Found in an internal audit.
Improvements / Changes
Custom Templates & Configuration
- PR-1648 Custom template allowlist constants added to
ipconfig.php, making custom invoice and quote template selection explicit while preserving the no-filesystem-scan RCE fix. - PR-1652 Upgrade documentation corrected to state that
CUSTOM_TEMPLATES_FOLDERalone lists no templates; template names must be copied into the relevantipconfig.phpallowlist variable. - PR-1653 Custom template documentation clarified: administrators must provide both the template file under
CUSTOM_TEMPLATES_FOLDERand the matchingCUSTOM_*_TEMPLATESallowlist entry. - PR-1656 Administrators upgrading with selected legacy custom templates now get a targeted
/setupcompletion and Settings-page warning listing the saved custom template names and the exactCUSTOM_INVOICE_TEMPLATES_PDF,CUSTOM_INVOICE_TEMPLATES_PUBLIC,CUSTOM_QUOTE_TEMPLATES_PDF, orCUSTOM_QUOTE_TEMPLATES_PUBLICvariable to update.
Payment Processing
- IP-1677 Stripe zero-decimal currencies: Checkout Sessions now convert invoice balances using the configured currency's minor unit instead of multiplying every amount by 100. Callback validation, recorded payments, and merchant-response details use the same conversion, preventing JPY, KRW, CLP, and other zero-decimal invoices from charging customers 100 times the invoice total. Thanks to @snajafov.
- PR-1289 Re-introduced Stripe & PayPal, adding PayPal Advanced Credit Cards and Venmo support. Thanks to @drewangell.
Infrastructure
- PR-1509 Added a Docker application container (combined web server + PHP). Thanks to @mpldr.
- PR-1489 The QR-code size on invoices is now configurable.
Fixed
- PR-1665
Upload::delete_file()no longer reports a spurious "delete failed" error for a file that was already removed. - IP-1680 Cryptor binary-safety regression:
decryptString()had silently regressed tomb_strlen()/mb_substr()on raw binary ciphertext (reverted by an automated code-style pass), which could break SMTP authentication for affected users. Reverted to byte-safestrlen()/substr()and disabled the offending Pint rule so it can't be silently reintroduced. Thanks to @Kapmeister. - Session config bug:
sess_table_nameandsess_cookie_nameincorrectly read from theSESS_DRIVERenv var, making it impossible to rename the session cookie or table without also changing the driver name.
Full Changelog (since v1.7.1): https://github.com/InvoicePlane/InvoicePlane/compare/v1.7.1...v1.7.2