Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .github/workflows/build-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ on:
installer_base_name:
required: true
type: string
stealth_leakage_mode:
description: "Optional stealth leakage scan mode, for example stealth or stealth-novpn"
required: false
type: string
default: ""

jobs:
build-android:
Expand Down Expand Up @@ -156,6 +161,15 @@ jobs:
INSTALLER_NAME: ${{ inputs.installer_base_name }}
GOMOBILECACHE: ${{ env.GOMOBILECACHE }}

- name: Stealth leakage check
if: ${{ inputs.stealth_leakage_mode != '' }}
run: make stealth-leakage-check
Comment on lines +164 to +166
env:
STEALTH_LEAKAGE_MODE: ${{ inputs.stealth_leakage_mode }}
STEALTH_LEAKAGE_PATHS: >-
${{ inputs.installer_base_name }}${{ inputs.build_type != 'production' && format('-{0}', inputs.build_type) || '' }}.apk
${{ inputs.installer_base_name }}${{ inputs.build_type != 'production' && format('-{0}', inputs.build_type) || '' }}.aab

- name: Upload Android APK
uses: actions/upload-artifact@v4
with:
Expand Down
15 changes: 15 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ ANDROID_RELEASE_APK := $(INSTALLER_NAME)$(if $(filter-out production,$(BUILD_TYP
ANDROID_RELEASE_AAB := $(INSTALLER_NAME)$(if $(filter-out production,$(BUILD_TYPE)),-$(BUILD_TYPE)).aab
ANDROID_MAPPING_SRC := build/app/outputs/mapping/release/mapping.txt
ANDROID_SYMBOLS_SRC := build/app/outputs/native-debug-symbols/release/native-debug-symbols.zip
PYTHON ?= python3
STEALTH_LEAKAGE_MODE ?= stealth
STEALTH_LEAKAGE_CONFIG ?= scripts/stealth/forbidden_tokens.json
STEALTH_LEAKAGE_PATHS ?= $(ANDROID_RELEASE_APK) $(ANDROID_RELEASE_AAB) $(ANDROID_APK_RELEASE_BUILD) $(ANDROID_AAB_RELEASE_BUILD)
ANDROID_NDK_VERSION ?= 28.2.13676358
ANDROID_CMAKE_VERSION ?= 3.22.1
ANDROID_BUILD_TOOLS_VERSION ?= 35.0.0
Expand Down Expand Up @@ -530,6 +534,17 @@ android-release: clean android pubget gen android-apk-release
.PHONY: android-release-ci
android-release-ci: android pubget gen android-apk-release android-aab-release

.PHONY: stealth-leakage-check stealth-novpn-leakage-check
stealth-leakage-check:
$(PYTHON) scripts/stealth/check_leakage.py \
--config "$(STEALTH_LEAKAGE_CONFIG)" \
--mode "$(STEALTH_LEAKAGE_MODE)" \
--missing-ok \
$(STEALTH_LEAKAGE_PATHS)

stealth-novpn-leakage-check:
$(MAKE) stealth-leakage-check STEALTH_LEAKAGE_MODE=stealth-novpn

# iOS Build
.PHONY: install-ios-deps

Expand Down
58 changes: 58 additions & 0 deletions docs/stealth-leakage-checks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Stealth Leakage Checks

`scripts/stealth/check_leakage.py` scans built stealth artifacts for normal
Lantern identifiers. It accepts APK, AAB, ZIP-like archives, and unpacked build
directories. Archive entries are scanned recursively, and string matching checks
UTF-8, UTF-16LE, and UTF-16BE encodings.

Run the default stealth check:

```sh
make stealth-leakage-check \
STEALTH_LEAKAGE_PATHS="path/to/app.apk path/to/app.aab"
```

Run the stricter no-VPN variant:

```sh
make stealth-novpn-leakage-check \
STEALTH_LEAKAGE_PATHS="path/to/app.apk"
```

If the configured targets are absent, the Make targets skip successfully. This
keeps normal builds and ordinary CI runs from failing on stealth-only checks.

## Modes

The forbidden-token config lives at
`scripts/stealth/forbidden_tokens.json`.

`stealth` checks for:

- normal Lantern package, brand, library, service, and organization identifiers
- user-facing VPN strings
- OAuth provider strings and method-channel entry points
- billing and subscription entry points
- app-link hosts, custom schemes, and deep-link paths
- Lantern social/support URLs
- update feed and release URLs

`stealth-novpn` extends `stealth` and also checks Android VPN/TUN surfaces such
as `android.net.VpnService`, `BIND_VPN_SERVICE`, `TunOptions`, and VPN quick
tile/service actions.

## Allowlists

Each mode supports an `allowlist` in the JSON config. Allowlist entries can
match by `token`, `category`, `location` glob, and `encoding`. Example:

```json
{
"token": "Lantern",
"location": "*.SF",
"reason": "example only"
}
```

Keep allowlist entries narrow and mode-specific so real leaks still fail the
scan.
Loading
Loading