Share
## https://sploitus.com/exploit?id=420BEB65-BD63-521E-90B1-5065E05B96C0
# EcoOnline EHS (Android) β€” Deep Link Validation Bypass β†’ WebView Open Redirect (CVE-2026-26897)

Public disclosure / advisory for **CVE-2026-26897**, a deep link validation bypass in the
**EcoOnline EHS** Android application (`com.airsweb.v10`). A crafted `ehs-app://` deep link is
rewritten to `https://` and loaded directly into the app's main WebView **without the host
allow-list check** that the app applies on every other navigation path, letting a remote attacker
render arbitrary attacker-controlled content inside the trusted application (phishing).

Responsibly disclosed, acknowledged by the vendor, and **fixed in version 0.2.500**.

## βœ… Status: FIXED
- **Vulnerable version analysed:** `com.airsweb.v10` **0.2.499** (versionCode `44631`)
- **Fixed version:** **0.2.500** (live on Google Play)
- **Action for users:** update the EcoOnline EHS app to the latest version.

## Affected binary (for verification)

The vendor's application is proprietary and is **not redistributed in this repository**. The static
analysis below was performed on the build identified here β€” obtain the exact APK from an archive
(e.g. APKPure version history) and verify its hash before reproducing:

| | |
|---|---|
| Package | `com.airsweb.v10` |
| versionName / versionCode | `0.2.499` / `44631` |
| SHA-256 | `e9e8a38d133cb9da9901caf03c4a7a033c75ad1f32ba0539260e47d5dd5068c0` |
| Source | APKPure β€” "EcoOnline EHS" version history |

## Summary

| Field | Value |
|---|---|
| **CVE ID** | CVE-2026-26897 |
| **Vendor** | EcoOnline ("EcoOnline Global") β€” https://www.ecoonline.com/ |
| **Product** | EcoOnline EHS for Android (`com.airsweb.v10`) |
| **Affected version** | 0.2.499 (versionCode 44631) |
| **Fixed version** | 0.2.500 |
| **Vulnerability type** | Improper validation in a custom URL scheme handler (deep link bypass) β†’ unvalidated WebView load / open redirect |
| **CWE** | CWE-939 (Improper Authorization in Handler for Custom URL Scheme); related CWE-749 |
| **Affected component** | `com.airsweb.v10.MainActivity` (exported deep-link handler) and the deep-link branch in `MainActivityKt.WebViewPage` |
| **Custom scheme** | `ehs-app://` |
| **Attack type** | Remote (requires user interaction β€” opening a crafted link) |
| **Impact** | Phishing / social engineering: arbitrary attacker-controlled web content rendered inside the trusted EcoOnline EHS app (e.g. a fake login), bypassing the app's domain allow-list |
| **Discoverer** | Ahmet Mersin |

## Description

EcoOnline EHS for Android is a Jetpack-Compose **WebView wrapper** around the EHS web platform. Its
default content is loaded from:

```
startUrl = "https://ehsmobilelanding.ecoonline.net/"
```

The app exports a single Activity (`MainActivity`) that is both the launcher and the handler for the
custom URL scheme **`ehs-app`**. The `` element of the deep-link `intent-filter` declares
**only a scheme β€” no host and no path** β€” so *any* `ehs-app://…` URI is routed to the app.

To protect WebView navigation, the app implements a host allow-list (`isInternalHost`) and applies it
when restoring the last-visited URL. **However, the deep-link handling branch does not call that
allow-list at all.** It takes the incoming deep-link URI, performs a naΓ―ve string replacement of the
scheme `ehs-app:` β†’ `https:`, and calls `WebView.loadUrl()` on the result. A remote attacker can
therefore craft a deep link that causes the trusted app to load an arbitrary `https://` origin.

## Affected component

### `AndroidManifest.xml` (v0.2.499) β€” exported, scheme-only deep link

```xml

    
        
        
    
    
        
        
        
           
    

```

