mlocati/ip-lib
A PHP library to parse, match, and manipulate IPv4 and IPv6 addresses, CIDR subnets, and address ranges, with support for wildcards, interval arithmetic, and network containment checks—useful for validation, access control, and IP math in any PHP project.
Architecture fit. Unchanged. mlocati/ip-lib remains a framework-agnostic, dependency-free PHP domain library owning one narrow concern: parsing, normalizing, and comparing IPv4/IPv6 addresses and ranges (CIDR, wildcard, and explicit start–end ranges). No service provider, facade, config, or migrations — which for a Laravel estate is a feature: no container bindings, no framework coupling, no constraint on our Laravel major version. It belongs beside our validation rules and authorization primitives, not in infrastructure. Highest-value insertion points are unchanged: request validation, trusted-proxy / X-Forwarded-For resolution, allow/deny lists, tenant-scoped IP range administration, audit-log IP normalization, and egress/SSRF guardrails. Release 1.22.1 does not alter the architecture or API surface — it is a patch release with no new features, no deprecations, and no breaking changes.
Integration feasibility. Straightforward, and materially safer than at the time of the prior review. 1.22.1 fixes six parsing/serialization defects that map almost one-to-one onto the failure modes we flagged: Subnet::asPattern() returning an incorrect end address, Pattern::toString() producing wrong output for IPv6 patterns with an IPv4-mapped prefix, Pattern accepting trailing text when parsing IPv6 reverse-DNS lookup names, and string parsing accepting trailing newlines. Those last two are the concerning ones from a security standpoint — lenient parsing is how validation bypasses and allowlist mismatches get into production. The net effect is that the library's correctness posture improved meaningfully in a single patch, and the remaining integration nuance is unchanged: parse methods return null on invalid input rather than throwing, so our conventions must treat "null means unparseable input" explicitly or we ship null-dereference bugs. Zero runtime dependencies continues to keep the transitive and security-review surface flat.
Technical risk. Intrinsic code risk stays low; the release is evidence-based rather than reassuring. Three observations:
unknown repository metadata in our supplied record all still stand: provenance verification, version pinning, and an internal mirror remain conditions of approval, not nice-to-haves."192.0.2.1\n"-style input and could serialize IPv4-mapped IPv6 patterns incorrectly. Pinning to a floating ^1.22 is insufficient policy — we should set the floor at >=1.22.1 so no environment resolves to a release with known parsing leniency. This is the single most actionable output of this release.Residual risk concentrates where it did before: trust boundary for forwarded headers, mixed persisted formats, and address-family normalization at ingestion.
Key questions.
TrustProxies correctly configured in every environment?Subnet::asPattern() on a prior version? Those rows carry an incorrect end address and must be re-derived, not merely re-read.Stack fit. Unchanged. Compatible with any modern PHP runtime and therefore with Laravel, Lumen, Symfony, and plain PHP services. The pragmatic pattern remains a thin internal adapter — an IpPolicy or IpRangeService — wrapping the library and exposing only the operations our domain needs: one place for caching, one place to enforce null handling, one seam to swap implementations. A minimal service provider plus config key can make config-driven allowlists first-class in Laravel, but remains optional.
Migration path. Unchanged in sequence, tightened at two points. Migrate in ascending blast radius: validation and normalization first, then audit/logging output, then containment checks in authorization paths, last any persisted range schema. Two amendments driven by 1.22.1:
\n and \r\n, IPv6 reverse-DNS names with trailing text, IPv4-mapped IPv6 addressed in both pattern and range form, and round-trip asPattern() → re-parse → end-address equality assertions. These are now known adversarial inputs, not hypotheticals, and belong in contract tests behind the adapter.Compatibility. Set the floor at >=1.22.1 and pin exactly in composer.lock. Verify the package's PHP constraint against our supported matrix; PHP version support has moved over the project's history. Watch 32-bit platforms, where integer-based handling silently breaks and where this library's string/object approach is the safer choice. Watch IPv4-mapped IPv6 from dual-stack listeners — better handled in 1.22.1, but the address-family normalization obligation at the ingestion boundary is unchanged. Watch data persisted in inconsistent formats: a normalization migration is likely required before containment checks can be trusted.
Sequencing.
asPattern()-sourced ranges.Maintenance. Low, and marginally lower after this release since known parsing defects are closed upstream rather than absorbed by us. Pinned version with quarterly review remains sufficient; 1.22.1 should be treated as an expedited patch rather than waiting for the review cycle given the parsing-leniency fixes. The real obligation is still governance: named code owner, recorded provenance verification, internal mirror so an upstream disappearance cannot block a deploy, and a documented fork-and-maintain contingency — credible precisely because the API is small. The release cadence and the hygiene PRs mildly strengthen the case that the maintainer is engaged, but single-maintainer concentration is unchanged and should not be argued away on the basis of one active patch cycle.
Support. No commercial tier. Reliance remains on GitHub issues and maintainer availability, which reinforces the adapter seam and internal coverage. Parsing defects route to the owning team. One improvement worth noting: the release shows defects being found, fixed, and reported transparently with linked PRs — a healthy signal for a project of this size, and a reason to keep the changelog in our dependency-review checklist.
Scaling. Unchanged. Parsing and containment checks are CPU-bound and cheap per call but not free in hot paths. Two concerns dominate: repeated parsing of identical range strings on every request benefits enormously from memoization or a cached parsed representation, and linear scans over thousands of ranges are O(n) per check — plan for sorted-range binary search or a precomputed structure rather than calling contains() in a loop. 1.22.1 introduces no performance-relevant changes.
Failure modes.
| Failure mode | Symptom | Mitigation |
|---|---|---|
| Null returned on unparseable input | Null dereference or, worse, default-allow | Adapter must convert null into explicit deny/validation error |
| Untrusted forwarded headers | Containment checks evaluate attacker-supplied addresses | Enforce trusted-proxy config and test per environment |
| Mixed persisted formats | Ranges that never match, silently | Normalization migration before enabling comparisons |
| IPv4-mapped IPv6 mismatch | IPv4 allowlist entries fail for dual-stack clients | Normalize address family at the boundary; fixed for patterns/ranges in 1.22.1 |
| Trailing newline / trailing text accepted | Malformed input passes validation; allowlist or denylist mismatch | Fixed in 1.22.1 — set version floor to >=1.22.1; do not rely on older pins |
Stale asPattern() output in storage |
Persisted ranges carry wrong end address | Re-derive rather than reformat during migration; assert round-trip |
| 32-bit host arithmetic | Overflow in legacy helpers still in the path | Remove integer-based handling; verify platform |
| Single-maintainer abandonment | No upstream fixes | Internal mirror plus documented fork path |
Ramp-up. Still measured in hours, not weeks. The API is small enough to learn from the README, and 1.22.1 adds no new surface to learn. The actual learning curve remains IP semantics — CIDR boundaries, address families, trust boundaries — knowledge the team needs regardless of library choice. Budget a short internal cookbook covering adapter usage, the null-handling rule, the trusted-proxy expectation, and now the version floor rationale. That last item matters: a future engineer who sees ^1.22 in a composer file and downgrades to dodge a lockfile conflict would silently reintroduce two of the defects this release closed.
Recommendation. Adopt behind a thin adapter, with version pinning at >=1.22.1, provenance verification, and an internal mirror as conditions of approval. 1.22.1 does not change the recommendation but strengthens it on two axes: it raises the correctness floor for a validation-path dependency, and it confirms — within a single minor cycle — that the identified IP-semantics risks were real rather than theoretical. Treat the upgrade as expedited and low-risk, and treat the release notes as the first entries in the regression fixture corpus.
How can I help you explore Laravel packages today?