Skip to content

feat(mobile): android app shell - #1068

Open
SeanDuggan wants to merge 15 commits into
OWASP:devfrom
SeanDuggan:mobile-split/04-android-app-shell
Open

SeanDuggan wants to merge 15 commits into
OWASP:devfrom
SeanDuggan:mobile-split/04-android-app-shell

Conversation

@SeanDuggan

Copy link
Copy Markdown
Member

Summary

Adds the Mobile Shepherd Android app shell. It has no lessons or challenges; those arrive one OWASP Mobile category per PR, after this merges.

Part 3 of the split of #894. Depends on the module IDs/cheatsheets PR and the server API PR.

Included

  • Gradle project under mobile/
  • Landing, login, home, Preferences and ADB Reference screens
  • Navigation drawer with a "Completed" group driven by module registries
  • Server sign-in/registration (AuthManager), scoreboard, progress tracking and badges
  • KeyValidator (server-validated keys), KeyProvider, ModuleInfoHelper
  • Empty module registries and KeyValidator.Module enum, which each category PR fills in

Security notes

  • HTTP is not allowed in this PR. The network security config sets cleartextTrafficPermitted=false, and the app only accepts an https:// server URL (AuthManager.isSecureServerUrl).
  • Cleartext exceptions are added only by the insecure-communication modules, scoped to their own hosts.
  • Debug builds trust user-installed CAs so a proxy such as Burp can be used. Release builds do not.
  • No platform (Java/JSP/server) changes are in this PR.

Testing

  • ./gradlew assembleDebug testDebugUnitTest passes.
  • Smoke-tested on an Android emulator (API 34+): the app launches, Home/ADB Reference/Scoreboard navigation works, and no crashes appear in logcat.

Adds the Gradle project, manifest, resources, launch/login/main activities,
navigation, preferences, authentication, key validation and progress
tracking utilities, and the home, progress, scoreboard and ADB reference
screens. Lesson and challenge screens referenced by the navigation graph are
added in the following PRs, so those destinations are not usable until then.

Part of the split of OWASP#894 (mobile app).
Disable cleartext traffic app-wide via a network security config and reject non-https server URLs at login, registration and key validation. Debug builds additionally trust user-installed CAs for local development.
The shell now builds with an empty KeyValidator.Module enum and empty
nav, menu and module-info registries. Each lesson/challenge category PR
registers its own entries. Removes the myapp://open deep link and the
KeyValidator unit test, which return with the first category.
Removes lesson/challenge strings and the Insufficient Cryptography ADB
reference card. These return with their own category PRs.
@SeanDuggan SeanDuggan changed the title Mobile split/04 android app shell Mobile android app shell Oct 26, 2026
@SeanDuggan SeanDuggan self-assigned this Oct 26, 2026
@SeanDuggan
SeanDuggan requested a review from ismisepaul October 26, 2026 19:19
@SeanDuggan SeanDuggan changed the title Mobile android app shell feat(mobile): android app shell Oct 26, 2026
@ismisepaul
ismisepaul requested a balanced review from Copilot October 26, 2026 20:01

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.

🟡 Changes recommended

Unresolved critical issues can break builds, crash sign-in on supported Android versions, and expose session cookies through server-address changes, backups, and insufficient release certificate restrictions on older devices.

8 open issues
What changed in this PR

Adds the unified Mobile Shepherd Android app shell, establishing the shared interface and server integration for later lesson and challenge PRs split from #894. This PR does not add training modules or change the server platform.

Changes:

  • Introduces the Gradle Android project, app configuration, and HTTPS network policy.
  • Adds landing, authentication, Home, Preferences, ADB Reference, and Scoreboard interfaces.
  • Provides navigation, progress tracking, badges, and key-management infrastructure with empty module registries.
