<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://bugs.webkit.org/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4.1"
          urlbase="https://bugs.webkit.org/"
          
          maintainer="admin@webkit.org"
>

    <bug>
          <bug_id>324968</bug_id>
          
          <creation_ts>2026-09-23 05:24:29 -0700</creation_ts>
          <short_desc>iOS 27: JS and Wasm run without JIT on non-secure-context (http://) pages</short_desc>
          <delta_ts>2026-09-30 08:45:21 -0700</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>WebKit</product>
          <component>JavaScriptCore</component>
          <version>Safari 27</version>
          <rep_platform>iPhone / iPad</rep_platform>
          <op_sys>iOS 27</op_sys>
          <bug_status>RESOLVED</bug_status>
          <resolution>INVALID</resolution>
          
          <see_also>https://bugs.webkit.org/show_bug.cgi?id=307047</see_also>
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords>InRadar</keywords>
          <priority>P2</priority>
          <bug_severity>Normal</bug_severity>
          <target_milestone>---</target_milestone>
          
          
          <everconfirmed>1</everconfirmed>
          <reporter>alexey.pelykh</reporter>
          <assigned_to name="Nobody">webkit-unassigned</assigned_to>
          <cc>ap</cc>
    
    <cc>k_monsen</cc>
    
    <cc>ronan_turner</cc>
    
    <cc>syg</cc>
    
    <cc>webkit-bug-importer</cc>
          

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>2253445</commentid>
    <comment_count>0</comment_count>
      <attachid>481528</attachid>
    <who name="">alexey.pelykh</who>
    <bug_when>2026-09-23 05:24:29 -0700</bug_when>
    <thetext>Created attachment 481528
Minimal self-contained reproduction (2.3 KB, no network). Runs a 30M-iteration float loop three times in JavaScript and once as a 128-byte hand-assembled WebAssembly module (bit-identical result), and

&lt;!-- bugs.webkit.org — suggested fields --&gt;
&lt;!-- Product: WebKit · Component: JavaScriptCore · Version: Safari 27 (or &quot;Other&quot;) · Hardware: iPhone / iPad · OS: iOS 27 · Severity: Normal --&gt;
&lt;!-- Attachment: secure-context-jit.html (2.3 KB, self-contained, no external resources) --&gt;

# iOS 27: JS and Wasm run without JIT on non-secure-context (http://) pages

## Summary

On iOS 27.0, a page that is **not a secure context** — plain `http://` served from a machine on the local network, whether addressed by IP literal or by a `.local` mDNS hostname — executes JavaScript **and** WebAssembly at interpreter speed: roughly 4–5× slower on a scalar loop and 20–60× slower on compute-heavy library code, with no tier-up over 45 s of hot execution. The **same page** served over an `https://` origin, on the **same device**, minutes later, runs at full JIT speed. The behaviour is identical in Safari and in Chrome for iOS (WKWebView), so it appears to be WebKit-wide rather than Safari-specific. The same device on iOS 26.6 five weeks earlier ran the same library code at full speed over the same kind of plain-HTTP LAN origin.

I could not find this documented anywhere (Safari 27.0 release notes, iOS 27 security notes, WebKit blog). If it is an intentional hardening step, the practical problem is that it silently invalidates every on-device measurement made through the ordinary local-development workflow (`python3 -m http.server`, `npm run dev` on a LAN IP), with no console warning and no observable difference except the numbers.

## Environment

| Detail | Value |
|--------|-------|
| Device | iPhone [model — please fill in], iOS 27.0 |
| Safari | UA `Version/27.0 Mobile/15E148 Safari/604.1` (reports `iPhone OS 18_7` in the UA; the device is on 27.0) |
| Chrome for iOS (WKWebView) | `CriOS/154.0.8037.41` — same result as Safari |
| Serving (slow case) | `python3 -m http.server` (Python 3.14) on a Mac on the same Wi-Fi; page opened as `http://&lt;lan-ip&gt;:&lt;port&gt;/…` and as `http://&lt;host&gt;.local:&lt;port&gt;/…` — `window.isSecureContext === false` |
| Serving (fast case) | the same directory exposed through an HTTPS tunnel (ngrok); page opened as `https://…` — `window.isSecureContext === true` |
| Control, desktop | macOS 26.6.2 (25G83), Safari 26.6.2, same plain-HTTP LAN origin: **full JIT speed** — the macOS engine does not show this |
| Control, engines | node v26.8.2 (V8) normal, and `node --jitless` as a known-interpreter reference |
| Lockdown Mode | off (`WebAssembly` is present on the page; Lockdown Mode removes it) |
| Low Power Mode | off. Rebooting the device changes nothing |

## Steps to reproduce

1. Save the attached `secure-context-jit.html` (self-contained: a 30M-iteration float loop in JavaScript, the identical loop as a 128-byte hand-assembled WebAssembly module, and a readout of `location.origin`, `isSecureContext` and the UA). It loads nothing from the network.
2. On a Mac on the same Wi-Fi: `python3 -m http.server 8000` in that directory.
3. On the iPhone (iOS 27.0), in Safari, open `http://&lt;mac-lan-ip&gt;:8000/secure-context-jit.html` and tap **Run**. Note the three JS timings and the wasm timing.
4. Serve the same directory over HTTPS (any tunnel, or a locally trusted certificate) and open the `https://` URL on the same phone. Tap **Run**.
5. Optional: repeat step 3 with `http://&lt;mac-hostname&gt;.local:8000/…`, and in Chrome for iOS.

## Expected behaviour

The same page yields the same timings on the same device regardless of whether the origin is a secure context. If JIT policy depends on the origin, that policy is documented, and local-development origins (private-network IPs, `.local`) have a supported way to opt in.

## Actual behaviour

Over `http://` (either IP or `.local`), all three consecutive JS runs take ~430–550 ms and the wasm loop ~520–570 ms; no run is faster than the previous one. Over `https://` the JS loop takes ~98 ms and the wasm loop ~66 ms.

## Measurements

All on the same iPhone, same page, the same afternoon. ms.

| Probe | `http://` LAN, IP literal | `http://` LAN, `.local` hostname | **`https://`** | macOS 26.6.2 Safari, same http:// LAN origin | node V8 | node `--jitless` |
|---|---:|---:|---:|---:|---:|---:|
| JS loop, 30M iterations | 409–550 (5 runs) | 444 | **98** | 75 | 118 | 599 |
| Same loop, WebAssembly | 517–568 | 568 | **66** | — | 177 | — |
| 200,000 × h3-js `latLngToCell` (emscripten asm.js-style) | 5,236–5,948 | 5,451 | **204** | — | 231 | 5,471 |
| Real workload: h3-js `polygonToCells` + per-cell filtering, 150 km disk | 3,845–4,417 (Safari and Chrome) | 4,190 | **116** | 147 | 78 | 3,549 |
| Same workload, 500 km disk | 43,008–46,112 | — | **793** | 991 | 950 | 40,214 |

Two further observations:

- **No tier-up.** Per-cell cost of the workload over `http://` is constant across radii (0.237 ms/cell at 150 km, 0.227 at 300, 0.226 at 500) — i.e. across 45 s of the same hot function nothing gets faster. Over `https://` the phone is 1.2× *faster* than the laptop&apos;s V8, as it was on iOS 26.6.
- **The device JITs fine otherwise.** JetStream 3 (browserbench.org, an `https://` origin) scores **257** on this phone in the same session.

The `http://` column matches `node --jitless` within ~10% on every row, which is why I read it as interpreter-only execution rather than a slow JIT.

## Regression window

Same device, same library, same plain-HTTP LAN workflow: on **iOS 26.6 (2026-08-19)** `latLngToCell` ran at ~0.68 µs/call (79 ms per 117k). On **iOS 27.0 (2026-09-23)** it runs at ~26 µs/call over `http://` and ~1 µs/call over `https://`.

## What this breaks in practice

Any on-device performance measurement made through the normal local workflow (`python3 -m http.server`, a dev server on a LAN IP, `.local` names) now reports interpreter numbers with nothing to indicate why. In our case a build that costs 116 ms in production was measured at 4.0 s, and a 500 km variant that costs 0.8 s was measured at 45 s, before the origin was suspected.

## Ask

1. If this is intentional: document the policy (which origins are affected, and whether WKWebView hosts can override it), and provide a developer affordance — e.g. a Feature Flag, or treating private-network / `.local` origins as *potentially trustworthy* for JIT purposes the way `localhost` already is.
2. If it is not intentional: this looks like JSC running LLInt-only (and wasm without its compiled tiers) for non-secure-context pages on iOS 27.0.

Happy to run any further probe on the device.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2253963</commentid>
    <comment_count>1</comment_count>
    <who name="Alexey Proskuryakov">ap</who>
    <bug_when>2026-09-23 23:27:35 -0700</bug_when>
    <thetext>Have you tried if the &quot;Enable EnhancedSecurity Heuristic&quot; feature flag changes this behavior?

As far as I know, this is intentional, and details are subject to change, so documenting those may not be realistic. CC&apos;ed some folks who may speak more authoritatively.

Would you be willing to elaborate on the use case? I understand it as a hypothetical, but in practice I&apos;d expect that a plain http server is rarely of use to Web developers, because so many APIs are disabled in insecure contexts. So even before performance testing, one can&apos;t use it for correctness validation.

&gt; treating private-network / `.local` origins as *potentially trustworthy* for JIT purposes the way `localhost` already is.

This is an interesting idea, although an active network attacker on one&apos;s corporate network could once again inject malicious content attacking JIT if this was allowed.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2256635</commentid>
    <comment_count>2</comment_count>
    <who name="Radar WebKit Bug Importer">webkit-bug-importer</who>
    <bug_when>2026-09-30 05:25:14 -0700</bug_when>
    <thetext>&lt;rdar://problem/188805621&gt;</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2256681</commentid>
    <comment_count>3</comment_count>
    <who name="">ronan_turner</who>
    <bug_when>2026-09-30 08:31:42 -0700</bug_when>
    <thetext>I can confirm this is intended behaviour - this is part of a feature named Enhanced Security which applies certain hardening policies when navigations occur that we wish to protect further. Requests relating to plaintext HTTP are one such scenario. As noted above, disabling the &quot;Enable EnhancedSecurity Heuristics&quot; flag should prevent this behaviour from occurring if necessary for testing and benchmarking purposes.</thetext>
  </long_desc>
      
          <attachment
              isobsolete="0"
              ispatch="0"
              isprivate="0"
          >
            <attachid>481528</attachid>
            <date>2026-09-23 05:24:29 -0700</date>
            <delta_ts>2026-09-23 05:24:29 -0700</delta_ts>
            <desc>Minimal self-contained reproduction (2.3 KB, no network). Runs a 30M-iteration float loop three times in JavaScript and once as a 128-byte hand-assembled WebAssembly module (bit-identical result), and</desc>
            <filename>secure-context-jit.html</filename>
            <type>text/html</type>
            <size>2341</size>
            <attacher>alexey.pelykh</attacher>
            
              <data encoding="base64">PCFkb2N0eXBlIGh0bWw+CjxtZXRhIGNoYXJzZXQ9InV0Zi04Ij48bWV0YSBuYW1lPSJ2aWV3cG9y
dCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLGluaXRpYWwtc2NhbGU9MSI+Cjx0aXRsZT5K
SVQgdnMgc2VjdXJlIGNvbnRleHQ8L3RpdGxlPgo8c3R5bGU+Ym9keXtmb250OjE1cHggLWFwcGxl
LXN5c3RlbSxzeXN0ZW0tdWksc2Fucy1zZXJpZjttYXJnaW46MTZweH1wcmV7d2hpdGUtc3BhY2U6
cHJlLXdyYXA7d29yZC1icmVhazpicmVhay1hbGw7YmFja2dyb3VuZDojZjRmNGY0O3BhZGRpbmc6
OHB4fWJ1dHRvbntmb250LXNpemU6MThweDtwYWRkaW5nOjEwcHggMjBweH08L3N0eWxlPgo8cD5T
YW1lIHBhZ2UsIHR3byBvcmlnaW5zLiBUYXAgUnVuIG9uIDxjb2RlPmh0dHA6Ly8mbHQ7bGFuLWhv
c3QmZ3Q7L+KApjwvY29kZT4gYW5kIG9uIGFuIDxjb2RlPmh0dHBzOi8vPC9jb2RlPiBvcmlnaW4s
IGNvbXBhcmUuPC9wPgo8YnV0dG9uIGlkPSJiIj5SdW48L2J1dHRvbj4KPHByZSBpZD0ibyI+KG5v
dCBydW4geWV0KTwvcHJlPgo8c2NyaXB0PgovLyBBIDEyOC1ieXRlIFdlYkFzc2VtYmx5IG1vZHVs
ZTogdGhlIHNhbWUgbG9vcCBhcyBqc0xvb3AoKSwgZXhwb3J0ZWQgYXMgbG9vcChuKSAtPiBmNjQu
CmNvbnN0IFdBU00gPSBuZXcgVWludDhBcnJheShbMCwgOTcsIDExNSwgMTA5LCAxLCAwLCAwLCAw
LCAxLCA2LCAxLCA5NiwgMSwgMTI3LCAxLCAxMjQsIDMsIDIsIDEsIDAsIDcsIDgsIDEsIDQsIDEw
OCwgMTExLCAxMTEsIDExMiwgMCwgMCwgMTAsIDk2LCAxLCA5NCwgMiwgMSwgMTI3LCAxLCAxMjQs
IDY4LCAwLCAwLCAwLCAwLCAwLCAwLCAyMjQsIDYzLCAzMywgMiwgMiwgNjQsIDMsIDY0LCAzMiwg
MSwgMzIsIDAsIDc5LCAxMywgMSwgMzIsIDIsIDY4LCAxNTUsIDI0MiwgMjE1LCAyNiwgMCwgMCwg
MjQwLCA2MywgMTYyLCA2OCwgMTQ5LCAyMTQsIDM4LCAyMzIsIDExLCA0NiwgMTcsIDYyLCAxNjAs
IDMzLCAyLCAzMiwgMiwgNjgsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDY0LCAxMDAsIDQsIDY0LCAz
MiwgMiwgNjgsIDAsIDAsIDAsIDAsIDAsIDAsIDI0MCwgNjMsIDE2MSwgMzMsIDIsIDExLCAzMiwg
MSwgNjUsIDEsIDEwNiwgMzMsIDEsIDEyLCAwLCAxMSwgMTEsIDMyLCAyLCAxMV0pOwpmdW5jdGlv
biBqc0xvb3AobikgeyBsZXQgeCA9IDAuNTsgZm9yIChsZXQgaSA9IDA7IGkgPCBuOyBpKyspIHsg
eCA9IHggKiAxLjAwMDAwMDEgKyAxZS05OyBpZiAoeCA+IDIpIHggLT0gMTsgfSByZXR1cm4geDsg
fQpmdW5jdGlvbiB0aW1lKGYpIHsgY29uc3QgdCA9IHBlcmZvcm1hbmNlLm5vdygpOyBjb25zdCBy
ID0gZigpOyByZXR1cm4gW3BlcmZvcm1hbmNlLm5vdygpIC0gdCwgcl07IH0KZG9jdW1lbnQuZ2V0
RWxlbWVudEJ5SWQoJ2InKS5vbmNsaWNrID0gKCkgPT4gewogIGNvbnN0IE4gPSAzMDAwMDAwMCwg
b3V0ID0gW107CiAgb3V0LnB1c2goJ29yaWdpbjogJyArIGxvY2F0aW9uLm9yaWdpbik7CiAgb3V0
LnB1c2goJ2lzU2VjdXJlQ29udGV4dDogJyArIHdpbmRvdy5pc1NlY3VyZUNvbnRleHQpOwogIG91
dC5wdXNoKCd1c2VyQWdlbnQ6ICcgKyBuYXZpZ2F0b3IudXNlckFnZW50KTsKICBvdXQucHVzaCgn
V2ViQXNzZW1ibHk6ICcgKyAodHlwZW9mIFdlYkFzc2VtYmx5ID09PSAndW5kZWZpbmVkJyA/ICdB
QlNFTlQnIDogJ3ByZXNlbnQnKSk7CiAgLy8gdGhyZWUgY29uc2VjdXRpdmUgSlMgcnVuczogYSBK
SVQgdGllcnMgdXAgYW5kIHRoZSBsYXRlciBydW5zIGdldCBmYXN0ZXI7IGFuIGludGVycHJldGVy
IHN0YXlzIGZsYXQKICBsZXQganNYOwogIGZvciAobGV0IGsgPSAxOyBrIDw9IDM7IGsrKykgeyBj
b25zdCBbbXMsIHhdID0gdGltZSgoKSA9PiBqc0xvb3AoTikpOyBqc1ggPSB4OyBvdXQucHVzaCgn
SlMgbG9vcCBydW4gJyArIGsgKyAnLCAzME0gaXRlcmF0aW9uczogJyArIG1zLnRvRml4ZWQoMCkg
KyAnIG1zJyk7IH0KICBpZiAodHlwZW9mIFdlYkFzc2VtYmx5ICE9PSAndW5kZWZpbmVkJykgewog
ICAgY29uc3QgZiA9IG5ldyBXZWJBc3NlbWJseS5JbnN0YW5jZShuZXcgV2ViQXNzZW1ibHkuTW9k
dWxlKFdBU00pKS5leHBvcnRzLmxvb3A7IGYoMTAwMCk7CiAgICBjb25zdCBbbXMsIHhdID0gdGlt
ZSgoKSA9PiBmKE4pKTsKICAgIG91dC5wdXNoKCd3YXNtIGxvb3AsIHNhbWUgMzBNIGl0ZXJhdGlv
bnM6ICcgKyBtcy50b0ZpeGVkKDApICsgJyBtcyAocmVzdWx0ICcgKyAoeCA9PT0ganNYID8gJ2Jp
dC1pZGVudGljYWwgdG8gSlMnIDogJ0RJRkZFUlMnKSArICcpJyk7CiAgfQogIGRvY3VtZW50Lmdl
dEVsZW1lbnRCeUlkKCdvJykudGV4dENvbnRlbnQgPSBvdXQuam9pbignXG4nKTsKfTsKPC9zY3Jp
cHQ+Cg==
</data>

          </attachment>
      

    </bug>

</bugzilla>