Security means limited access, and the access limits have to be simple to define and universally valid.
It is ostensibly easy to configure a web server to do the following, "Only give outside access to this HTML form and the result page."
But because of the various layers involved in a web form and result page, a person intent on gaining more access might inject some clever SQL that writes a file containing some script to the disk. Then they could request the server pull up that file, and gain control of a whole lot more than was intended.
Although it was simple to define the access limits in the example, they were not universally valid due to the complexity of the application stack.
It is that complexity that makes security such a difficult endeavor. It is beyond a single developer's ability to foresee all the ways in which people will abuse their creations. And even some foreseen threats must be left unaddressed due to various constraints.
Imagine a building contractor hired to create a house that not only stood up to the wind and rain, but also was safe against every sort of bulldozer, wrecking ball, tank and bomb that other human's can construct.
Designing secure software is less like designing a building and more like designing crumple zones for automobiles. People will destroy the machine. The hope is for a graceful wreck where the important parts come out intact.