Skip to content

[stealth 03/11] Stealth Lantern: randomize Android build identity#8781

Closed
reflog wants to merge 15 commits into
mainfrom
stealth/8765-android-identity-randomization
Closed

[stealth 03/11] Stealth Lantern: randomize Android build identity#8781
reflog wants to merge 15 commits into
mainfrom
stealth/8765-android-identity-randomization

Conversation

@reflog

@reflog reflog commented May 15, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add a deterministic/random Stealth Android identity profile generator
  • wire Android Gradle to consume profile values for applicationId, labels, auth scheme, metadata, BuildConfig, manifest placeholders, and app name resValue
  • move VPN session, notification, and quick settings tile visible labels to generated BuildConfig values
  • add neutral Android icon resources, Make/CI wiring, docs, and generator tests

Dependency / non-goals

This closes getlantern/engineering#3566 for per-build install identity and native Android identity surfaces. Static inspection can still find source namespace/class/action strings such as org.getlantern and LanternVpnService until the manifest/source minimization work lands; this PR intentionally depends on getlantern/engineering#3571 for that broader minimization instead of expanding this branch.

Verification

  • python3 -m unittest discover -s scripts/stealth -p '*_test.py'
  • make android-identity-profile BUILD_TYPE=stealth ANDROID_IDENTITY_SEED=issue-8765-test
  • make -n android-apk-release BUILD_TYPE=stealth ANDROID_IDENTITY_SEED=issue-8765-test
  • python3 -m py_compile scripts/stealth/generate_android_identity.py scripts/stealth/generate_android_identity_test.py
  • git diff --check

Closes getlantern/engineering#3566

Copilot AI review requested due to automatic review settings May 15, 2026 13:05
@reflog reflog self-assigned this May 15, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds build-time “identity profiles” for Stealth Android builds so each artifact can have a distinct install identity (applicationId, labels, scheme, icons, and various user-visible strings), while keeping normal builds on the existing Lantern identity.

Changes:

  • Introduces a Python generator + unit tests to produce deterministic (seeded) or random Android identity .properties profiles.
  • Wires Android Gradle/manifest placeholders + BuildConfig fields to consume identity profile values (applicationId, labels, auth scheme, metadata, notification/tile strings, icons).
  • Adds Make/CI/docs plumbing and neutral icon resources to support reproducible Stealth builds.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
scripts/stealth/generate_android_identity.py Generates Android identity profiles (applicationId, labels, metadata, icons, strings).
scripts/stealth/generate_android_identity_test.py Unit tests for deterministic/random generation and properties output.
Makefile Adds identity profile generation and injects ANDROID_IDENTITY_PROFILE into Flutter Android builds.
docs/stealth-android-identity.md Documents how to generate/use identity profiles and schema.
android/app/src/main/res/values/string.xml Removes static app_name so Gradle resValue can control it per build.
android/app/src/main/res/drawable/neutral_notification_icon.xml Adds neutral notification small icon vector.
android/app/src/main/res/drawable/neutral_app_icon.xml Adds neutral app icon vector.
android/app/src/main/kotlin/org/getlantern/lantern/service/QuickTileService.kt Uses BuildConfig-provided quick settings tile labels.
android/app/src/main/kotlin/org/getlantern/lantern/service/LanternVpnService.kt Uses BuildConfig-provided VPN session name.
android/app/src/main/kotlin/org/getlantern/lantern/notification/NotificationManager.kt Uses BuildConfig-provided notification strings + resolves small icon from BuildConfig.
android/app/src/main/AndroidManifest.xml Switches app labels/icons/schemes to manifest placeholders; adds identity meta-data placeholders.
android/app/build.gradle Loads identity profile, validates applicationId, sets manifest placeholders, resValue app_name, and BuildConfig fields.
.github/workflows/build-android.yml Adds optional android_identity_seed input passed through to builds.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread android/app/src/main/AndroidManifest.xml Outdated
Comment thread Makefile Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Comment thread android/app/build.gradle

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Comment thread android/app/build.gradle
Comment thread android/app/src/main/res/drawable/neutral_notification_icon.xml Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Comment thread docs/stealth-android-identity.md

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.

Comment thread android/app/build.gradle Outdated
Comment thread android/app/src/main/AndroidManifest.xml
Comment thread scripts/stealth/generate_android_identity.py Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.

Comment thread Makefile Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 2 comments.

Comment thread scripts/stealth/generate_android_identity.py Outdated
Comment thread lib/core/common/app_build_info.dart Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.

Comment thread docs/stealth-android-identity.md Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

