# Android security review

Review Android storage, verified links and release artifacts. Keep browser policy models distinct from device verification.

Original AI-assisted SecNet educational content. Fictional local examples; not a standards provider publication, endorsement or compliance evidence. Page exercises do not create account progress.

Sources checked: 2026-10-21

## Key and token lifecycle

An app-private directory is not encryption. Retain short-lived tokens only as needed; if persistence is required, design authenticated encryption using an Android Keystore key. The example uses a fresh AES-GCM IV on each encryption; the IV is not secret but must not repeat under a key. Examine ciphertext backups, logs, crash reports and screenshots as separate copies.

## Keystore limits and links

Keystore key material is non-exportable; hardware protection depends on device and configuration. A compromised app context may still invoke the key, so it is not a complete prevention guarantee. App Links require HTTPS, exact host/path policy and OS domain verification together. Check assetlinks.json and signing fingerprints; the application server must still authorize the requested object.

## Complete verification on a device

Inspect debuggable settings, cleartext policy, exported components and signing chain on the release APK/AAB. Testing a debug build does not verify the release artifact. Test data behavior across reinstall, lock, key invalidation and upgrade. MASVS guides requirements; MASTG supplies testing techniques. The Kotlin fragment is an integration component, not a complete Android app or device lab.

## Device workpaper: token and links

Use only a synthetic token on the test device. Check its required accessibility after lock, app termination and upgrade, and inspect logs and backup copies. If a key disappears, require safe reauthentication rather than an endless error loop or plaintext fallback. For links, try the correct domain, lookalikes, wrong paths and foreign-tenant tickets. A valid URL still requires the server to deny a foreign record. Record artifact digest, signature, Android version, verification state and observed outcomes. The Kotlin component demonstrates key generation and encryption; it does not implement UI, backup rules or app session management.

## Working sequence

1. Pin the release artifact and device versions.
2. Review token copies and key lifecycle.
3. Verify App Links domain and signing association.
4. Test component, network and backup policies.
5. Bind device evidence to the artifact digest.

## 1. Plaintext in a private directory

privateDirectory alone is insufficient. Encryption, Keystore and log/backup boundaries are required together. Fields represent evidence assumptions; the model does not inspect device files or hardware.

This code is a local policy model; it does not replace target/device testing.

### Weak implementation
```js
s=>s.privateDirectory
```

### Corrected implementation
```js
s=>s.privateDirectory&&s.encrypted&&s.keystoreKey&&!s.backedUp&&!s.logged
```

### Synthetic input and actual model output
```json
{
  "before": [
    {
      "name": "private-plaintext",
      "input": {
        "privateDirectory": true,
        "encrypted": false,
        "keystoreKey": false,
        "backedUp": true,
        "logged": false
      },
      "expected": false,
      "observed": true,
      "matched": false
    },
    {
      "name": "controlled-token",
      "input": {
        "privateDirectory": true,
        "encrypted": true,
        "keystoreKey": true,
        "backedUp": false,
        "logged": false
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "log-copy",
      "input": {
        "privateDirectory": true,
        "encrypted": true,
        "keystoreKey": true,
        "backedUp": false,
        "logged": true
      },
      "expected": false,
      "observed": true,
      "matched": false
    }
  ],
  "after": [
    {
      "name": "private-plaintext",
      "input": {
        "privateDirectory": true,
        "encrypted": false,
        "keystoreKey": false,
        "backedUp": true,
        "logged": false
      },
      "expected": false,
      "observed": false,
      "matched": true
    },
    {
      "name": "controlled-token",
      "input": {
        "privateDirectory": true,
        "encrypted": true,
        "keystoreKey": true,
        "backedUp": false,
        "logged": false
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "log-copy",
      "input": {
        "privateDirectory": true,
        "encrypted": true,
        "keystoreKey": true,
        "backedUp": false,
        "logged": true
      },
      "expected": false,
      "observed": false,
      "matched": true
    }
  ]
}
```

## 2. A lookalike domain

An includes check also accepts harbor.example.other.example. Exact host/path and OS verification deny lookalikes and unverified handlers. Device testing on relevant Android versions is still required.

This code is a local policy model; it does not replace target/device testing.

### Weak implementation
```js
s=>s.host.includes('harbor.example')
```

### Corrected implementation
```js
s=>s.scheme==='https'&&s.host==='harbor.example'&&s.osVerified&&/^\/tickets\/[a-z0-9-]+$/.test(s.path)
```