File Description
mobile/​settings.gradle Defines repositories and the app module.
mobile/​scripts/​calculate_key_hashes.py Generates training-key hashes.
mobile/​gradlew.bat Adds the Windows Gradle launcher.
mobile/​gradlew Adds the POSIX Gradle launcher.
mobile/​gradle/​wrapper/​gradle-wrapper.properties Pins the Gradle distribution.
mobile/​gradle.properties Configures Gradle and Android resources.
mobile/​build.gradle Declares Android build plugins.
mobile/​app/​src/​main/​res/​xml/​preferences.xml Defines application preferences.
mobile/​app/​src/​main/​res/​xml/​network_security_config.xml Configures HTTPS and debug CA trust.
mobile/​app/​src/​main/​res/​xml/​file_paths.xml Defines FileProvider sharing paths.
mobile/​app/​src/​main/​res/​xml/​data_extraction_rules.xml Adds modern backup configuration.
mobile/​app/​src/​main/​res/​xml/​backup_rules.xml Adds legacy backup configuration.
mobile/​app/​src/​main/​res/​values/​themes.xml Defines the Material application theme.
mobile/​app/​src/​main/​res/​values/​strings.xml Supplies interface text and commands.
mobile/​app/​src/​main/​res/​values/​dimens.xml Defines default spacing.
mobile/​app/​src/​main/​res/​values/​colors.xml Defines the light-mode palette.
mobile/​app/​src/​main/​res/​values-w600dp/​dimens.xml Adjusts spacing for wider screens.
mobile/​app/​src/​main/​res/​values-w1240dp/​dimens.xml Adjusts spacing for large screens.
mobile/​app/​src/​main/​res/​values-night/​themes.xml Defines dark-mode theme overrides.
mobile/​app/​src/​main/​res/​values-night/​colors.xml Defines the dark-mode palette.
mobile/​app/​src/​main/​res/​values-land/​dimens.xml Adjusts landscape spacing.
mobile/​app/​src/​main/​res/​navigation/​mobile_navigation.xml Declares shell navigation destinations.
mobile/​app/​src/​main/​res/​mipmap-anydpi-v26/​ic_launcher.xml Defines an adaptive launcher icon.
mobile/​app/​src/​main/​res/​mipmap-anydpi-v26/​ic_launcher_round.xml Defines a round adaptive icon.
mobile/​app/​src/​main/​res/​menu/​main.xml Adds toolbar menu actions.
mobile/​app/​src/​main/​res/​menu/​activity_main_drawer.xml Defines the Home menu entry.
mobile/​app/​src/​main/​res/​layout/​nav_item_layout.xml Defines expandable navigation rows.
mobile/​app/​src/​main/​res/​layout/​nav_header_main.xml Adds branding and authentication controls.
mobile/​app/​src/​main/​res/​layout/​nav_drawer_layout.xml Arranges the drawer header and list.
mobile/​app/​src/​main/​res/​layout/​item_user_result.xml Defines a user-result card.
mobile/​app/​src/​main/​res/​layout/​item_scoreboard_entry.xml Displays rankings, medals, and scores.
mobile/​app/​src/​main/​res/​layout/​item_module_progress.xml Displays module completion details.
mobile/​app/​src/​main/​res/​layout/​fragment_scoreboard.xml Defines scoreboard loading and result states.
mobile/​app/​src/​main/​res/​layout/​fragment_progress.xml Defines progress totals and module lists.
mobile/​app/​src/​main/​res/​layout/​fragment_preferences.xml Adds a placeholder preferences layout.
mobile/​app/​src/​main/​res/​layout/​fragment_home.xml Defines welcome and authentication cards.
mobile/​app/​src/​main/​res/​layout/​dialog_lesson_info.xml Provides a reusable module-information layout.
mobile/​app/​src/​main/​res/​layout/​dialog_auth.xml Defines the authentication dialog form.
mobile/​app/​src/​main/​res/​layout/​content_main.xml Hosts navigation content.
mobile/​app/​src/​main/​res/​layout/​app_bar_main.xml Arranges the toolbar and help buttons.
mobile/​app/​src/​main/​res/​layout/​activity_main.xml Combines app content and drawer.
mobile/​app/​src/​main/​res/​layout/​activity_login.xml Defines sign-in and registration forms.
mobile/​app/​src/​main/​res/​layout/​activity_landing.xml Defines the introduction and warning screen.
mobile/​app/​src/​main/​res/​drawable/​side_nav_bar.xml Adds a navigation gradient.
mobile/​app/​src/​main/​res/​drawable/​shepherd_background.xml Composes the branded screen background.
mobile/​app/​src/​main/​res/​drawable/​shape.xml Adds a bordered rectangular background.
mobile/​app/​src/​main/​res/​drawable/​nav_header_background.xml Composes the drawer-header background.
mobile/​app/​src/​main/​res/​drawable/​ic_status_incomplete.xml Adds an incomplete-status icon.
mobile/​app/​src/​main/​res/​drawable/​ic_status_complete.xml Adds a completion icon.
mobile/​app/​src/​main/​res/​drawable/​ic_menu_web.xml Adds a web navigation icon.
mobile/​app/​src/​main/​res/​drawable/​ic_menu_warning.xml Adds a warning icon.
mobile/​app/​src/​main/​res/​drawable/​ic_menu_slideshow.xml Adds a slideshow icon.
mobile/​app/​src/​main/​res/​drawable/​ic_menu_shield.xml Adds a shield icon.
mobile/​app/​src/​main/​res/​drawable/​ic_menu_settings.xml Adds a settings icon.
mobile/​app/​src/​main/​res/​drawable/​ic_menu_network.xml Adds a network icon.
mobile/​app/​src/​main/​res/​drawable/​ic_menu_lock.xml Adds a lock icon.
mobile/​app/​src/​main/​res/​drawable/​ic_menu_link.xml Adds a link icon.
mobile/​app/​src/​main/​res/​drawable/​ic_menu_key.xml Adds a key icon.
mobile/​app/​src/​main/​res/​drawable/​ic_menu_home.xml Adds the Home icon.
mobile/​app/​src/​main/​res/​drawable/​ic_menu_gallery.xml Adds a gallery icon.
mobile/​app/​src/​main/​res/​drawable/​ic_menu_database.xml Adds a database icon.
mobile/​app/​src/​main/​res/​drawable/​ic_menu_code.xml Adds a code icon.
mobile/​app/​src/​main/​res/​drawable/​ic_menu_camera.xml Adds a navigation icon resource.
mobile/​app/​src/​main/​res/​drawable/​ic_menu_alert.xml Adds an alert icon.
mobile/​app/​src/​main/​res/​drawable/​ic_launcher_background.xml Adds launcher background artwork.
mobile/​app/​src/​main/​res/​drawable/​ic_expand_more.xml Adds the drawer expansion indicator.
mobile/​app/​src/​main/​res/​drawable/​grassbackground.xml Adds a tiled branded background.
mobile/​app/​src/​main/​res/​drawable/​card_ripple.xml Defines card touch feedback.
mobile/​app/​src/​main/​res/​drawable/​button_scale_animation.xml Defines button scaling states.
mobile/​app/​src/​main/​res/​drawable/​bg_scoreboard_row.xml Styles scoreboard rows.
mobile/​app/​src/​main/​res/​drawable/​bg_medal_silver.xml Styles silver medal indicators.
mobile/​app/​src/​main/​res/​drawable/​bg_medal_gold.xml Styles gold medal indicators.
mobile/​app/​src/​main/​res/​drawable/​bg_medal_bronze.xml Styles bronze medal indicators.
mobile/​app/​src/​main/​res/​drawable/​animation.xml Defines a frame animation.
mobile/​app/​src/​main/​res/​drawable-v24/​ic_menu.xml Adds an API-qualified menu icon.
mobile/​app/​src/​main/​res/​drawable-v24/​ic_launcher_foreground.xml Adds launcher foreground artwork.
mobile/​app/​src/​main/​res/​drawable-v24/​ic_launcher_background.xml Adds API-qualified launcher artwork.
mobile/​app/​src/​main/​res/​drawable-v24/​animation.xml Adds an API-qualified frame animation.
mobile/​app/​src/​main/​res/​anim/​slide_out_right.xml Defines a rightward exit transition.
mobile/​app/​src/​main/​res/​anim/​slide_out_left.xml Defines a leftward exit transition.
mobile/​app/​src/​main/​res/​anim/​slide_in_right.xml Defines entry from the right.
mobile/​app/​src/​main/​res/​anim/​slide_in_left.xml Defines entry from the left.
mobile/​app/​src/​main/​res/​anim/​scale_up.xml Defines a scale-up entrance.
mobile/​app/​src/​main/​res/​anim/​scale_down.xml Defines a scale-down exit.
mobile/​app/​src/​main/​res/​anim/​fade_out.xml Defines a fade-out transition.
mobile/​app/​src/​main/​res/​anim/​fade_in.xml Defines a fade-in transition.
mobile/​app/​src/​main/​java/​org/​owasp/​mobileshepherd/​utils/​ProgressTracker.java Persists completion status and statistics.
mobile/​app/​src/​main/​java/​org/​owasp/​mobileshepherd/​utils/​ModuleInfoHelper.java Provides module metadata dialogs.
mobile/​app/​src/​main/​java/​org/​owasp/​mobileshepherd/​utils/​KeyValidator.java Provides server and offline key validation.
mobile/​app/​src/​main/​java/​org/​owasp/​mobileshepherd/​utils/​KeyProvider.java Fetches user-specific module keys.
mobile/​app/​src/​main/​java/​org/​owasp/​mobileshepherd/​utils/​CompletionVisualFeedback.java Applies completion borders.
mobile/​app/​src/​main/​java/​org/​owasp/​mobileshepherd/​utils/​CompletionBadge.java Calculates badges and progress messages.
mobile/​app/​src/​main/​java/​org/​owasp/​mobileshepherd/​ui/​scoreboard/​ScoreboardFragment.java Fetches and renders server rankings.
mobile/​app/​src/​main/​java/​org/​owasp/​mobileshepherd/​ui/​progress/​ProgressFragment.java Renders progress statistics and history.
mobile/​app/​src/​main/​java/​org/​owasp/​mobileshepherd/​ui/​home/​HomeFragment.java Manages Home authentication controls.
mobile/​app/​src/​main/​java/​org/​owasp/​mobileshepherd/​ui/​adb/​AdbReferenceFragment.java Copies reference commands to the clipboard.
mobile/​app/​src/​main/​java/​org/​owasp/​mobileshepherd/​Preferences.java Handles themes, progress reset, and support.
mobile/​app/​src/​main/​java/​org/​owasp/​mobileshepherd/​NavigationItem.java Models hierarchical drawer entries.
mobile/​app/​src/​main/​java/​org/​owasp/​mobileshepherd/​NavigationAdapter.java Renders expandable navigation entries.
mobile/​app/​src/​main/​java/​org/​owasp/​mobileshepherd/​LoginActivity.java Coordinates registration, login, and offline entry.
mobile/​app/​src/​main/​java/​org/​owasp/​mobileshepherd/​LandingActivity.java Presents the introduction and entrance animations.
mobile/​app/​src/​main/​AndroidManifest.xml Declares activities, permissions, and app policies.
mobile/​app/​src/​androidTest/​java/​com/​owasp/​reverser/​ExampleInstrumentedTest.java Checks the installed application package.
mobile/​app/​proguard-rules.pro Configures release shrinking and class retention.
mobile/​app/​build.gradle Configures Android builds and dependencies.
mobile/​app/​.gitignore Excludes app build output.
mobile/​.gitignore Updates generated-file and local-file exclusions.

