Skip to content

Security model

The reference study is A Small Leak Will Sink Many Ships: Vulnerabilities in Mini-Programs (arXiv 2205.15202). It tested more than 2,580 APIs across 9 mini-program ecosystems, and its result is the honest starting point for anything new in this category:

Every one of the nine ecosystems examined had at least one vulnerability.

There is no secure implementation here to copy. There is a catalogue of how everyone got it wrong.

Section 3.2 of the paper names six categories. They are Sollar’s review checklist and the agenda for its internal penetration testing.

One mini app reads a file cached by another, because the host stores everything in a common directory.

Sollar: a synthetic origin per mini app. Cache, localStorage, IndexedDB and cookies are partitioned by the browser engine, not by a directory convention. It is the difference between a rule the runtime remembers to apply and one it cannot violate.

2. PEL-API — permission encapsulated in a leaked API

Section titled “2. PEL-API — permission encapsulated in a leaked API”

A high-level API internally invokes a privileged capability and, once exposed, hands the privilege over for free. The paper’s example: obtaining the latitude and longitude of a map’s centre “without the user’s authorisation”, through a map context function.

Sollar: the bridge is minimal by construction, and every method is audited against one question — what capability does this grant indirectly? A method that accepts a broad configuration object is suspect by default, because that is where the extra capability hides. Where a web equivalent exists it is used instead: navigator.geolocation already carries the engine’s own prompt and has no side path through another API.

Data leaves for a remote server without the user noticing. The paper cites the clipboard: “the copied text could be sent to a remote server without user’s awareness.”

Sollar: a network allowlist in the signed manifest, enforced in the native request interceptor. Changing a destination requires a new version and a new gate. CSP is the second layer — a mini app can rewrite its own CSP at runtime, but it cannot reach the native interceptor.

A permission granted once lasts forever, leaks between contexts, or cannot be revoked.

Sollar: permissions are keyed on (user, mini app, scope) and revocable at any time. Host app permissions do not flow to a mini app — required by Apple’s Guideline 4.7.3 and enforced on both platforms. And the mandatory purpose string turns the grant into a contestable claim at review rather than a technical checkbox.

An embedded webview component loads external content that escapes the runtime’s permission model.

Sollar: there is no <web-view> component. External content opens in the system browser via sollar.ui.openExternal(), with a visible address bar and lock icon.

This is a deliberate amputation. WeChat’s web-view requires a business-domain allowlist covering nested iframes and still is the vector for this entire category. The feature is not worth its attack surface.

6. Permission divergence across environments

Section titled “6. Permission divergence across environments”

The permission model behaves differently in development, trial and production — and the hole exists in only one of them.

Sollar: the same permission-checking code in all three environments. What changes between environments is data and endpoints, never the authorisation path. The conformance suite runs the same permission tests against all three.

ControlRule
BridgeWebViewCompat.addWebMessageListener with allowedOriginRules. Never addJavascriptInterface.
Serving the packageWebViewAssetLoader + shouldInterceptRequesthttps://<appid>.miniapp.localhost/
File accesssetAllowFileAccessFromFileURLs(false), setAllowUniversalAccessFromFileURLs(false), setAllowFileAccess(false)
Safe BrowsingEnabled
RendererSeparate process, with WebViewRenderProcessClient to detect a hang
PrioritysetRendererPriorityPolicy — the mini app’s renderer is sacrificed before the host

allowedOriginRules matches scheme, host and port; the path is ignored.

ControlRule
BridgeWKScriptMessageHandlerWithReply in a dedicated WKContentWorld
Serving the packageWKURLSchemeHandler — see the secure-context risk in Architecture
StorageWKWebsiteDataStore(forIdentifier:) per mini app; nonPersistent() for ephemeral mode
DomainsWKAppBoundDomains where applicable — capped at 10 domains, which makes it unusable as a per-mini-app control
JITPresent in the WebContent process — an advantage, not a risk

The submission validator refuses a package that does not meet:

default-src 'self';
script-src 'self'; ← no 'unsafe-eval', no remote host
object-src 'none';
base-uri 'none';
frame-ancestors 'none';
connect-src 'self' <manifest hosts>

script-src 'self' with no remote host is also what keeps Sollar inside Google Play’s interpreter exemption: every executable byte arrives in the verified package. A mini app pulling a script from a CDN is, technically, downloading executable code from outside it.

A third-party resource that genuinely must be remote requires Subresource Integrity with a pinned hash.

Per instance: a ceiling on concurrent connections, on storage, and on memory — with the mini app destroyed rather than the host running out of memory — plus a rate limit per bridge method. A mini app cannot degrade Sollar for the user.

Beyond the six categories:

  1. The manifest validates, and every permission has a purpose plausible for the declared function.
  2. The network allowlist is justifiable — an unexplained host is a question to the developer.
  3. The CSP meets the floor.
  4. An SBOM is present, with no high-severity CVE in a shipped dependency.
  5. No remote scripts, no eval, no obfuscation that defeats review.
  6. actions[] describe honestly what they do; destructive is set where it is destructive.
  7. Reporting and blocking are reachable (Guideline 4.7.1); a content rating is declared (4.7.5).

The submission pipeline: validate the manifest → scan the SBOM against vulnerability data → check the CSP → static analysis for prohibited patterns (eval, Function(), remote scripts) → dynamic tests for all six categories, with a deliberately malicious mini app kept as a permanent test case.

TaintMini (ICSE 2023), a static taint-analysis tool for mini programs, is a candidate for the pipeline.

Stated plainly, because a security page that claims completeness is not a security page.

  1. Secure context on iOS. If a custom scheme is not a secure context, crypto.subtle and service workers are unavailable inside mini apps and the storage design changes. Verified per release.
  2. Obfuscation versus review. WeChat ships code obfuscation as a first-party plugin with a reversible sourcemap. Obfuscation that review cannot undo is incompatible with real review; the policy must be settled before the store opens.
  3. No independent audit yet. Nothing described here has been tested by an outside team. Before opening the store to unvetted third parties, penetration testing with a written scope, an isolated environment and synthetic data is a precondition, not a nice-to-have.