### Synthetic input and actual model output
```json
{
  "before": [
    {
      "name": "verified-link",
      "input": {
        "scheme": "https",
        "host": "harbor.example",
        "osVerified": true,
        "path": "/tickets/t-1"
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "lookalike-host",
      "input": {
        "scheme": "https",
        "host": "harbor.example.other.example",
        "osVerified": false,
        "path": "/tickets/t-1"
      },
      "expected": false,
      "observed": true,
      "matched": false
    },
    {
      "name": "unverified-handler",
      "input": {
        "scheme": "https",
        "host": "harbor.example",
        "osVerified": false,
        "path": "/tickets/t-1"
      },
      "expected": false,
      "observed": true,
      "matched": false
    },
    {
      "name": "unexpected-path",
      "input": {
        "scheme": "https",
        "host": "harbor.example",
        "osVerified": true,
        "path": "/admin"
      },
      "expected": false,
      "observed": true,
      "matched": false
    }
  ],
  "after": [
    {
      "name": "verified-link",
      "input": {
        "scheme": "https",
        "host": "harbor.example",
        "osVerified": true,
        "path": "/tickets/t-1"
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "lookalike-host",
      "input": {
        "scheme": "https",
        "host": "harbor.example.other.example",
        "osVerified": false,
        "path": "/tickets/t-1"
      },
      "expected": false,
      "observed": false,
      "matched": true
    },
    {
      "name": "unverified-handler",
      "input": {
        "scheme": "https",
        "host": "harbor.example",
        "osVerified": false,
        "path": "/tickets/t-1"
      },
      "expected": false,
      "observed": false,
      "matched": true
    },
    {
      "name": "unexpected-path",
      "input": {
        "scheme": "https",
        "host": "harbor.example",
        "osVerified": true,
        "path": "/admin"
      },
      "expected": false,
      "observed": false,
      "matched": true
    }
  ]
}
```

## 3. Is installation enough?

An installable package may still expose debug and cleartext settings. The model requires release review and signing evidence; it does not replace actual APK/AAB analysis.

This code is a local policy model; it does not replace target/device testing.

### Weak implementation
```js
s=>s.installable
```

### Corrected implementation
```js
s=>s.installable&&!s.debuggable&&!s.cleartext&&s.exportsReviewed&&s.signatureVerified
```

### Synthetic input and actual model output
```json
{
  "before": [
    {
      "name": "debug-build",
      "input": {
        "installable": true,
        "debuggable": true,
        "cleartext": true,
        "exportsReviewed": false,
        "signatureVerified": true
      },
      "expected": false,
      "observed": true,
      "matched": false
    },
    {
      "name": "reviewed-build",
      "input": {
        "installable": true,
        "debuggable": false,
        "cleartext": false,
        "exportsReviewed": true,
        "signatureVerified": true
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "unverified-signature",
      "input": {
        "installable": true,
        "debuggable": false,
        "cleartext": false,
        "exportsReviewed": true,
        "signatureVerified": false
      },
      "expected": false,
      "observed": true,
      "matched": false
    }
  ],
  "after": [
    {
      "name": "debug-build",
      "input": {
        "installable": true,
        "debuggable": true,
        "cleartext": true,
        "exportsReviewed": false,
        "signatureVerified": true
      },
      "expected": false,
      "observed": false,
      "matched": true
    },
    {
      "name": "reviewed-build",
      "input": {
        "installable": true,
        "debuggable": false,
        "cleartext": false,
        "exportsReviewed": true,
        "signatureVerified": true
      },
      "expected": true,
      "observed": true,
      "matched": true
    },
    {
      "name": "unverified-signature",
      "input": {
        "installable": true,
        "debuggable": false,
        "cleartext": false,
        "exportsReviewed": true,
        "signatureVerified": false
      },
      "expected": false,
      "observed": false,
      "matched": true
    }
  ]
}
```

## Exit evidence

- APK/AAB digest and device/OS matrix
- Keystore, link and exported-component test records

## References

- [OWASP MASVS](https://mas.owasp.org/MASVS/)
- [OWASP MASTG](https://mas.owasp.org/MASTG/0x03-Overview/)
- [Android Keystore](https://developer.android.com/privacy-and-security/keystore)
- [Android verified App Links](https://developer.android.com/training/app-links/verify-applinks)