### Root cause β€” deep-link branch in `MainActivityKt.WebViewPage` (decompiled, v0.2.499)

```java
// intent delivered to the exported MainActivity
if (intent.getScheme().equals("ehs-app")) {
    WebView webView = ...;
    if (webView != null) {
        Uri data = intent.getData();                       // full ehs-app://… URI
        String s = String.valueOf(data);
        // naΓ―ve scheme rewrite: "ehs-app:" -> "https:"
        String url = StringsKt.replaceFirst(s, "ehs-app:", "https:", false, 4, null);
        webView.loadUrl(url);                              //  excludeDomainsStartingWith =
        listOf("passport", "login", "auth");

public static boolean isInternalHost(String host) {
    for (String p : excludeDomainsStartingWith)
        if (host.startsWith(p)) return false;
    return internalDomains.containsMatchIn(host);
}
```

> Secondary note: the `internalDomains` regex is itself weak (broken alternation + `containsMatchIn`
> substring matching), but the primary issue is that **the deep-link branch never invokes
> `isInternalHost` at all.**

## Proof of Concept

A screen-recording PoC was produced on **2026-01-13** against `com.airsweb.v10` 0.2.499.

1. Install the affected version (**0.2.499**) on an Android device.
2. Deliver a crafted deep link to the victim (e.g. via email, SMS, chat, QR, or a web page):
   ```
   ehs-app://attacker.example/login
   ```
3. When the victim opens it, `MainActivity` rewrites the scheme and the WebView loads:
   ```
   https://attacker.example/login
   ```
   inside the trusted EcoOnline EHS app β€” no allow-list check is performed.
4. The attacker page is rendered with the look and chrome of the legitimate app and can, for example,
   present a fake EHS login to harvest credentials.

> In the original PoC the researcher hosted a **benign look-alike landing page** purely to
> demonstrate the redirect. This advisory documents the vulnerability for **defensive / disclosure
> purposes** and intentionally contains **no phishing page or credential-capture code**.

## Impact

- Loads arbitrary attacker-controlled `https://` content inside the trusted application context.
- Phishing / credential theft via a login prompt that appears to originate from the real app.
- UI spoofing and general social-engineering uplift (the malicious page inherits the app's trust).

**CVSS v3.1 (researcher estimate β€” finalise before publication):**
`AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N` β†’ **6.3 (Medium)** (a Scope:Changed argument can be made, as
untrusted content executes in the trusted app context).

## Remediation

Update to **`com.airsweb.v10` 0.2.500** or later. Recommended fixes:

- Apply `isInternalHost()` (or an equivalent allow-list) to deep-link URLs **before** `loadUrl()`.
- Do not derive the loaded URL by blindly rewriting the scheme; validate scheme **and** host.
- Constrain the deep-link `intent-filter` with an explicit `android:host`/`android:pathPrefix`.
- Strengthen the `internalDomains` regex (anchor host fully; avoid substring matches).

## Disclosure timeline

| Date | Event |
|---|---|
| 2026-01-13 | PoC recorded against 0.2.499 |
| 2026-01-15 | CVE request submitted to MITRE (ticket scr1979357) |
| 2026-02-27 | **CVE-2026-26897** assigned by MITRE |
| prior to publication | Vendor acknowledged; fix released in 0.2.500 |
| 2026-03-04 | Publication request sent to MITRE |
| 2026-05-06 | MITRE requested a complete public disclosure URL |
| 2026-06-03 | Public advisory published (this repository) |

## References

- CVE-2026-26897 (MITRE CVE record)
- EcoOnline EHS on Google Play β€” https://play.google.com/store/apps/details?id=com.airsweb.v10
- Vendor β€” https://www.ecoonline.com/

## Credit

Discovered and reported by **Ahmet Mersin** β€” GitHub [@iwallplace](https://github.com/iwallplace),
HackerOne `iwallplace`.