lib/lantern_app.dart:199

  • _buildPrivateServerAccessKey() now accepts any AppBuildInfo.appAuthScheme URI, but still normalizes the returned access key to a hardcoded lantern//... prefix and the comment/example also hardcode lantern://.... If the intention is to preserve the randomized scheme end-to-end (or to avoid leaking "lantern" into a user-visible access key), update the normalization and comment to use AppBuildInfo.appAuthScheme (or add an explicit comment explaining why the lantern// prefix must remain constant).
    if (AppBuildInfo.isAppAuthUri(uri)) {
      // lantern://private-server?key=value → lantern//private-server?key=value
      var accessKey = 'lantern//${uri.host}';
      if (uri.hasQuery) {
        accessKey += '?${uri.query}';
      }
      return accessKey;

Comment thread Makefile Outdated
Comment thread scripts/stealth/generate_android_identity.py Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated no new comments.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated no new comments.

@reflog

reflog commented May 18, 2026

Copy link
Copy Markdown
Contributor Author

@copilot review

Copilot AI commented May 18, 2026

Copy link
Copy Markdown
Contributor

@copilot review

Ran a fresh review pass on commit ad2f3e4; there are no new actionable findings to address in this branch.

Copilot finished work on behalf of reflog May 18, 2026 10:17
reflog and others added 15 commits June 11, 2026 12:40
Adds scripts/stealth/generate_profile.py for private stealth-vpn/stealth-novpn
build profiles and wires profile values through Make targets, Flutter dart
defines, Android Gradle, manifest app label, session name, and Go build tags.

Key additions:
- generate_profile.py: validates/generates stealth profile JSON, emits
  dart-defines and artifact metadata (seed redacted to hash only)
- Makefile: STEALTH_PROFILE_TOOL/ENV/DART_DEFINES/GO_TAGS variables, stealth-
  profile target with incremental caching, wired into all platform build targets
- android/app/build.gradle: loadStealthProfile() with strict validation for
  mode/packageName/appName/sessionName/denylistVersion; STEALTH_* BuildConfig
  fields; dynamic applicationId from profile
- AndroidManifest.xml: ${appName} placeholder for manifest label
- LanternVpnService.kt: uses BuildConfig.STEALTH_SESSION_NAME
- app_build_info.dart: STEALTH_MODE/ENABLED/PACKAGE_NAME/APP_NAME/SESSION_NAME
  compile-time constants; isStealthBuild helper
- docs/stealth-build-profile.md: profile generation guide

Conflict resolution notes (rebased onto main's arm64-only + sideload changes):
- Android build targets now have BOTH stealth wiring (STEALTH_PROFILE_ENV,
  MAYBE_STEALTH_PROFILE, STEALTH_DART_DEFINES) AND main's -Plantern.sideloadUpdates=true
  + ANDROID_APK/AAB_TARGET_PLATFORMS variables
- build.gradle has BOTH sideload cert verification AND stealth profile loading
- abiFilters: arm64-v8a only (aligning with main's arm64-only direction)

Closes getlantern/engineering#3571

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Manifest: remove app.identity.{label,profile_id,metadata} meta-data tags
— these embedded identityMetadata (containing "android-identity-v1",
"source":"stealth-profile", profileMode, seedFingerprint) directly in
the shipped artifact, readable via aapt2 without decompilation. Traceability
belongs in the private support profile, keyed by build ID (QA policy #3576).

Generator: strip "generator"/"source"/"profileMode"/"seedFingerprint" from
identityMetadata output in both identity_from_profile() and generate_identity()
so no stealth-identifying strings land in BuildConfig.ANDROID_IDENTITY_METADATA.
The fallback scheme in generate_identity now uses "id" prefix instead of "stealth".

Normal builds unaffected: identity meta-data defaults were inert (Lantern/standard/{}).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@reflog reflog force-pushed the stealth/8765-android-identity-randomization branch from ad2f3e4 to 72c39f0 Compare June 11, 2026 11:30
@reflog

reflog commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

Integration Notes for #8781 → Integration PR #8794

These items require attention when integrating this branch:

1. buildConfigString deduplication

buildConfigString is defined in both #8781 (android/app/build.gradle) and #8784 (the foundation build-profile PR). The integrator should dedupe to #8784's version — it has more complete escaping logic. Remove the duplicate definition from the #8781 contribution at integration time.

2. defaultConfig.applicationId + manifestPlaceholders collision

Both #8781 and #8784 set defaultConfig.applicationId and populate manifestPlaceholders. Reconcile to a single identity source at integration: the architectural intent is applicationId = stealthProfile.packageName (from #8784's profile plumbing), with #8781's identity profile providing all other placeholders. Do not have two blocks clobbering each other at integration.

@reflog reflog left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressing remaining review comments.

Comment thread scripts/stealth/generate_android_identity.py Outdated
Comment thread docs/stealth-android-identity.md Outdated
Comment thread Makefile Outdated
Comment thread scripts/stealth/generate_android_identity.py Outdated
Comment thread Makefile Outdated
Comment thread android/app/build.gradle Outdated
Comment thread lib/lantern_app.dart Outdated

@reflog reflog left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.

Comment thread lib/core/common/app_build_info.dart Outdated
@reflog

reflog commented Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

Superseded — the 11 per-issue stealth PRs were consolidated into a 6-PR stack for epic getlantern/engineering#3569. This work now lives in #8860.

@reflog reflog closed this Jun 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants