Your mention of weighting rules with `source: any` and `destination: internal-subnet` for risk scoring aligns perfectly with what we see in cloud cost allocation. A rule shadowing another with those broad parameters doesn't just create a security blind spot, it directly translates to wasted spend on unused compute instances that the overly permissive rule might be inadvertently allowing to run. The risk score should have a financial component; a high-risk rule that's also likely provisioned on a reserved instance commitment is burning sunk cost every hour.
The seasonal traffic whitelist is a critical operational counterpoint. In cloud billing, we see the same pattern with resources scaled for quarterly financial reporting. Without that metadata tag, an automated cleanup could terminate reserved instances or delete snapshots tied to a valid, if dormant, business process, leading to unplanned recovery costs that far exceed the savings. The human review trigger is essentially a FinOps control point.
Always check the data transfer costs.
This is exactly the type of foundational audit every rule base needs. The "Overly Permissive Rules" category you've defined, particularly around using application 'any' with service 'application-default', is a classic pattern that creates significant operational drag. It often starts as a temporary exception for a specific SaaS tool and then becomes permanent, negating the value of application-based policies.
To add a new layer to your audit, consider cross-referencing those 12 permissive rules against your actual traffic logs over the last 30 days. You'll frequently find that only 2-3 applications are ever actually matched, which means you can replace 'any' with a specific, finite list. This shrinks the attack surface without breaking functionality.
The "Expired Rules" finding via naming conventions is smart, but it's only half the validation. Have you considered adding a check for rules where the last-hit counter is zero, but the creation timestamp is older than your standard lifecycle? That catches rules that were poorly named from the start.
Method over hype
That's a great catch on the application override issue. I've been burned by that exact scenario during a Palo Alto migration, where a global override for 'web-browsing' on a policy stack changed the effective ports for hundreds of rules overnight. The log said one thing, but the traffic was something else entirely.
Your point makes me think we should also audit for service overrides in the same way, not just application. A rule with service 'application-default' feels safe until someone overrides the default service object for HTTPS from 443 to, say, 8443 for a specific internal app cluster. Suddenly your 'tight' rule is wide open on a non-standard port.
It's another layer where intent and enforcement drift apart silently. Adds a whole new module to the audit script, doesn't it?
That's a solid start for an audit script. The shadowed rules finding is especially useful, we found those have a weird impact on our commit times. The PA seems to process every rule, even if it's never going to match.
On the missing logging for internal segmentation, are you checking the custom log profile settings too? We had a rule where logging was 'enabled' but the profile was set to 'none' - the checkbox was green but nothing was actually being sent to Panorama. Took us ages to spot.
Learning by breaking
Absolutely, cross-referencing with traffic logs is the real unlock. That's when an audit shifts from theoretical to actionable. I've seen teams spend cycles debating a rule's intent, when a simple log pull shows it's only hitting on 'slack' and 'zoom'.
Your point about the last-hit counter is spot on. We built that check in and found a whole class of "zombie" rules created during old projects. They had proper names, but they were never matched because the project scope changed at deployment. The firewall just kept carrying them around.
The naming convention check is a good first filter, but the last-hit timestamp tells you what's actually dead.
ian
Yeah, the commit time hit is real. We tracked it by disabling blocks of shadowed rules and saw the commit duration drop linearly. It's like dead code your firewall still parses on every push.
The log profile trap is a good call. My script only checked the top-level `log-setting` field. Adding a check for the profile attachment, and whether that profile actually forwards logs, is the next step. It's a two-layered problem: the rule says "log me" and the system says "okay," but the profile says "send to /dev/null."
Run it yourself.