## Summary
An alternate trigger, but not a fixed-version bypass, was validated for CVE-2026-48558. The original reproduction exercised the generic OpenID Connect authorization-code flow: `/auth/v1/account/oidc_get` generated a pending state, the callback reached `/oidc?code=...&state=...`, and SimpleHelp exchanged the code at a fake token endpoint that returned a forged ID token. This variant exercises SimpleHelp's Azure/Entra-flavoured OIDC path instead: `/auth/v1/account/oidc_get` returns a Microsoft authorization URL using `response_type=id_token` and `response_mode=form_post`, and the attacker posts a forged `id_token` directly to `/oidc` with the server-issued `state` and `nonce`. SimpleHelp 5.5.15 accepts the forged token and creates a `FULLY_AUTHENTICATED` technician session. Patched 5.5.16 rejects the same forged direct-ID-token callback, so no bypass of the vendor fix was found.

## Fix Coverage / Assumptions
The vendor fix appears to rely on a new invariant: every ID token consumed by the OIDC callback/authentication path must be cryptographically verified before claims are trusted for group-authenticated technician login. Because SimpleHelp is distributed as commercial binaries, no public source commit was available. Runtime and class comparison evidence shows the following binary-level changes between 5.5.15 and 5.5.16:

- `utils/oauth/oidc/IDTokenVerifier.class` and supporting JWKS cache classes are absent in 5.5.15 and present in 5.5.16.
- `com/aem/shelp/proxy/wds/OIDCCallbackManager.class` grows from 6,340 bytes to 10,556 bytes and gains `OIDCCallbackManager$ActiveOIDCCallback.class` and `OIDCCallbackManager$OIDCTestResult.class`.
- `com/aem/shelp/proxy/authentication/oidc/OIDCAuthenticator.class` grows from 6,188 bytes to 7,244 bytes.
- `com/aem/shelp/proxy/config/authentication/AzureAuthenticationProvider.class` grows from 3,860 bytes to 8,580 bytes.

The code paths explicitly covered by the tested fix include both:

1. The generic OIDC authorization-code callback used in the parent reproduction.
2. The Azure/Entra implicit/direct ID-token form-post callback tested in this variant stage.

The tested fix did not leave an observable gap for the alternate Azure/Entra path. Both the generic and Azure paths use the same `/oidc` callback and downstream `OIDCAuthenticator` / group-authentication sink, and 5.5.16 fails closed before creating a technician session.

The target's stated security scope matches this testing: the vendor advisory states that vulnerable configurations are SimpleHelp servers with an enabled OIDC Authentication Service, including OIDC-based categories labelled Active Directory, Azure, and OpenID Connect, plus a Technician Group with the OIDC service enabled and "Allow group authenticated logins" enabled. It also states that 5.5.16 and the public/fixed 6.0 release are not affected. The variant test stayed within that threat model: the input is remote unauthenticated login traffic crossing the SimpleHelp technician-authentication trust boundary, not a local/self-attacking configuration file issue.

## Variant / Alternate Trigger
Tested alternate trigger: Azure/Entra-style OIDC implicit/direct ID-token callback.

- Entry point 1: `GET https://127.0.0.1/auth/v1/account/login_options`
- Entry point 2: `GET https://127.0.0.1/auth/v1/account/oidc_get?payload=...`
- Entry point 3: `POST https://127.0.0.1/oidc` with form fields:
  - `state=<server-issued state>`
  - `id_token=<attacker-forged JWT with alg:none and bogus signature>`
- Status proof endpoint: `GET https://127.0.0.1/auth/v1/account/status`

This differs materially from the parent reproduction because no fake token endpoint is contacted and no authorization `code` is exchanged. SimpleHelp itself generates an Azure/Entra authorization URL with `response_type=id_token`, `response_mode=form_post`, and a `nonce`; the variant then forges the direct callback payload that an identity provider would post back. The vulnerable server accepts the forged claims as the identity of `azure-attacker@example.com` / `Forged Azure Attacker`.

Relevant code/class anchors from the binary inspection:

- `com/aem/shelp/proxy/config/authentication/AzureAuthenticationProvider.class` — Azure/Entra provider; vulnerable javap evidence shows `getResponseType()` returns `id_token` and `createAuthenticationMetadata()` adds `response_mode=form_post`.
- `com/aem/shelp/proxy/wds/OIDCCallbackManager.class` — `/oidc` callback manager.
- `com/aem/shelp/proxy/authentication/oidc/OIDCAuthenticator.class` — OIDC callback/token-to-login authenticator.
- `utils/oauth/oidc/IDToken.class` — parses ID-token claims.
- `utils/oauth/oidc/IDTokenVerifier.class` — absent in 5.5.15 and present in 5.5.16.
- `com/aem/shelp/proxy/ProxyServerAuthentication.class` — downstream group-authenticated technician login sink.

## Impact
- Package/component affected: SimpleHelp server technician authentication, specifically OIDC/Azure OIDC login processing and group-authenticated technician account creation.
- Affected version tested: SimpleHelp 5.5.15, build `20260326-092709`, official Linux tarball SHA256 `26cd904ebf78ac4b2c5b99f6a9659a562390777dc8fe730469e2ecfc8ad139ab`.
- Fixed version tested: SimpleHelp 5.5.16, build `20260526-203544`, official Linux tarball SHA256 `9360af980277e1ef4330eb1ed08d981c9dfdcc4e25d87ed0552a47f5ebd5161a`.
- Risk level and consequences on vulnerable builds: Critical authentication bypass. In the tested vulnerable configuration, a remote unauthenticated attacker can become a fully authenticated technician through the Azure/Entra OIDC option if OIDC group-authenticated logins are enabled and login IP restrictions permit the source address.

## Impact Parity
- Disclosed/claimed maximum impact for the parent: remote authentication bypass and possible MFA bypass via forged OIDC identity token, yielding a technician session.
- Reproduced impact from this variant run: on SimpleHelp 5.5.15, the Azure/Entra direct ID-token callback produces `FULLY_AUTHENTICATED` status for `Forged Azure Attacker` / `azure-attacker@example.com` without a valid identity-provider signature.
- Parity: `full` for the vulnerable-version alternate trigger; `none` as a fixed-version bypass because patched 5.5.16 rejects the same forged direct-ID-token callback.
- Not demonstrated: post-auth remote-control actions against managed endpoints were not performed. The proof stops at authenticated technician-session creation and status-page authorization evidence.

## Root Cause
The same underlying vulnerable sink can be reached in SimpleHelp 5.5.15 from the Azure/Entra OIDC path because the vulnerable implementation parses and trusts an ID token before verifying its signature. For Azure/Entra providers, `AzureAuthenticationProvider.getResponseType()` returns `id_token` and the provider adds `response_mode=form_post`; this causes `/auth/v1/account/oidc_get` to create an authorization URL where the identity token is returned directly to `/oidc`, instead of being obtained from a token endpoint after a code exchange. In 5.5.15, posting a forged JWT with `alg:none`, a bogus signature segment, matching `aud`, and the server-issued `nonce`/`state` reaches the same `OIDCAuthenticator` and `ProxyServerAuthentication` group-authentication path as the parent reproduction.

The fix commit is not public. The tested vendor fixed binary, 5.5.16, adds `utils/oauth/oidc/IDTokenVerifier.class` and rejects the forged Azure/Entra direct callback. This indicates the fix enforces signature/JWKS validation before the parsed `IDToken` is accepted by group authentication.

## Reproduction Steps
1. Run `bundle/vuln_variant/reproduction_steps.sh`.
2. The script:
   - Verifies the official SimpleHelp 5.5.15 and 5.5.16 Linux tarball SHA256 values, reusing the downloaded repro artifacts if present.
   - Extracts clean vulnerable and patched server instances under `bundle/vuln_variant/runtime-azure-implicit/`.
   - Initializes each SimpleHelp server through first launch.
   - Configures an Azure/Entra-style OIDC authentication provider (`type="oidc_azure"`) and a non-admin Technician Group with group-authenticated logins enabled.
   - Requests a real SimpleHelp OIDC authorization URL through `/auth/v1/account/oidc_get`.
   - Confirms the server-generated Azure authorization URL uses `response_type=id_token`, `response_mode=form_post`, `state`, and `nonce`.
   - Posts a forged unsigned/bogus-signature ID token directly to `/oidc` with the server-issued `state`.
   - Checks `/auth/v1/account/status` to determine whether a technician session was created.
   - Repeats the same test against patched 5.5.16.
3. Expected evidence:
   - Vulnerable 5.5.15: `bundle/logs/vuln_variant/azure_vuln_flow.json` contains `"state":"FULLY_AUTHENTICATED"` and the forged Azure identity.
   - Patched 5.5.16: `bundle/logs/vuln_variant/azure_patched_flow.json` contains a `Login Failed` callback and `"state":"UNAUTHENTICATED"`.
   - Script exit: `1`, because the alternate trigger is vulnerable-only and did not bypass fixed 5.5.16.

## Evidence
Primary evidence files:

- `bundle/logs/vuln_variant/reproduction_steps.log` — full output from the second idempotency run of the variant script.
- `bundle/logs/vuln_variant/azure_vuln_flow.json` — vulnerable Azure/Entra direct-ID-token flow result.
- `bundle/logs/vuln_variant/azure_patched_flow.json` — patched negative-control result.
- `bundle/logs/vuln_variant/azure_flow_summary.json` — structured variant summary.
- `bundle/logs/vuln_variant/azure_vuln_runtime_tail.log` — vulnerable server runtime tail showing group-authenticated login/session registration.
- `bundle/logs/vuln_variant/azure_patched_runtime_tail.log` — patched server runtime tail.
- `bundle/logs/vuln_variant/azure_class_comparison.log` — class-level comparison showing verifier addition and Azure/OIDC class changes.
- `bundle/logs/vuln_variant/fixed_version.txt` — exact fixed binary identity tested.
- `bundle/vuln_variant/runtime_manifest.json` — runtime evidence manifest.

Key evidence excerpt from `azure_flow_summary.json`:

```json
{
  "vulnerable_auth_url_direct_id_token_flow": true,
  "vulnerable_status_fully_authenticated": true,
  "patched_has_IDTokenVerifier_class": true,
  "patched_status_fully_authenticated": false,
  "patched_failed_closed": true,
  "vulnerable_status_after": "{\"state\":\"FULLY_AUTHENTICATED\",\"user\":{\"displayName\":\"Forged Azure Attacker\",\"username\":\"azure-attacker\",\"emailAddress\":\"azure-attacker@example.com\"...}}",
  "patched_status_after": "{\"state\":\"UNAUTHENTICATED\",\"code\":0}"
}
```

Key class-comparison excerpt from `azure_class_comparison.log`:

```text
[*] Vulnerable Azure/OIDC-relevant classes
  com/aem/shelp/proxy/config/authentication/AzureAuthenticationProvider.class
  utils/oauth/oidc/IDToken.class
  com/aem/shelp/proxy/wds/OIDCCallbackManager.class
  com/aem/shelp/proxy/authentication/oidc/OIDCAuthenticator.class
[*] Patched Azure/OIDC-relevant classes
  com/aem/shelp/proxy/config/authentication/AzureAuthenticationProvider.class
  utils/oauth/oidc/IDTokenVerifier.class
  com/aem/shelp/proxy/wds/OIDCCallbackManager.class
  com/aem/shelp/proxy/authentication/oidc/OIDCAuthenticator.class
```

The script was executed twice. Both runs completed deterministically with exit code `1`, which is the expected stage result for "alternate trigger works on vulnerable build but no fixed-version bypass was found."

## Recommendations / Next Steps
- Keep the fix centralized at the ID-token acceptance boundary. Every route that constructs or receives an `IDToken` must call the verifier before exposing claims to `OIDCAuthenticator`, group filters, account lookup/linking, or technician-session creation.
- Add regression tests for both materially different OIDC modes:
  1. Generic authorization-code callback where `/oidc` receives `code` and the server obtains `id_token` from `/token`.
  2. Azure/Entra direct callback where `/oidc` receives a form-posted `id_token` directly.
- Regression tests should reject `alg:none`, bogus signatures, missing/empty JWKS, mismatched `kid`, wrong `iss`, wrong `aud`, expired `exp`, and nonce/state mismatches.
- Ensure Azure/Entra-specific validation uses the correct issuer/JWKS metadata for the configured tenant and does not silently fall back to claim-only parsing if metadata retrieval fails.
- Continue documenting operational mitigations from the vendor advisory: disable OIDC group-authenticated logins if patching is delayed, enforce technician login IP restrictions, and audit newly created OIDC/anonymous technician accounts.

## Additional Notes
- Idempotency confirmed: `bundle/vuln_variant/reproduction_steps.sh` was run twice consecutively and completed both times with the expected exit code `1`.
- The variant uses the real SimpleHelp server binaries and real HTTPS `/auth/v1/account/oidc_get`, `/oidc`, and `/auth/v1/account/status` endpoints. No source checkout was modified.
- The only synthetic input is the forged ID token, which models the attacker-controlled OIDC response at the trust boundary described by the vendor advisory.
- No fixed-version bypass was found in the tested 5.5.16 Linux server build.
