r/PHP • u/Tomas_Votruba • 16h ago
r/PHP • u/brendt_gd • 1d ago
Weekly help thread
Hey there!
This subreddit isn't meant for help threads, though there's one exception to the rule: in this thread you can ask anything you want PHP related, someone will probably be able to help you out!
r/PHP • u/brendt_gd • 8d ago
Weekly help thread
Hey there!
This subreddit isn't meant for help threads, though there's one exception to the rule: in this thread you can ask anything you want PHP related, someone will probably be able to help you out!
r/PHP • u/DrWhatNoName • 15h ago
Video How the "Steal My Bitcoin" challenge was solved - It was really 2 hours.
youtube.comTL;DR for the first 26 hours the page was a static html page being served by php. After the challenger author was informed that if there is no php code php doesn't execute, the author added a phpversion() script.
After this became exploitable it took 2 hours for someone to hack the server and steal the bitcoin.
r/PHP • u/sprain_mr • 18h ago
Swiss campsite operator reports data theft linked to PHP2Shell
srf.chExcerpt translated from German:
In connection with the global security vulnerability in the PHP programming language, TCS Camping is warning around 15,000 customers: the provider of "Camping.Care", the booking system used by TCS, has been hit by a data theft. As the TCS confirmed […], fraudsters were able to steal customer and booking information.
r/PHP • u/Reasonable_Green7254 • 23h ago
Should regular users do anything after the recent PHP vulnerability?
With the recent PHP vulnerability, I've been wondering if there's anything I should do as a regular user. Specifically, should I be changing my passwords or taking any other precautions?
Also, is signing up for Have I Been Pwned enough to stay informed about data breaches and leaked passwords?
I've heard that some people also use Google's built-in Password Manager, which can notify you if any of your saved passwords have been compromised. However, I'm not really comfortable with the idea of storing all my passwords with Google.
What do you guys recommend? Is HIBP enough, or are there any other steps worth taking?
Or am I overthinking this, and should I just leave things as they are for now and wait for notifications from HIBP or emails from any affected services?
Thanks!
r/PHP • u/Big_Muffin8280 • 1d ago
Which PHP tools or practices made the biggest difference to your code quality in the last 2 years?
Static analysis, formatters, typed properties, enums, readonly classes, attributes, Pest or PHPUnit, mutation testing, there’s a lot to choose from.
- Which single tool or feature changed your day-to-day work the most?
- What did you adopt that turned out not to be worth the effort?
- How did you introduce it into an existing codebase without a huge rewrite?
- What would you add first to a legacy project today?
Examples with before and after (bugs caught, review time saved) help most.
r/PHP • u/dereuromark • 1d ago
Discussion Carve: a markup language with a native PHP engine and Laravel, Symfony and WordPress integration
Hey folks. I have been building Carve, a modern lightweight markup language for content that outgrows Markdown (and Djot). For humans and agents working on the same docs.
After many months of specs and coding, it should finally be stable enough now.
PHP 8.2+, zero runtime dependencies, PHPStan level 9.
composer require markup-carve/carve-php
What it looks like
/italic/ *bold* _underline_ =highlight=
{#fig-sun}

^ Figure #: A sunset
See </#fig-sun> for the colors.
Unlike Markdown, *text* is bold and /text/ is italic. The figure gets its number, and the reference becomes a link reading "Figure 1".
Tables with merged cells and captions, footnotes, admonitions and definition lists are part of the core language. Diagram fences are an optional extension; without a renderer, they remain code blocks.
For example, ^ makes “Team” span two rows, while > right-aligns Seats and Price:
|= Plan |=> Seats |=> Price |
| Team | 25 | $49 |
| ^ | 50 | $89 |
Personally, I like and use this a lot, as I (or agents) don't need to fall back to HTML anywhere anymore.
Task lists - and they can track more than open and done:
- [x] Draft the API guide (done)
- [ ] Drop the old endpoint example (open)
- [!] Migration notes need an API decision (blocked)
- [/] Finish the screenshots (in progress)
to name a few.
I wrote a post about some of the killer features and things other markup can't do (written with the PHP library - source markup of that blog post linked at the bottom).
But for more context also check out the other articles.
Why it might be interesting for your PHP app
- Intuitive for non-techies. Feature-rich for power-users (like technical bloggers).
- Safe for web-based user content. Pasted HTML renders as text, and safe mode also escapes or strips raw HTML blocks and removes event handlers and
javascript:links. Profiles control which features each role may use. That said: Use sanitizers on top just in case. - One source, several outputs. The same document renders to HTML (with a static mode for print/PDF), Markdown, plain text or terminal output from one AST, and the same markup writes reveal.js slide decks.
- Works with rich-text editors. Documents convert to and from Tiptap/ProseMirror on the server, no Node needed.
- Migration path. Import existing Markdown, HTML, Djot or BBCode. The migration CLI can report conversion losses for review.
- Tooling. Formatter, linter, and editor support for PhpStorm, VS Code and others, plus a language and MCP server.
Some small facts or wins along the way:
- Conversion fidelity: in 66 pandoc round-trip probes, Carve (via the pandoc-carve bridge) brings back 64 unchanged; Markdown manages 46, HTML 44, DOCX 23 (pandoc-format-fidelity). In other words: Its the textual format that can best keep structural content.
- Hardened: fuzzed, and nesting is capped so hostile input cannot exhaust the server. You don't want 50s loading time on some `[[[[[[[[[` input or alike.
Framework packages
- Laravel:
markup-carve/laravel-carve(Blade directives, validation rule, render cache) - Filament:
jeffersongoncalves/filament-carve(community; editor field with preview, infolist entry, table column) - Symfony:
markup-carve/symfony-carve(bundle with Twig filters) - CakePHP:
markup-carve/cakephp-carve(helper,.crvviews, validation, ORM behavior, commands) - Tempest:
markup-carve/tempest-carve(safe-by-default view component) - WordPress: Carve Markup plugin (posts, comments, live preview)
- Shopware:
markup-carve/shopware-carve(6.6/6.7: Twig filters, CMS elements, product and category fields, mail templates)
Live demos: Laravel, Symfony, CakePHP, Tempest.
Not just PHP
There are also JavaScript and Rust engines, with Python, Ruby, Go and WebAssembly bindings on top of the Rust one.
I built it for documents that need more structure than I could comfortably write in Markdown. Without HTML workarounds and especially without inline HTML everywhere possible. And for online usage with a fair amount of native features. If you work with user-written content, I would especially like to hear what you think about this, or if there is something I missed.
Thinking about some next major topics I would like to get some feedback on:
- Should it be more "djot"-like with simpler block structure? It sure would make the parser simpler. Humans usually prefer the MD style I assume.
- Are some of the new language features making it too complicated? Overloading concise tables with inline alignment - or the `+` continuation operator to make human input easier?
Links
- Spec & Playground: https://github.com/markup-carve/carve
- PHP engine: https://github.com/markup-carve/carve-php
- PHP sandbox: https://sandbox.dereuromark.de/sandbox/carve
- Awesome list / ecosystem: https://github.com/markup-carve/awesome-carve
r/PHP • u/ICanEditPostTitles • 2d ago
Hackermews member challenges you to successfully exploit php2shell on his server
news.ycombinator.comThe DOOM showcase, written in PHP and compiled with Elephc, has evolved quite a bit
You can watch a video of it in the project's README: https://github.com/illegalstudio/elephc
News PHP Foundation 'Under-funded' With One Full-time Staff Member, Director Says
developers.slashdot.orgr/PHP • u/NeelbyteWeb • 18h ago
After years of living in legacy hell, we finally upgraded production to PHP 8.2. Am I safe to sleep now, or is the server going to combust tomorrow?
r/PHP • u/[deleted] • 20h ago
Laravel with Docker Compose: Five Infrastructure Mistakes Worth Avoiding
blog.ifirestone.devService names, Postgres healthchecks, a scheduler without a cache table, queues and migrations on deploy: the mistakes that show up when taking Laravel to Docker Compose and how to avoid them.
Taking a Laravel application to Docker Compose seems trivial until the first deployment fails for reasons that aren't in your code. These are five infrastructure mistakes I found while debugging real projects, with the symptom, the cause and the fix.
r/PHP • u/Low_Lawyer_5684 • 1d ago
Compile-time file inclusion
Hello everyone!
Have you ever been to situation when you miss C-style `#include` in PHP? I.e. a directive that simple inserts contents of a file at compile time
r/PHP • u/Alarmed-Dog-9141 • 2d ago
Plot twist: php2shell was just a ploy to get people onto newer versions of PHP
Obviously just a stupid satirical post, but a plot twist of php2shell just being a ploy to get people to update their PHP versions would be funny. :)
r/PHP • u/Own-Equipment-5454 • 1d ago
Discussion Plain PHP on shared hosting in 2026: request-time migrations, a file-cached GitHub stats proxy, and the corner I know I cut
I build and run onllm.dev, my studio site and blog, and the rebuild went live on 24 October. Plain PHP (7.4+) and MySQL behind Apache rewrites on Hostinger shared hosting. No framework. Most of the site is static HTML; PHP only handles the blog, comments, the contact form and a few endpoints.
Three parts I would like opinions on.
Migrations run on request. Anything that touches the database includes db.php, which calls the migrator. A file in the temp directory stores how many migration files existed at the last good run. In the common case that is one file read and no query. When the count changes, the runner applies pending files in order and records each name. If one fails, the runner deletes the file and throws; the caller logs it and lets the request carry on, so the next request tries again.
That file is a skip check, not a lock. Two cold requests can both see a changed count and both start migrating. Most migrations use IF NOT EXISTS, so a second pass does nothing. One is a bare ALTER TABLE ADD COLUMN, so a second pass would error, get logged and be swallowed. The page still loads, but that is luck, not a guarantee in the runner. MySQL's GET_LOCK() would close the gap with a few lines.
GitHub stats go through a file cache. api/github-stats.php adds up release asset downloads across paginated releases, reads container pull counts from the GHCR package page (as far as I can tell there is no API for those), and writes the JSON to a file with a five-minute TTL. Without it, every visitor would spend the unauthenticated GitHub rate limit. The numbers it serves right now: onWatch at 758 stars, 19,730 release downloads and 46,450 container pulls.
llms-full.txt is built from the page and the database. It loads index.html into DOMDocument, pulls the product and service copy out with XPath, then appends every published post from MySQL. If the database is down it returns 503 with Retry-After instead of half a file.
Laravel would solve the first two for me. migrate --isolated takes an atomic lock so only one process runs migrations, and its cache layer would replace the hand-rolled file cache. For a site this small on shared hosting, running migrations on request was the simplest thing that worked.
The generated output: https://onllm.dev/llms-full.txt
Two questions. Is GET_LOCK() worth adding at this traffic, or is it enough to make that one migration idempotent and keep the skip file? And is reading pull counts off the GHCR HTML as fragile as it feels?
r/PHP • u/technojoe99 • 1d ago
Discussion Is PHP FPM inside chroot now worth the effort?
Years ago, I setup my server's php-fpm inside a chroot, just to be extra safe. Many blog posts from the time said they either do not bother or use containers instead. I'm wondering if php2shell changes things, especially since AI might find other security holes.
What do you use in a post-php2shell world? containers? chroot? something else? And why?
Also, let me know if you're interested in how I set mine up.
r/PHP • u/linuxpert • 1d ago
PHP2Shell: We could have handled this better (Why was the mitigation guidance not released earlier)?
First, thanks to everyone who spent 2 months working on this vulnerability, developing the patch, and coordinating the disclosure. The effort is appreciated.
That said, I think the incident highlights a serious flaw in how we handle vulnerability disclosures. Many operators were left with little practical choice but to disable PHP or accept the risk while waiting for the technical details and patch. The frustrating part is that there were configuration changes in php.ini that could help mitigate the exploit, yet this guidance was not provided ahead of the public disclosure and patch release. I'm not suggesting that the vulnerability details or exploit instructions should have been released earlier. I'm saying that mitigation guidance should have been.
The current process is missing a step. As I understand it, the process had two stages:
Advance warning: An alert about an upcoming serious vulnerability, roughly one week before disclosure.
Public disclosure: Release of the vulnerability information and patch
The first stage gives administrators advance notice, but without actionable mitigation guidance, there isn't much they can safely do beyond preparing for the worst. Some operators may decide to disable PHP altogether before the public disclosure, even when a less disruptive mitigation could have reduced their exposure.
I believe we need 3 stages, with the mitigation guidance released at least one week before the full disclosure and patch. A better three-stage process:
Alert operators that a serious vulnerability is coming: Notify the community that a critical vulnerability is being addressed, identify the affected versions as far as safely possible, and provide an expected disclosure date. This gives hosting providers, developers, and system administrators time to prepare their response.
Publish mitigation guidance at least one week before disclosure (this is the missing step): Provide the relevant php.ini configuration changes that can mitigate the exploit, along with instructions on how to apply them and any known compatibility implications. This does not require publishing the root cause, the vulnerable code path, a proof of concept, or the details needed to construct an exploit. The mitigation guidance should be specific enough to be useful, but limited to what administrators need to protect their systems. It should also explain the limitations of the workaround, so nobody mistakes a mitigation for a complete fix.
Release the patch and full technical disclosure: Publish the patch, complete technical details, affected version information, and upgrade instructions. At this point, administrators who applied the recommended configuration changes have already had time to reduce their exposure. They can then deploy the permanent fix and review the full disclosure to determine whether further action is necessary.
Why this matters?
For operators managing production infrastructure, the difference between having a mitigation and having no mitigation can be enormous. Disabling PHP may be a reasonable emergency response for some systems, but it can also take websites, applications, and business operations offline. If a configuration change can reduce the risk without causing that level of disruption, operators should have the opportunity to apply it before the vulnerability becomes public. Of course, configuration changes are not guaranteed to eliminate every attack path. Their effectiveness depends on the vulnerability, and they may introduce compatibility issues. Some vulnerabilities may have no reliable configuration-based workaround at all. But in this case, configuration settings that could help mitigate exploitation existed. The question is why that guidance was not made available earlier, when it could have helped operators prepare without requiring them to understand the vulnerability itself.
The goal of coordinated disclosure should not simply be to keep technical details secret until the patch is ready. It should also be to give defenders the best possible chance to protect their systems during that period. This is not a request to disclose vulnerabilities earlier. I support responsible disclosure. Releasing technical details prematurely can give attackers an advantage, especially when a patch is not yet available.
The first two stages could even be combined when the mitigation is ready at the time of the initial alert. The important requirement is that actionable mitigation guidance reaches operators at least 2 days before the public release of the technical details and patch.
For future critical PHP vulnerabilities, I would like the disclosure process to explicitly include:
- An advance warning with an expected disclosure date.
- A separate, coordinated release of safe and actionable mitigation guidance, ideally at least one week before public disclosure.
- A clear statement when no reliable interim mitigation exists.
- A patch release with full technical details and upgrade instructions.
Thanks again to everyone who put in the work to investigate and fix PHP2Shell. This isn't about dismissing that effort. It's about recognizing that the response could have done more to protect the people running PHP in production.
r/PHP • u/CheesecakeBrief7795 • 2d ago
Patching PHP2Shell on EOL PHP 7.1 / CentOS 7 by rebuilding the Webtatic RPMs (what worked, what bit us)
TL;DR:* ported upstream 712e60f9ed into the Webtatic php71w 7.1.33 SRPM, rebuilt on a CentOS 7 container, ~35 min to build, ~6 s of php-fpm downtime per host. Two gotchas at the bottom.
Someone in the earlier PHP2Shell thread asked if Ondřej's backports are Debian only. They are, and that was our problem. We still had a couple dozen CentOS 7 boxes on Webtatic 7.1.33, Webtatic has been dead for years, and the PHP 8 estimate for just one of the apps was 6 to 8 person-days. So we rebuilt the packages ourselves. Writing it down because I couldn't find anyone who had done it for Webtatic.
The patch. Upstream's fix for old branches is php-src 712e60f9ed ("Avoid state corruption via bailout"). It doesn't apply to 7.1 cleanly. I diffed four community 7.1 ports against upstream and Qsnh/php2shell-fixed was the closest. Sury's Debian patches depend on another one of his patches to even compile, so I skipped those.
The gist: an OOM in the allocator now kills the worker with _exit(1) instead of jumping back with half-built state, upload_progress is hard-disabled, rfc1867.c only keeps the part headers it needs and gets a max_multipart_body_parts limit, and request shutdown clears some globals.
I changed one line in the port. Codex caught it when I had it read the diff, then I checked the 7.1 source:
diff
+/* 7.1 hash part is nTableSize uint32 slots (7.3+ uses 2x); keep >= 2 so Buckets stay 8-byte aligned */
#define array_init_singleton(arg) do { \
array_init(arg); \
- Z_ARRVAL_P(arg)->nTableSize = 1; \
+ Z_ARRVAL_P(arg)->nTableSize = 2; \
} while (0)
The build. podman centos:7 container (gcc 4.8.5) pointed at the vault repos. Verify the Webtatic SRPM signature and that the tarball inside matches php.net's sha256, then four spec edits:
Release: 1%{?rcver:.%{rcver}}%{?dist}.php2shell1
Patch400: php-7.1.33-php2shell-cve-2026-109618-109619.patch
%patch400 -p1 -b .php2shell
+ a %changelog entry
yum-builddep -y --define 'dist .w7' SPECS/php71.spec
rpmbuild -bb --define "dist .w7" SPECS/php71.spec
First run died on make: command not found because yum-builddep doesn't pull it in. Around 35 minutes of rpmbuild, the Webtatic spec builds several SAPIs. You get 33 RPMs, all 7.1.33-1.w7.php2shell1, and since 1.w7 sorts below that, a later yum update won't quietly undo it.
Testing. No public RCE PoC. I wrote a small checker instead:
- 3000-field multipart should hit the parts limit
- a 1 MB upload should still arrive intact
- upload_progress shouldn't land in the session
- OOM at memory_limit=32M should kill the worker (unpatched just says "Allowed memory size" and keeps going)
- requests after that still return 200
Original 2/5, patched 5/5, back to 2/5 after rollback.
Then the php.net test suite, 9,454 tests against the installed packages:
| Build | Passed | Failed |
|---|---|---|
| original 1.w7 | 8,751 | 34 |
| patched | 8,742 | 43 |
The 9 new failures are 8 rfc1867 session tests plus one that expects the old OOM message, all expected. The port author reports the same 9.
Rollout. Save rpm -qa, pull the original NEVRAs from a Webtatic mirror so you can roll back, then:
yum --disablerepo='*' --assumeno upgrade ./php71w-*.rpm # must say only "Upgrade N Packages"
systemctl stop php-fpm
yum -y --disablerepo='*' upgrade ./php71w-*.rpm
php-fpm -t && systemctl start php-fpm
php-fpm was down about 6 seconds, the whole thing was 2 to 7 minutes a host with checks. Rollback is yum downgrade from the saved originals.
What bit us:
- The spec resets
/var/lib/php/session(and wsdlcache, opcache) toroot:apache 770on upgrade. Our pools don't run as apache, sosession_start()broke for about 4 minutes on one box before we chowned it back. My container test missed it because the test pool did run as apache. Write down the owners first. - WorkerMan kept running the old binary,
/proc/<pid>/exeshowed(deleted). Restart your long-running CLI stuff too.
For 7.4 I didn't build anything. exception0x876's php74-el7 packages are a Remi 7.4.33 rebuild with the same upstream commit. I checked their signed SHA256SUMS and diffed their SRPM against Remi's before trusting it.
This only closes this one CVE pair, 7.1 is still 7.1. It just gave us time to do the upgrade properly.
r/PHP • u/taras_chr • 2d ago
manticore-fmt: a fast PHP formatter compiled to a native binary
For years I've used PHP-CS-Fixer on both personal and commercial projects. I like its ruleset, but I also like how fast Mago is.
So when I started working on a PHP compiler, I decided to build a formatter that follows PHP-CS-Fixer's rules and runs at a speed comparable to Mago's. It's written in PHP and compiled with the Manticore compiler, so there's no PHP runtime to install.
It's early (v0.1.x), so it may be unstable. Bug reports with a small snippet are very welcome.
r/PHP • u/shinsenter • 2d ago
News Update shinsenter/php images now
The shinsenter/php Docker images were recently rebuilt and patched to fix two critical PHP vulnerabilities (CVE-2026-109618 and CVE-2026-109619) enabling unauthenticated remote code execution via memory corruption in out-of-memory error handling.
Update your images immediately!
👉🏻https://hub.docker.com/r/shinsenter/php