Scope & ethics: This module is for authorized, lab-only testing and for defensive hardening of your own apps. We’ll cover inventorying and testing third-party SDKs, tracking transitive dependencies, vetting privacy/telemetry behavior, and securing your build/signing pipeline end-to-end. Emphasis is on evidence-driven analysis, repeatable labs, and CI/CD enforcement—not exploitation of systems outside written scope.
18.0 Learning objectives
By the end, you will be able to:
- Produce a complete SBOM (Software Bill of Materials) of your Android app (direct + transitive).
- Identify risky SDKs (over-privileged, ad/analytics, webview wrappers, crash reporters) and their network endpoints.
- Test SDK behavior dynamically (network/IPC/storage) and validate privacy assertions.
- Audit code signing, release keys, and Android App Signing settings; lock down keystore access.
- Implement reproducible builds, artifact integrity, and supply-chain controls (pinning, verifications, attestation of provenance).
- Enforce CI/CD gates for dependency risk, signature/verifier checks, and tamper resistance.
- Create a remediation plan with owners, timelines, and measurable acceptance criteria.
18.1 Threat model (SDKs & build chain)
- Dependency risk: A benign SDK update introduces sensitive data capture, trackers, or exploitable code (RCE, webview bridge exposure).
- Transitive drift: A sub-dependency pulls in vulnerable libs (e.g., outdated OkHttp, crypto misuse).
- Build system compromise: Malicious plugin/Gradle script executes during build.
- Key compromise: Release keystore leak or misconfigured Android App Signing enrollment.
- Artifact tampering: Re-signed APKs, modified bundles, or CI artifacts altered post-build.
- Telemetry/privacy: SDKs exfiltrate PII/device IDs outside policy or region.
18.2 Inventory & SBOM (what you ship)
18.2.1 Generate SBOM (CycloneDX or SPDX)
Gradle (CycloneDX plugin) example:
plugins {
id "org.cyclonedx.bom" version "1.8.2"
}
cyclonedxBom {
includeConfigs = ["releaseRuntimeClasspath"]
skipConfigs = ["debugCompileClasspath"]
projectType = "application"
schemaVersion = "1.5"
}
Run:
./gradlew :app:cyclonedxBom
# Output: app/build/reports/bom.json (CycloneDX)
What to include: group:artifact:version, checksums, licenses, PURLs, and source repositories when available.
18.2.2 Lock files & reproducibility
- Gradle version catalogs (
libs.versions.toml) with strict versions. - Dependency lock:
./gradlew dependencies --write-locks
- Check lock files into VCS; block builds that resolve new versions without a PR.
18.2.3 Map owners & purpose
Create an SDK registry:
| Library | Owner (team/vendor) | Purpose | Version | Perms used | Network domains | Data types touched |
|---|
Populate from SBOM + static scan (see §18.4).
18.3 Policy & risk classification
Define a simple, enforceable rubric:
- Tier 0 (Allowed, core): essential frameworks (AndroidX, Kotlin Stdlib).
- Tier 1 (Low-risk): small utilities, no network/PII.
- Tier 2 (Medium): analytics/crash libs with data minimization and DPAs.
- Tier 3 (High): adtech/monetization, webview wrappers, device fingerprinting.
- Forbidden: SDKs with dynamic code loading, obfuscated network egress, or known CVEs without remediation.
Every SDK must have:
- Owner and business justification.
- Data minimization statement (fields collected, retention).
- Update SLA (how fast to patch CVEs / major updates).
- Offboarding plan (how to remove cleanly).
18.4 Static analysis of SDKs
18.4.1 What to scan
- Permissions: Compare
AndroidManifest.xmlfrom AARs/merged manifest to your intent. - Exported components: Activities/Services/Receivers/Providers added by SDKs (check
android:exported, permissions). - WebView usage:
addJavascriptInterface, file access flags. - Native libs:
.sofiles (ABI coverage, dangerous syscalls in NDK code). - Crypto & RNG: look for AES/ECB, static IVs, MD5/SHA1.
- Dynamic code loading:
DexClassLoader, reflection for network-fetched code.
18.4.2 Commands / steps
Merged manifest inspection:
./gradlew :app:processReleaseMainManifest
cat app/build/intermediates/merged_manifests/release/AndroidManifest.xml | sed -n '1,300p'
Decompile AAR/JAR for SDKs:
unzip -l ~/.gradle/caches/modules-2/files-2.1/<group>/<artifact>/<version>/*.aar
# extract classes.jar and inspect with JADX
jadx -d out classes.jar
grep -RIn "@JavascriptInterface|DexClassLoader|Cipher.getInstance|addJavascriptInterface" out/
Permissions diff:
- Capture before/after merged manifest; fail CI if SDK inflates permissions beyond policy.
18.5 Dynamic analysis of SDK behavior (lab)
18.5.1 Network egress mapping
- Run app through mitmproxy/Burp (lab CA installed).
- Exercise screens using each SDK feature; export HTTP history.
- Classify endpoints (analytics, crash, ad, config, feature flags).
- Record payload schema: fields sent, identifiers (GAID/AAID, Android ID, vendor IDs), any PII.
Evidence to keep: proxy project file, PCAPs, annotated endpoints table, timestamps (UTC), app/SDK versions.
18.5.2 Storage & device artifacts
- Inspect app private storage for SDK caches, databases, crash attachments.
- Look for PII in plaintext or long-lived unique identifiers.
- Verify data deletion on logout and on “Delete account” flows.
18.5.3 IPC & component exposure
- Attempt to start/bind exported components from SDKs (see Module 14 commands).
- Confirm signature/permission guards.
18.5.4 Feature toggles & remote config
- Capture SDK bootstraps (config JSON).
- Validate that remote flags cannot enable hidden debugs, logging of PII, or dynamic code without app update.
18.6 Privacy & data governance
- Maintain a data inventory per SDK: what fields, lawful basis, retention, region routing (e.g., EU vs. US).
- Enforce user consent gates before initializing telemetry (IAB TCF 2 for ads where applicable).
- Support opt-out paths and Do Not Track where required.
- Configure crash/analytics SDKs to scrub secrets (beforeSend hooks).
- Ensure child/age gates if app may serve minors.
Deliver a Privacy Controls Matrix:
| SDK | Init gated by consent? | PII collected | Region | Retention | Scrubbing hooks |
|---|
18.7 Build & signing integrity
18.7.1 Keystore hygiene (self-managed)
- Store release keystore in HSM/KMS or a sealed secrets store; never in repo.
- Use per-environment signing configs; restrict access by role.
- Rotate upload keys and signing keys per policy; document procedures.
- Enforce sig alg: e.g., SHA-256 with RSA-2048+/ECDSA-P256.
Gradle (safe loading via env):
android {
signingConfigs {
release {
storeFile file(System.getenv("KEYSTORE_PATH"))
storePassword System.getenv("KEYSTORE_PASS")
keyAlias System.getenv("KEY_ALIAS")
keyPassword System.getenv("KEY_PASS")
enableV3Signing true
enableV4Signing true
}
}
}
18.7.2 Android App Signing (Play)
- Understand upload key vs app signing key.
- Enforce 2FA, restricted console roles, and signing key upgrade plan.
- Keep off-store distribution (enterprise) with separate key lineage.
18.7.3 Provenance & tamper detection
- Use reproducible builds: fixed timestamps, stable ordering, documented environment (JDK, AGP, R8).
- Verify APK Signature Scheme v2/v3/v4 presence.
- Check integrity post-build:
apksigner verify --print-certs app-release.apk
jarsigner -verify -verbose -certs app-release.apk
- Hash artifacts and publish checksums/SLSA provenance (see §18.11).
18.8 Reproducible & deterministic builds
- Pin Android Gradle Plugin, Gradle, JDK versions.
- Use Docker/remote build runners with immutable images.
- Normalize file timestamps (Gradle supports reproducibility for many tasks).
- Avoid embedding build time or git SHA directly into app unless isolated under a single resource (documented) to compare.
Provenance record (example fields): AGP version, Gradle version, JVM, OS image hash, dependency lock hash, commit SHA.
18.9 Dependency risk management (CI gates)
18.9.1 Automated scanners
- OWASP Dependency-Check, Snyk, OWASP DC Gradle plugin, or commercial equivalents.
- Fail on CVSS ≥ threshold; create ticket with affected SDK, loaded code paths, SLA.
18.9.2 Allowlist/denylist
- Maintain a permit list for approved SDK coordinates.
- Denylist classes/APIs (e.g.,
DexClassLoader,addJavascriptInterface) unless justified with a waiver.
18.9.3 Release checklist
- SBOM attached to release artifact.
- Signatures verified in CI.
- Diff of merged manifest vs previous release (permissions, exported comps).
- Network endpoint diff (from lab capture) signed off.
18.10 Runtime defenses & anti-tamper (client-side)
- Integrity signals: Use Play Integrity/Key Attestation (Module 12) to tie app identity and signing cert digest to server policy.
- Pinning: SPKI pin to your API; don’t pin to SDK endpoints you don’t control (or do so only with vendor coordination).
- Self-checks: Optional code to verify embedded SDK code hashes at runtime—treat as telemetry only; decisions remain server-side.
18.11 Build provenance & artifact supply-chain
- Adopt SLSA (Supply-chain Levels for Software Artifacts) level appropriate to your org.
- Produce attestations (in-toto) that bind SBOM + source + builder identity to the artifact.
- Store release artifacts and provenance in an immutable registry (e.g., OCI-style, artifact repository).
Minimal provenance JSON (example fields):
{
"builder": "gh-runner-image@sha256:...",
"source": "git@repo#commit:abc123",
"dependencies_lock": "sha256:...",
"sbom": "cyclonedx@sha256:...",
"apksigner_cert_shas": ["sha256:..."],
"time_utc": "2025-09-27T15:00:00Z"
}
18.12 Evidence model & severity rubric
18.12.1 Evidence to collect
- SBOM (JSON) + checksum.
- Merged manifest diff (permissions/components).
- Proxy/PCAP logs annotated with SDK endpoint mapping.
- Storage artifacts showing SDK caches/PII (hashed).
- Signing verification output & cert chain details.
- CI logs for dependency scans and signature checks.
- Team approvals/waivers tied to release.
18.12.2 Severity (examples)
- Critical: SDK exfiltrates credentials/PII without consent; dynamic code loading from untrusted origin; signing keys exposed; tampered build shipped.
- High: SDK adds exported component enabling unauthorized actions; serious CVE in active code path; analytics sends stable device ID + PII without controls.
- Medium: Over-collection of metadata; missing consent gating; inflated permissions unused by app.
- Low: Non-actionable metadata gaps; outdated SDK with no known exploitable vector.
18.13 Practical labs (authorized, reproducible)
Lab 18-A — SBOM + permission drift
- Generate CycloneDX SBOM for
releaseRuntimeClasspath. - Build baseline manifest and a build with a new SDK; diff permissions/exported components.
- Output an alert in CI if drift detected.
Deliverables: SBOM JSON, manifest diff, CI log snippet.
Lab 18-B — SDK network behavior
- In a lab device, enable proxy and exercise screens using SDK features.
- Export Burp/mitm session; tag flows per SDK.
- Produce endpoint inventory with payload schemas; mark PII.
Deliverables: proxy project, endpoints CSV, screenshots, hashes.
Lab 18-C — Crash/analytics PII scrubbing
- Trigger handled/unhandled exceptions.
- Verify beforeSend scrubber masks tokens/passwords.
- Prove opt-out path prevents telemetry init.
Deliverables: SDK config, request samples before/after scrub, app logs.
Lab 18-D — Signing & provenance
- Verify APK signature with
apksigner, extract signer cert SHA-256. - Rebuild in clean runner; compare SHA/size diffs and record provenance JSON.
- Validate reproducibility criteria or explain deviations (R8 mapping, timestamps).
Deliverables: apksigner output, provenance record, notes on determinism.
18.14 Developer hardening checklist (copy-paste into PR template)
- SBOM generated; no unapproved SDKs introduced.
- Merged manifest reviewed; no unexpected permissions/exported comps.
- SDKs initialized after consent; telemetry scrubbers configured.
- No dynamic code loading; no
DexClassLoaderwithout waiver. - WebView settings in SDK UIs audited; no bridges on remote content.
- Storage review: SDK caches don’t store PII in plaintext; cleared on logout.
- Dependency scan: no High/Critical CVEs unresolved.
- Signing setup: keys not in repo; CI uses env-injected secrets; v2/v3 signing on.
- Provenance & checksums attached to artifacts.
- Endpoint inventory updated; privacy matrix updated.
18.15 CI/CD guardrails (ready-to-adopt)
- Step 1 (SBOM): generate CycloneDX; upload as artifact.
- Step 2 (Deps scan): run Snyk/OWASP DC on SBOM; fail on thresholds.
- Step 3 (Manifest diff): parse merged manifest and compare to previous release; fail on drift without
SECURITY_APPROVED=true. - Step 4 (Sign verify): run
apksigner verify; capture signer cert SHA-256; compare to allowlist. - Step 5 (Provenance): emit JSON attestation with environment hash; publish alongside APK/AAB.
- Step 6 (Waiver ledger): PR labels with risk tier and expiry date; require security sign-off.
18.16 Communication & vendor management
- Maintain vendor contacts, DPAs, and security advisories subscription for each SDK.
- Request changelogs and data maps before version upgrades.
- For high-risk SDKs, require security review call and a sandbox test prior to rollout.
- Establish rollback plans and feature flags to disable SDK runtime.
18.17 Common pitfalls & how to avoid them
- “It’s only analytics” → still can exfiltrate PII; gate by consent; scrub aggressively.
- Silent permission creep → always diff merged manifest.
- Unpinned, silent updates → pin versions; require PR to bump.
- Keystore in repo → move to KMS/HSM; rotate keys; restrict access.
- Builds on dev laptops → move to hardened, reproducible CI runners.
- Opaque vendor behavior → insist on endpoint lists, data dictionaries, and SDK privacy modes.
18.18 Deliverables
- SDK Registry & Privacy Matrix (owners, endpoints, data).
- SBOM (CycloneDX/SPDX) + dependency risk report.
- Manifest & endpoint diffs for each release.
- Signing/provenance bundle (apksigner output, provenance JSON, checksums).
- CI policy files (lockfiles, deny/allow lists, scan configs).
- Waiver ledger with expiry and mitigation plan.
18.19 “At a glance” cheat-sheet
- Know what you ship: SBOM + endpoint inventory.
- Gate everything: consent, permissions, manifests, versions.
- Least data: scrub, minimize, regionalize.
- Lock the chain: signed, reproducible builds; keys in KMS; provenance attached.
- Automate drift detection: manifest/endpoint diffs in CI.
- Own your SDKs: named owners, update SLAs, offboarding paths.
