{
  "claim_outcome": "confirmed",
  "claim_block_reason": null,
  "variant_result": "confirmed",
  "variant_kind": "alternate_trigger_authz_bypass",
  "is_bypass": true,
  "validated_surface": "api_remote",
  "evidence_scope": "production_path",
  "claimed_impact_class": "authorization_bypass",
  "observed_impact_class": "authorization_bypass",
  "exploitability_confidence": "high",
  "attacker_controlled_input": "POST /egroupware/json.php?menuaction=EGroupware\\SmallParT\\Overlay::ajax_write with JSON body: course_id as a PHP array {\"participants\":[{\"account_id\":<attacker>,\"participant_role\":3}],\"course_id\":\"1\"} — isParticipant() caches the attacker-supplied role and isTeacher() returns true",
  "trigger_path": "Overlay::ajax_write -> Overlay::aclCheck($data['course_id'], true) -> Bo::isParticipant($course_id_array) caches role=3 -> Bo::isTeacher($course_id_array) returns true via cache -> aclCheck PASSES -> Overlay::write() rejects array with InvalidArgumentException (pre-existing type guard)",
  "end_to_end_target_reached": true,
  "sanitizer_used": false,
  "crash_observed": false,
  "read_write_primitive_observed": false,
  "exploit_chain_demonstrated": false,
  "blocking_mitigation": "Overlay::write() has a pre-existing is_int/is_numeric type guard that rejects array course_id, preventing the overlay write operation. The authz bypass itself IS confirmed — the ACL check is bypassed on the fixed version. The original RCE sink (file write via videoPath() traversal) is properly closed by basename() guards.",
  "inferred": false,
  "vuln_version_results": {
    "tag": "26.2.20260216",
    "authz_bypass": true,
    "control_denied": true,
    "bypass_past_acl": true,
    "response_control": "Permission denied!",
    "response_bypass": "Invalid argument (Overlay::write type guard)"
  },
  "fixed_version_results": {
    "tag": "26.2.20260224",
    "authz_bypass": true,
    "control_denied": true,
    "bypass_past_acl": true,
    "response_control": "Permission denied!",
    "response_bypass": "Invalid argument (Overlay::write type guard)"
  },
  "root_cause_fixed": false,
  "root_cause_function": "Bo::isParticipant()",
  "root_cause_file": "smallpart/src/Bo.php",
  "root_cause_lines": "2339-2370",
  "latest_version_checked": "26.7.20260702",
  "latest_version_root_cause_fixed": false,
  "notes": "The isParticipant() function is byte-identical across 26.2.20260216, 26.2.20260224, and 26.7.20260702. The fix only hardened the ajax_upload caller with an (int) cast; the root cause (isParticipant trusting request-supplied participants arrays) was never addressed. The authz bypass is confirmed on the fixed version via Overlay::ajax_write. The full RCE chain is NOT achievable through this variant because videoPath() now has basename() guards."
}
