Actually, I blame WordPress even for most plugins’ security vulnerabilities, because its chosen architecture makes them much more exploitable than they should generally be.
There’s also the problem that WordPress builds upon and relies heavily on being able to modify its own code. Although this does allow you to reliably do things like unattended automatic updates, which would probably be net good (normally improving things, though occasionally harming), it also means that even the slightest security vulnerability tends to become immediate total server takeover. This is why I blame WordPress core architecture more than individual plugins: in most ecosystems, most security bugs apparent in plugins wouldn’t be so exploitable. This design decision is probably responsible for most WordPress site hijackings (… which are very common). Taking all things into consideration, I suspect that going read-only file system and not supporting installing/updating/removing any code via its web interface would probably be good for WordPress’s security, despite it meaning most sites would never be updated—but it would certainly harm its ease of use, and I can easily see why it’s basically a non-starter.
By contrast, choosing another PHP system as an example (since it’s one of the few popular languages that particularly supports this kind of self-modification), last time I dealt with Drupal (back in 5 and 6 days), it would actively complain if it could write to its own directory, urging you to make all but the directory it uploaded user files to read-only to the web server user account. Updates were then done out-of-band, using your user account on the machine which had write access to replace the files, rather than the web server’s account. (There were manual steps involving the web interface and local file operations, or tools like Drush to make it a single command.) Bad for ease-of-use, excellent for security.
I haven’t had much to do with WordPress, but I gather storing executable PHP code in the database is also fairly common, which is almost worse than having a writeable file system. My vague recollection of Drupal is that although it supported “PHP code” as a content type, you had to turn it on in the config file, where it warned you of the vulnerabilities this opened.
(My qualifications in this comment: I’ve helped recover several hijacked WordPress instances, mostly around 2015 and 2022; migrated one business off WordPress in 2022; done almost nothing else ever with WordPress; worked fairly extensively with Drupal 5 and 6 on a few sites quite a few years ago; worked a fair bit with Django over the years, and some in other web frameworky things in Node.js and Rust; haven’t done anything serious with PHP for years now, preferring Python, JavaScript and Rust. Certainly don’t trust me for any insights into WordPress. I could easily have made errors in this comment.)
> last time I dealt with Drupal (back in 5 and 6 days), it would actively complain if it could write to its own directory,
That's great, but if you remember drupalgeddon, the attack vector (sql injection) used the url routing system, which very conveniently would map a path to any php function + arguments. Ugh.
SQL Insert a call to php's eval + the code of your choice as the args and voila, SQL injection becomes rce instantly.
I can understand a CMS having read write access to the database, the main benefit is to update the content of course. But mapping paths to executable code, straight into the database is a highly dubious choice.
I completely agree that the problems associated with the plug-in ecosystem arise as a result of design choices in core WordPress.
It’s not just technical API design, though — it’s also business logic and community architecture. WordPress didn’t stay a blogging engine, but became an everything platform, with plugins needed to fulfill vastly expanded ambitions. The inadequacies of the extensibility design have much more severe consequences when stretched to encompass such sprawling scale and scope.
There’s also the problem that WordPress builds upon and relies heavily on being able to modify its own code. Although this does allow you to reliably do things like unattended automatic updates, which would probably be net good (normally improving things, though occasionally harming), it also means that even the slightest security vulnerability tends to become immediate total server takeover. This is why I blame WordPress core architecture more than individual plugins: in most ecosystems, most security bugs apparent in plugins wouldn’t be so exploitable. This design decision is probably responsible for most WordPress site hijackings (… which are very common). Taking all things into consideration, I suspect that going read-only file system and not supporting installing/updating/removing any code via its web interface would probably be good for WordPress’s security, despite it meaning most sites would never be updated—but it would certainly harm its ease of use, and I can easily see why it’s basically a non-starter.
By contrast, choosing another PHP system as an example (since it’s one of the few popular languages that particularly supports this kind of self-modification), last time I dealt with Drupal (back in 5 and 6 days), it would actively complain if it could write to its own directory, urging you to make all but the directory it uploaded user files to read-only to the web server user account. Updates were then done out-of-band, using your user account on the machine which had write access to replace the files, rather than the web server’s account. (There were manual steps involving the web interface and local file operations, or tools like Drush to make it a single command.) Bad for ease-of-use, excellent for security.
I haven’t had much to do with WordPress, but I gather storing executable PHP code in the database is also fairly common, which is almost worse than having a writeable file system. My vague recollection of Drupal is that although it supported “PHP code” as a content type, you had to turn it on in the config file, where it warned you of the vulnerabilities this opened.
(My qualifications in this comment: I’ve helped recover several hijacked WordPress instances, mostly around 2015 and 2022; migrated one business off WordPress in 2022; done almost nothing else ever with WordPress; worked fairly extensively with Drupal 5 and 6 on a few sites quite a few years ago; worked a fair bit with Django over the years, and some in other web frameworky things in Node.js and Rust; haven’t done anything serious with PHP for years now, preferring Python, JavaScript and Rust. Certainly don’t trust me for any insights into WordPress. I could easily have made errors in this comment.)