Review effort: Balanced

Comment on lines +11 to +13
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
Comment on lines +138 to +140
statusText.setTextColor(isError
? getResources().getColor(android.R.color.holo_red_dark, getTheme())
: getResources().getColor(android.R.color.darker_gray, getTheme()));
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
// Load the preferences from an XML resource
setPreferencesFromResource(R.xml.preferences, rootKey);
Comment on lines +13 to +16
<debug-overrides>
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
Comment thread mobile/gradle.properties Outdated
Comment on lines +10 to +11
# Configure Gradle to use Java 17
org.gradle.java.home=C:\\Program Files\\Android\\Android Studio\\jbr
setupCopyButton(binding.copySqliteQuery, "sqlite> SELECT * FROM users;");
setupCopyButton(binding.copyCat, "adb shell cat /data/data/org.owasp.mobileshepherd/shared_prefs/UserCredentials.xml");

setupCopyButton(binding.copyGetPackages, "adb shell pm list packages | grep reverser");
Comment on lines +38 to +52
updateAuthCard();
}

private void updateAuthCard() {
TextView statusText = binding.getRoot().findViewById(org.owasp.mobileshepherd.R.id.home_auth_status_text);
MaterialButton authButton = binding.getRoot().findViewById(org.owasp.mobileshepherd.R.id.home_auth_button);
if (statusText == null || authButton == null) return;

if (AuthManager.isAuthenticated(requireContext())) {
String username = AuthManager.getUsername(requireContext());
statusText.setText("Signed in as " + username + " — keys update from server");
authButton.setText("Sign Out");
authButton.setOnClickListener(v -> {
AuthManager.logout(requireContext());
updateAuthCard();
Comment on lines +65 to +68
signInButton.setOnClickListener(v -> {
if (getActivity() instanceof MainActivity) {
((MainActivity) getActivity()).openAuthDialog();
}
The app asks /mobileModuleStatus which modules the signed-in student can
open and greys out the rest in the navigation drawer and progress list,
with the server's reason shown when tapped. This mirrors the platform's
open floor / CTF rules: module closed, event not running, module blocked.

Advisory only: the server re-checks every module start and key request.
It fails open, so signed-out or offline use and failed requests grey out
nothing. Status refreshes on resume, drawer open, sign in and sign out.
…JDK path

Changing server_preference while signed in kept the old server's session
cookie, so it would be sent to the new server. Log out when the server
actually changes.

Remove org.gradle.java.home, which pinned a Windows Android Studio path and
overrode JAVA_HOME on other machines.
@ismisepaul ismisepaul added this to the 4.0.0 milestone Oct 27, 2026
SeanDuggan and others added 3 commits October 27, 2026 22:47
Replace the individually listed local planning docs with a single *.md rule.
Remove CHALLENGE_SOLUTIONS.txt and missing_challenges.txt, which refer to
no files in the repository.
The logcat grep example rendered a literal &quot;search_term&quot; on the ADB Commands screen.
The Android app lives in mobile/, not mobile/MobileShepherd/.
Insecure Communication is deferred to 4.0.1. Remove its key hash
entries, ProGuard rules and the cleartext-traffic comment.
Drop the About dialog button that opened owasp.org and the unused hidden Top 10 FAB with its string. Lessons now name the relevant risk as plain text.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

3 participants