|
| 1 | +# Stealth Leakage Checks |
| 2 | + |
| 3 | +`scripts/stealth/check_leakage.py` scans built stealth artifacts for normal |
| 4 | +Lantern identifiers. It accepts APK, AAB, ZIP-like archives, and unpacked build |
| 5 | +directories. Archive entries are scanned recursively, and string matching checks |
| 6 | +UTF-8, UTF-16LE, and UTF-16BE encodings. |
| 7 | + |
| 8 | +Run the default stealth check: |
| 9 | + |
| 10 | +```sh |
| 11 | +make stealth-leakage-check \ |
| 12 | + STEALTH_LEAKAGE_PATHS="path/to/app.apk path/to/app.aab" |
| 13 | +``` |
| 14 | + |
| 15 | +Run the stricter no-VPN variant: |
| 16 | + |
| 17 | +```sh |
| 18 | +make stealth-novpn-leakage-check \ |
| 19 | + STEALTH_LEAKAGE_PATHS="path/to/app.apk" |
| 20 | +``` |
| 21 | + |
| 22 | +If the configured targets are absent, the Make targets skip successfully. This |
| 23 | +keeps normal builds and ordinary CI runs from failing on stealth-only checks. |
| 24 | + |
| 25 | +## Modes |
| 26 | + |
| 27 | +The forbidden-token config lives at |
| 28 | +`scripts/stealth/forbidden_tokens.json`. |
| 29 | + |
| 30 | +### `stealth` (base) |
| 31 | + |
| 32 | +Checks for normal Lantern package, brand, library, service, and organization |
| 33 | +identifiers; user-facing VPN strings; OAuth provider strings and method-channel |
| 34 | +entry points; billing and subscription entry points; app-link hosts, custom |
| 35 | +schemes, and deep-link paths; Lantern social/support URLs; and update feed and |
| 36 | +release URLs. |
| 37 | + |
| 38 | +### `stealth-vpn` |
| 39 | + |
| 40 | +Brand-only policy for the de-branded full-featured VPN variant. Checks the |
| 41 | +`lantern_identity` and `social_urls` categories only. Generic tokens such as |
| 42 | +`oauth`, `stripe`, `billing`, and `VPN` are intentionally allowed — login, |
| 43 | +payment, and VPN surfaces are retained in this variant. OAuth2 and the |
| 44 | +`lantern://` deep-link scheme are excluded at source (via `//go:build !stealth` |
| 45 | +build tags in `account/oauth.go`, `backend/oauth.go`, and `mobile_oauth.go`), |
| 46 | +so they are absent from the binary for the correct reason — not merely |
| 47 | +garble-encrypted. The `lantern_identity` tokens are case-insensitive substrings |
| 48 | +that catch all brand variants (`lantern.io`, `lantern://`, `org.getlantern.*`, |
| 49 | +etc.) without false positives on generic tokens. |
| 50 | + |
| 51 | +### `stealth-novpn` |
| 52 | + |
| 53 | +Extends `stealth` (full forbidden set) and also checks Android VPN/TUN surfaces |
| 54 | +such as `android.net.VpnService`, `BIND_VPN_SERVICE`, `TunOptions`, and VPN |
| 55 | +quick tile/service actions. Carries three narrow allowlist entries in |
| 56 | +`forbidden_tokens.json` for irreducible third-party strings (`oauth` from |
| 57 | +`pion/webrtc/v4` RFC 7635, `stripe` from proto field name, `/auth` from proto |
| 58 | +file descriptor path) — see the allowlist entries for full rationale. |
| 59 | + |
| 60 | +## Scanner limitations |
| 61 | + |
| 62 | +`check_leakage` and raw `strings | grep` scan the post-garble binary. When a |
| 63 | +Go package is in `GARBLE_GOGARBLE` scope, garble `-literals` encrypts string |
| 64 | +literals at compile time, so brand strings in compiled-in garble packages are |
| 65 | +absent from the static binary but present at runtime. A pass from |
| 66 | +`check_leakage` alone is not sufficient evidence of brand removal for garbled |
| 67 | +packages. |
| 68 | + |
| 69 | +See `docs/stealth-builds.md` ("Garble string-literal obfuscation blind spot" |
| 70 | +and "Standing nm -D brand-symbol gate") for the required complementary checks. |
| 71 | + |
| 72 | +## Allowlists |
| 73 | + |
| 74 | +Each mode supports an `allowlist` in the JSON config. Allowlist entries can |
| 75 | +match by `token`, `category`, `location` glob, and `encoding`. Example: |
| 76 | + |
| 77 | +```json |
| 78 | +{ |
| 79 | + "token": "Lantern", |
| 80 | + "location": "*.SF", |
| 81 | + "reason": "example only" |
| 82 | +} |
| 83 | +``` |
| 84 | + |
| 85 | +Keep allowlist entries narrow and mode-specific so real leaks still fail the |
| 86 | +scan. |
0 commit comments