# Verification Report

## Fix Summary

The proposed patch removes PHP `eval()` from both vBulletin 5.1.5 `runMaths()` implementations and replaces it with a bounded recursive-descent arithmetic evaluator. It accepts only finite decimal numbers, whitespace, parentheses, and the stock arithmetic operators `+`, `-`, `*`, and `/`; it rejects all other tokens rather than deleting them. Expression length, nesting depth, operation count, division-by-zero, and non-finite results are bounded. Existing single CSS-unit behavior is retained. Because this change is made at the common runtime sink, it covers both the disclosed `pagenav[pagenumber]` trigger and the independently confirmed `pagenavnew[currentpage]` alternate trigger.

## Changes Made

- `includes/vb5/template/runtime.php`
  - Removed filter-plus-`eval()` execution from `vB5_Template_Runtime::runMaths()`.
  - Added strict arithmetic parsing, finite-result checks, and complexity limits.
  - Preserved normal arithmetic and supported CSS-unit suffixes.
- `core/vb/template/runtime.php`
  - Applied the same change to the duplicate `vB_Template_Runtime` implementation so alternate/template-validation contexts do not retain the vulnerable evaluator.
- `bundle/coding/proposed_fix.diff`
  - Unified patch for the two product runtime files; SHA-256 `e27e2960bc15334b5329211137c8f146a1026dfbb87443975c6ebb732fc03042`.
- `bundle/coding/verify_fix.sh`
  - Idempotent coding-stage verifier covering clean patch application, both runtime implementations, exact PHP 7.0.32 execution, and both real unauthenticated HTTP routes.

## Verification Steps

1. Bound the test to the exact affected source bytes:
   - front runtime SHA-256: `cfa52c8bd234e176d9fd994546d8bf0bcb2c0eb47078806717015ea9c6e62284`;
   - core runtime SHA-256: `1c576fedaf8daa2b16e4989b8c4979ad52d9716ec870663347a7e1750c9a1fd8`;
   - vulnerable product manifest: `sha256:df5a9fa87186c49101db79577a0401c07f1239bf79dd1e5d066328147f6727f8`;
   - PHP runtime manifest: `sha256:60cbd13178ed7f629098b1b7a0104ce038d55729f89784739e1bc2eca372f64a`.
2. Applied `bundle/coding/proposed_fix.diff` with `patch -p1` to a fresh tree and asserted that neither runtime retained `@eval`.
3. Linted and loaded each patched runtime independently in exact PHP 7.0.32.
4. Ran parser regression tests for precedence, parentheses, unary signs, whitespace, decimal arithmetic, division, CSS units, malformed tokens, function syntax, XOR, division by zero, malformed decimals, the complete 19 KB synthesized `strlen()` payload, mixed units, non-scalar input, and length/depth/operation limits.
5. Temporarily installed the patch into the real vBulletin 5.1.5 HTTP stack and waited beyond OPcache's revalidation interval.
6. Sent benign unauthenticated requests to both paging templates and required page values `1` and `3`.
7. Sent the full current-run payload to both confirmed routes and required `Invalid math expression` with no deterministic vulnerable result `data-page="36"`.
8. Restored the application files byte-for-byte after each run.
9. Executed the verifier twice consecutively to establish idempotency:

   ```bash
   PRUVA_CODING_WORKDIR=/tmp/pruva-coding-cve-2026-61511-run2 \
     PRUVA_CODING_RUN_ID=coding-live-2 \
     bash bundle/coding/verify_fix.sh

   PRUVA_CODING_WORKDIR=/tmp/pruva-coding-cve-2026-61511-run2 \
     PRUVA_CODING_RUN_ID=coding-live-3 \
     bash bundle/coding/verify_fix.sh
   ```

Both commands exited `0`. The final output was:

```text
patch_applied_cleanly=true
both_runtime_unit_suites_passed=true
eval_removed_from_both_runtimes=true
http_tested=true
benign_arithmetic_preserved=true
parent_trigger_blocked=true
alternate_trigger_blocked=true
VERIFIED: strict arithmetic parsing blocks both CVE-2026-61511 request paths without breaking normal paging.
```

## Test Results

- **Clean application:** PASS for both modified files using `patch -p1`.
- **PHP syntax:** PASS for both runtime implementations on PHP 7.0.32.
- **Unit regressions:** PASS for both classes across all valid, malformed, exploit, unit, and resource-bound cases.
- **Ordinary HTTP behavior:** PASS; both `pagenav` and `pagenavnew` still rendered previous page `1` and next page `3` for current page `2`.
- **Disclosed trigger:** PASS; the patched `ajax/render/pagenav` path returned `Invalid math expression` twice and rendered no `data-page="36"`.
- **Alternate trigger:** PASS; the patched `ajax/render/pagenavnew` path returned `Invalid math expression` and rendered no `data-page="36"`.
- **Idempotency:** PASS in two consecutive complete runs (`coding-live-2` and `coding-live-3`).
- **Restoration:** PASS; application runtime hashes after verification matched the original source hashes.

Primary evidence:

- `bundle/logs/coding/coding-live-3-proof.log`
- `bundle/logs/coding/coding-live-3-unit.log`
- `bundle/logs/coding/coding-live-3-http.log`
- `bundle/logs/coding/coding-live-3-observation.json`
- `bundle/logs/coding/coding-live-3-source-identity.txt`
- `bundle/logs/coding/coding-live-3-parent-benign.json`
- `bundle/logs/coding/coding-live-3-parent-attack.json`
- `bundle/logs/coding/coding-live-3-variant-benign.json`
- `bundle/logs/coding/coding-live-3-variant-attack.json`

## Remaining Concerns

- The official vBulletin 6.2.2 patch source is proprietary and unavailable. This patch is an independently developed remediation against the exact affected 5.1.5 bytes, not a byte-for-byte vendor backport.
- The parser intentionally omits PHP bitwise/comparison operators because stock math templates inspected for this target require ordinary arithmetic, while those operators enabled the exploit grammar. Customized templates relying on such PHP semantics will now receive `/* Invalid math expression */` and should be rewritten as explicit template logic.
- Defense-in-depth work remains advisable: cast paging request fields to bounded positive integers and allowlist templates exposed through unauthenticated `ajax/render`. Those measures do not replace removal of code execution at the common sink.
