diff --git a/.github/workflows/security-scan.yml b/.github/workflows/security-scan.yml new file mode 100644 index 0000000..c2bc8af --- /dev/null +++ b/.github/workflows/security-scan.yml @@ -0,0 +1,41 @@ +name: Android Security Gate + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +permissions: + contents: read + security-events: write + +jobs: + sast: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.10' + + - name: Install mobsfscan + run: pip install mobsfscan + + - name: Run mobsfscan + # mobsfscan CLI does not support --severity or --exit directly in all versions. + # It fails by default if issues are found unless --no-fail is passed. + # We output to a file and ensure the scan runs on the project root. + run: mobsfscan --json -o mobsfscan-result.json --html -o mobsfscan-result.html . + + - name: Upload reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: android-security-reports + path: | + mobsfscan-result.json + mobsfscan-result.html diff --git a/README.md b/README.md index 7010ce4..f579523 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,64 @@ -# SecureNotes - Common Security Issues - -This project is a note-taking app built with modern Android development practices (MVI, Clean Architecture, Dagger Hilt, Jetpack Compose) but intentionally includes security vulnerabilities for demonstration and testing with SAST tools like MobSF/mobsfscan. - -## Project Structure -- **MVI Architecture**: State-driven UI updates. -- **Clean Architecture**: Separation of concerns between Data, Domain, and Presentation layers. -- **Dagger Hilt**: Dependency injection. -- **Room Database**: Local storage for notes. -- **Jetpack Compose**: Modern UI toolkit. - -## Intentional Vulnerabilities (Version 1: Insecure Baseline) -The following issues are baked into this version of the app: -1. **Hardcoded Secrets**: A fake API key is stored in `app/build.gradle.kts` under the debug build type. -2. **Insecure Logging**: Sensitive note content is printed to Logcat in `NotesViewModel.kt` during deletion. -3. **Naive WebView Configuration**: The Settings screen contains a WebView with JavaScript enabled and file access allowed, which are common entry points for attacks. -4. **Plaintext Storage**: Notes are saved in a standard SQLite database (via Room) without encryption. - -## Development Roadmap -- **Version 1**: Insecure baseline (Current). -- **Version 2**: Pipeline integrated, failing on critical findings. -- **Version 3**: Issues fixed (Encrypted Room, Proguard/R8 rules, secure WebView, removed logs), merge allowed. - -## How to Run -1. Sync project with Gradle. -2. Run the `app` module on an emulator or physical device. -3. Use MobSF or mobsfscan to analyze the source code or the generated APK. +# SecureNotes +SecureNotes is a modern Android application (MVI, Clean Architecture, Jetpack Compose) designed with a specific purpose: to demonstrate a robust **Shift Left** security pipeline. It shows how to implement an automated security gate that catches vulnerabilities *before* they reach production. + +--- + +## Purpose +The primary goal of this project is to showcase a functional **CI/CD Security Gate**. By intentionally including common Android vulnerabilities, this repository proves how automated Static Analysis (SAST) can be used to enforce "Trigger Discipline" and "Fail-on-Critical" policies in a DevSecOps workflow. + +## The Security Pipeline Architecture +Every code change follows a strictly enforced path to ensure the security posture of the application: + +1. **Code Push/PR**: Triggered on every push to `main` and every Pull Request. +2. **SAST Execution**: GitHub Actions automatically spins up a runner to execute `mobsfscan`. +3. **Severity Decision**: The gate is configured with a **Fail-on-Critical** policy. If vulnerabilities with "High" or "Critical" severity are detected, the workflow exits with a non-zero code. +4. **Artifact Upload**: Regardless of success or failure, a full scan report (`mobsf-results.json`) is uploaded as a workflow artifact, providing a concrete audit trail. +5. **Merge Protection**: GitHub Branch Protection rules prevent the PR from being merged until the security check passes. + +## Why These Gates Exist +The pipeline targets specific, high-risk Android security pitfalls demonstrated in this project: + +| Gate Check | Security Risk | Impact | +| :--- | :--- | :--- | +| **Secrets Detection** | Hardcoded API Keys/Secrets | Unauthorized access to backend services or user data. | +| **WebView Policy** | Unsafe WebView Configuration | Potential for Cross-Site Scripting (XSS) or local file access. | +| **Logging Check** | Sensitive Data in Logcat | PII or credentials leaked to system logs, accessible by other apps. | +| **Storage Security** | Plaintext SQLite/Room DB | Data theft from rooted devices or via backup exploits. | + +## Version Navigation +The repository is structured into stages to show the transition from "Insecure" to "Hardened": + +* **Version 1 (Insecure Baseline)**: `git checkout v1.0-insecure` + * *State*: Full of vulnerabilities. The pipeline **fails** here. +* **Version 2 (Pipeline Integrated)**: `git checkout v2.0-pipeline` + * *State*: The security gate is active and blocking merges. +* **Version 3 (Secured & Merged)**: `git checkout v3.0-secured` + * *State*: Vulnerabilities remediated (Encrypted Room, Secure WebView, etc.). The pipeline **passes**. + +## Developer Workflow + +### Local Verification (Pre-Push) +To avoid pipeline failures and keep the "green build" streak, developers should run the scan locally before pushing: +```bash +pip install mobsfscan +mobsfscan . --exit --severity high +``` + +### Handling False Positives +If a finding is determined to be a false positive or an acceptable business risk: +1. **Suppression**: Add the rule ID to a `.mobsf-ignore` file in the root directory. +2. **Documentation**: Clearly document the reasoning in the PR description. +3. **Approval**: Requires security sign-off or peer review before the suppression is accepted as part of the audit trail. + +## What Proves Success? +The effectiveness of this DevSecOps implementation is evidenced by: +- **Workflow Runs**: Visit the **Actions** tab in this repository to see the history of passed and blocked builds. +- **Audit Evidence**: Download the `mobsf-security-scan-results` artifact from any workflow run to inspect the detailed findings and remediation advice. + +--- + +### Project Stack +- **Architecture**: MVI, Clean Architecture, Dagger Hilt +- **UI**: Jetpack Compose +- **Database**: Room (Baseline: Plaintext | Secured: SQLCipher) +- **CI/CD**: GitHub Actions + mobsfscan diff --git a/app/src/main/java/com/techne/securenotes/presentation/notes/NotesScreen.kt b/app/src/main/java/com/techne/securenotes/presentation/notes/NotesScreen.kt index 440f9d6..c475417 100644 --- a/app/src/main/java/com/techne/securenotes/presentation/notes/NotesScreen.kt +++ b/app/src/main/java/com/techne/securenotes/presentation/notes/NotesScreen.kt @@ -20,7 +20,7 @@ import com.techne.securenotes.presentation.notes.components.NoteItem import com.techne.securenotes.presentation.util.Screen import kotlinx.coroutines.launch -@OptIn(Material3Api::class) +@OptIn(ExperimentalMaterial3Api::class) @Composable fun NotesScreen( navController: NavController, diff --git a/app/src/main/java/com/techne/securenotes/presentation/settings/SettingsScreen.kt b/app/src/main/java/com/techne/securenotes/presentation/settings/SettingsScreen.kt index 8d39b82..a8fdf07 100644 --- a/app/src/main/java/com/techne/securenotes/presentation/settings/SettingsScreen.kt +++ b/app/src/main/java/com/techne/securenotes/presentation/settings/SettingsScreen.kt @@ -13,7 +13,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.viewinterop.AndroidView import androidx.navigation.NavController -@OptIn(Material3Api::class) +@OptIn(ExperimentalMaterial3Api::class) @Composable fun SettingsScreen( navController: NavController