Patterns from this week's pentests

Every Friday, our offensive team collects the week's engagement notes into a shared channel and looks for the shape: not individual findings, but repeating structure across unrelated targets. This week the pattern was unusually clean: the same three failure modes surfaced in a fintech API, a healthcare tenant portal, and an internal HR platform, none sharing a codebase or a vendor. When the same bug class appears in three environments in five days, it becomes a defensive priority. Here is what we saw, mapped to the advisories that landed the same week (AV26-796 through AV26-805, covering Grafana, HashiCorp, Commvault, AMD, Rapid7, Siemens, Red Hat, and Ivanti), and what to change on Monday.

Pattern 1: Identity-provider trust boundaries collapsing under federation

Three engagements this week ended in full tenant takeover through the identity layer, and none required an exploit against the IdP itself. In each case the target had wired an external OIDC provider into an internal application and trusted a claim it should not have. The clearest example: an application used the email claim as its primary user key, but the IdP permitted self-service account creation with unverified addresses in partner tenants. We registered admin@target-corp.com in a tenant we controlled, minted a valid signed token, and the downstream application mapped it straight onto the real admin account.

This is the same failure class the industry has been fighting for years. CVE-2023-25690 (mod_proxy request smuggling) and CVE-2020-13699 (screen-sharing token reuse) both stem from treating signed or structured input from a trusted intermediary as authoritative. The token was fine. The trust boundary was not.

The fix is small:

# BAD: trust the email claim as identity
user = User.objects.get(email=token["email"])

# BETTER: bind to the (issuer, subject) pair, and only use
# email as a display attribute after a verified-claim check
if not token.get("email_verified"):
    raise AuthError("unverified email claim")
iss, sub = token["iss"], token["sub"]
user = User.objects.get(idp_issuer=iss, idp_subject=sub)

If you accept federated identity, document every claim you consume and the exact guarantee the IdP makes about each one. Wherever the guarantee is weaker than the trust you place in the claim, you have a finding.

Pattern 2: Server-side request forgery through "helpful" integrations

The Grafana advisory (AV26-796) landed Wednesday; by Thursday we were writing up an SSRF in an unrelated product: a document-preview microservice that fetched user-supplied URLs to generate thumbnails. The service ran inside a VPC with access to the cloud metadata endpoint and an internal admin API. It blocked 169.254.169.254 in the hostname, but followed a 302 redirect from an attacker-controlled host to that same address. DNS rebinding worked too: the initial resolution passed the allowlist; the second, on the actual fetch, did not.

SSRF is old. CVE-2021-21975 (vRealize) and CVE-2024-21893 (Ivanti Connect Secure) weaponized the same primitive against enterprise perimeters, and Ivanti is back on this week's list with AV26-805. The pattern is not the vulnerability class; it is where the vulnerability lives. In 2026, SSRF rarely sits in the request handler you audited. It sits in the PDF renderer, the webhook validator, the OpenGraph unfurler, the AI tool-use loop calling out to a URL the model chose. Each is an outbound HTTP client written for correctness, not adversarial input.

Two controls, both boring and both effective:

Pattern 3: Backup and orchestration planes treated as infrastructure, not applications

Two engagements this week found their highest-severity issues in the backup and secrets tier, the systems that hold, by design, the keys to everything else. One had a Commvault-style console (AV26-799) reachable from a flat management VLAN with a service account whose credentials had never rotated. The other had a HashiCorp Vault deployment (AV26-797) with an auth method bound to a Kubernetes service-account token that any namespace tenant could mint, granting cross-tenant read on secrets the namespace should never have reached. Rapid7's advisory (AV26-801, CVE-2026-18972) and the Red Hat bulletin (AV26-803, CVE-2026-10090) land in the same category: privileged platform components whose compromise extends the blast radius to everything around them.

The root cause is cultural more than technical. Backup, secrets, and orchestration are typically owned by infrastructure teams that ship rarely, patch quarterly, and lack the code-review discipline of the product teams around them. That is exactly backwards given their blast radius. Treat them like production applications: generate SBOMs, assign a named owner to each vendor advisory feed, and run authenticated scans against their admin surfaces on the same schedule as your internet-facing tier. When Siemens ships an advisory like AV26-802 for a control-system component, the question is not "are we vulnerable?"; it is "who on our team is responsible for knowing?"

What to do on Monday

Three concrete tasks a small team can finish before the next patch cycle:

  1. Inventory every place your application ingests a signed token or claim from an external IdP. Document which claims are trusted and what the IdP actually guarantees about each. Fix the gaps.
  2. Enumerate every outbound HTTP client in your codebase, including those inside AI agents, unfurlers, and PDF pipelines. Route them through a shared egress module that handles DNS pinning, redirect scoping, and network-range denial in one place.
  3. Assign a named owner to every management-plane product in your stack: backup, secrets, orchestration, monitoring. Their task on Monday: confirm they are subscribed to vendor advisories and can name this week's CVEs without looking them up.

None of this is novel. All of it stops the next report from repeating the same three findings.

Verifiable security.