With the recent upheaval from the newly discovered PHP vulnerability (often referred to as PHP2Shell), and updates to OpenTelemetry declarations, it struck me that it’s worth highlighting an assumption we all tend to make with patches.
We tend to think patches introduce fixes or defences that mean functional behavior is immutable. It is an understandable reading based on definitions such as Semantic Versioning (semver):
PATCH version when you make backward compatible bug fixes
However, languages and frameworks point towards a different model, where defined API behaviour will be respected.
The bottom line is if you’re exploiting undocumented behaviors, it makes it all the more necessary to test and ideally in an automated manner changes not only in the applications but also for the stack.
If you are taking advantage of undocumented behavior, then it is worth adding an abstraction layer to allow mitigation changes to be added.
The following identifies the statements at a language level relating to what impact a patch can have:
| Language / runtime | Behavior changes in patches | Breaking API changes in patches | Policy, limitations and supporting documentation |
|---|---|---|---|
| Go | Yes | Exceptional | Explicit security, unspecified-behavior and specification-correction exceptions. Go compatibility promise |
| PHP | Yes, for corrections | Generally no | Security and bug fixes permitted; public userland API must remain backward compatible. Internal ABI/API has narrowly defined exceptions. PHP release policy |
| Python (CPython) | Yes, restricted | Exceptional | Reasonable bug fixes may affect behavior; stronger incompatibilities require exceptional justification. PEP 387 |
| Java (OpenJDK / Oracle JDK) | Yes | Generally no | Security corrections can alter runtime behavior; source, binary and behavioral compatibility are evaluated separately. OpenJDK compatibility |
| C# / .NET runtime | Exceptional | Exceptional | Breaking changes generally prohibited during servicing, except for security vulnerabilities or other critical issues. .NET release policy |
| F# / .NET runtime | Exceptional | Exceptional | Shares .NET runtime servicing policies; compiler and language tooling have their own compatibility considerations. .NET compatibility rules |
| VB.NET / .NET runtime | Exceptional | Exceptional | Same underlying .NET servicing guarantees. .NET servicing |
| TypeScript | Yes, restricted | Not normally | Patch releases may contain high-priority regression, performance-regression and safe language-service corrections. Ordinary breaking changes are targeted at larger releases. TypeScript release process |
| JavaScript (ECMAScript) | Not applicable at language-specification level | Not applicable | ECMAScript is a specification, not a separately patched runtime. Behavior depends on implementations such as V8, SpiderMonkey, JavaScriptCore and Node.js. ECMAScript specification |
| Node.js | Yes, for corrections | Exceptional | Patch releases accept fixes; semver-major changes are excluded under normal procedures. LTS security exceptions can affect native API/ABI compatibility when unavoidable. Node.js release procedures |
The following table, takes the same approach looking at how operating systems view changes for patches:
| Operating system | Behavior changes in maintenance patches | Breaking API / ABI changes | Policy, limitations and supporting documentation |
|---|---|---|---|
| Red Hat Enterprise Linux (RHEL) | Yes | Generally avoided | Backports security and bug fixes into supported versions. Red Hat explicitly tests for unwanted side effects, so this is not general permission to break compatibility. RHEL security backporting |
| SUSE Linux Enterprise Server (SLES) | Yes | Generally avoided | Maintenance includes security corrections and defect fixes; individual components have different lifecycle rules. Service packs allow broader changes. SUSE support policy and SLES release notes |
| Oracle Linux | Yes | No general permission established | Oracle distributes security, bug-fix and enhancement errata as package updates. Security hardening can alter functionality independently of major OS releases. Oracle Linux errata policy |
| Ubuntu LTS | Yes, cautiously | Generally avoided | Backported security patches prioritize compatibility. Exceptional changes and certain feature updates can be accepted under the Stable Release Updates process. Ubuntu security updates |
| Debian Stable | Yes, restricted | Generally avoided | Important bug and security fixes are acceptable; updates are deliberately minimal and require review. Debian Stable update rules |
| Microsoft Windows 11 / Windows Server | Yes | No general permission established | Cumulative security, quality and out-of-band updates may change functionality. Windows 11 may also deliver feature enhancements through monthly servicing. Windows update release policy |
| Apple macOS | Possible | No general permission established | Security and maintenance releases can affect operating behavior, but there is no general published patch-version exception equivalent to Go’s. Apple security releases |
Often when building solutions we don’t see low level frameworks and how they work, so we may not know about any undocumented feature exploitation.
The challenge it can bring
This points to increased testing, which ideally is automated. The reaction is initially is so what. But, when vulnerabilities like PHP come up which had openly triggered systems being disconnected from the net.
So extending testing (even if automated) is going to experience resistance from the commercial parts of an organization who are unlikely to understand the nuances, but will react to headlining risks.
How do we move forward?
There are some strategies we can adopt that can help us. The industry used to talk about security in depth and, more recently, system resilience. Regardless of terminology, we want to introduce control layers that reduce the chance of malicious intent. Often referred to as compensating controls.
For example, if the vulnerability is overloading the runtime by sending an oversized payload, a firewall or proxy layer can have rules that prevent payloads from being too big from hitting the backend.
If the networking allows it, then segmenting the network reduces the risk of a breach affecting other environments.
This doesn’t mean if we can patch, that we shouldn’t. What it does mean is we can be considered and not knee-jerk panic and unwittingly introduce new problems.
Conclusion
Adding additional security and proxy layers and segmenting system environments may seem like overkill, particularly when introducing new systems. But these steps create the means to be far more resilient.