← WatchMemory

Dokümantasyon

Sürüm 0.3.0 · Sürüm notları

Başlarken (Mac uygulaması)

Gereksinimler: macOS 14+ ve Xcode (iOS Simulator ve LLDB onunla gelir). Tarama motoru uygulamanın içindedir ve sistemdeki python3 ile çalışır; başka bir şey kurmanız gerekmez.

WatchMemory → Settings → System check'i açın. Her madde yeşil olmalı. “Developer mode is off” görürseniz aşağıdaki komutu bir kez çalıştırın; macOS debugger her bağlandığında şifre sormayı bırakır.

Uygulamanızın debug build'ini Simulator'da çalıştırın, araç çubuğunda simülatörü ve uygulamayı seçin, sonra bir kalıntı kontrolü başlatın.

sudo DevToolsSecurity -enable

Kalıntı kontrolü: logout'un çalıştığını kanıtlayın

1. Giriş yapın ve sır işleyen ekranları açın. 2. “Önce” kaydını alın. 3. Kullanıcının yapacağı gibi logout yapın. 4. “Sonra” kaydını alın. WatchMemory ikisini karşılaştırır ve PASS, FAIL veya INCOMPLETE döndürür.

Aynı akış komut satırından. --track-from, ikinci kaydın logout öncesi görülen sırları değerleriyle yeniden aramasını sağlar; hiçbir kalıba uymayan değerler dahil (yazıldığı gibi saklananlar; base64 gibi yeniden kodlanmış kopyalar izlenmez):

watchmemory residue capture --process MyApp --bundle-id com.acme.app --label "logged in" --out before.json
# log out in the Simulator (UI test, deep link…)
watchmemory residue capture --process MyApp --bundle-id com.acme.app \
  --track-from before.json --label "after logout" --out after.json
watchmemory residue compare before.json after.json --html residue.html

İki tarafı aynı sürümle kaydedin: 0.2.x kaydını 0.3.0 kaydıyla karşılaştırmak reddedilir.

Sonucu okumak

Sonuçlar sır bazında gruplanır. Bellekte ve diskte duran aynı token tek bir gruptur; kaldığı her yer, onu tutan depo ve anahtar (örneğin SDK:redux-persist › persist:root › auth › refreshToken, AsyncStorage'daki redux-persist kökü) ve bir düzeltmeyle listelenir. Başlık “3 sır logout sonrası 7 yerde kaldı” gibi okunur.

Kaldı (survived): logout öncesi ve sonrası var. Ortaya çıktı (appeared): logout sonrası yeni. Temizlendi (released): gitti.

Kapıyı kıranlar: diskte veya native bellekte kalan bir canary; --fail-on eşiğinde ya da üstünde (varsayılan high) diskte kalan her şey; MallocScribble açıkken native kodda yalnızca bellekte kalan bir değer. MallocScribble kapalıyken veya React Native ya da Flutter heap'inde yalnızca bellekte kalan değerler gerekçesiyle raporlanır, kapıyı kırmaz.

INCOMPLETE (çıkış 2): bir kayıt yazılabilir belleğin minimum payından azını okudu (varsayılan %90, --min-coverage), bir kaynak hata verdi, bir dosya veya klasör okunamadı, bir sınıra ulaşıldı ya da önceki kayıt hiç sır bulmadı. Yarım tarama asla PASS değildir.

Refresh, access, ID, session ve auth token'lar High; canary'ler Critical sayılır.

Canary'ler: sıfır yanlış pozitif

Debug ve UI test build'lerinde uygulamanın sahte bir token üretmesine ve gerçeği yerine onu kullanmasına izin verin. WatchMemoryDebugAgent Swift paketini ekleyin (yalnızca DEBUG) ve WatchMemory.canaryIfRequested() çağırın: uygulama canary modunda başlatıldıysa taze bir WMCANARY_… değeri, aksi halde nil döndürür.

Canary değerini asla launch argument'lerinde veya ortam değişkenlerinde vermeyin. Bunlar süreç ömrü boyunca bellekte kalır; canary her zaman “kalmış” görünür. WatchMemory böyle bir süreci taramayı reddeder (çıkış 2).

Serbest bırakılan native belleğin üzerine yazılması ve yalnızca canlı kopyaların sayılması için MallocScribble ile başlatın:

SIMCTL_CHILD_WM_CANARY_MODE=1 SIMCTL_CHILD_MallocScribble=1 SIMCTL_CHILD_MallocNanoZone=0 \
  xcrun simctl launch booted com.acme.app

// Swift, DEBUG builds (WatchMemoryDebugAgent)
let accessToken = WatchMemory.canaryIfRequested("access_token") ?? realAccessToken

// XCUITest
app.launchArguments += ["-WMCanaryMode", "1"]

Bir Xcode scheme'inde Environment Variables altına WM_CANARY_MODE=1 ekleyin ve Diagnostics altında Malloc Scribble'ı açın.

CI yayın kapısı

Sürümlü CLI'ı kurun ve açmadan önce SHA-256 değerini kontrol edin. İndirmeye tek başına güvenmek yerine sürüm notlarındaki checksum'ı pipeline'ınızda sabitleyin.

V=0.3.0
curl -fsSLO https://watchmemory.app/downloads/watchmemory-cli-$V.tar.gz
echo "$WM_CLI_SHA256  watchmemory-cli-$V.tar.gz" | shasum -a 256 -c -   # Linux: sha256sum -c -
tar xzf watchmemory-cli-$V.tar.gz
./watchmemory-cli/bin/watchmemory doctor
./watchmemory-cli/bin/watchmemory ci --process MyApp --bundle-id com.acme.app \
  --scan-profile full --baseline .watchmemory-baseline.json \
  --sarif wm.sarif --junit wm.xml --html wm.html

Çıkış kodları: 0 PASS, 1 FAIL (politika ihlali), 2 INCOMPLETE veya hata (yarım tarama, kapsam minimumun altında, hedef bulunamadı, canary launch argument'inde verildi).

WATCHMEMORY_LICENSE (Pro veya Team) ve WATCHMEMORY_HASH_KEY (herhangi uzun rastgele bir metin; baseline'ları sabit tutar) değerlerini CI secret'ı olarak tanımlayın. Lisans yoksa çalıştırma yalnızca rapor üretir: raporlardaki karar doğrudur, FAIL olsa da çıkış kodu 0'dır. Pro bir uygulama için zorlar; Team bir uygulamanın tüm geliştiricileri ve runner'ları için.

CI runner'larında (CI, GITHUB_ACTIONS, GITLAB_CI, TF_BUILD, JENKINS_URL, BUILDKITE, BITRISE_IO, CIRCLECI, TEAMCITY_VERSION, CODEBUILD_BUILD_ID ve docs/CI.md'deki diğer CI değişkenleri) --show-values reddedilir. GitHub Action ile fastlane ve Bitrise örnekleri CLI tarball'ının integrations klasöründe gelir.

SARIF'i yalnızca PASS veya FAIL için yükleyin: INCOMPLETE bir çalıştırmanın SARIF'i yalnızca okunabileni listeler (executionSuccessful: false olarak işaretlenir) ve code scanning onda olmayan uyarıları kapatır.

Android (beta)

Gereksinimler: debuggable bir build (debug varyantı), Linux veya macOS'ta adb ve Python 3.9+. Root gerekmez. WatchMemory uygulamanın özel verisini adb run-as ile kopyalar ve makinenizde tarar.

adb devices                     # emulator or USB device with USB debugging
watchmemory residue capture --android-package com.acme.app --label "logged in" --out before.json
# log out in the app (instrumented test, Maestro or by hand)
watchmemory residue capture --android-package com.acme.app \
  --track-from before.json --label "after logout" --out after.json
watchmemory residue compare before.json after.json --html residue.html

Taranır: SharedPreferences, DataStore, Room/SQLite (-wal dosyasıyla), WebView çerezleri ve depolaması, OkHttp önbelleği, MMKV ve uygulamanın veri dizinindeki diğer dosyalar. Cihaz seçmek için --adb-serial, iş profili veya ikincil kullanıcı için --android-user kullanın. Aynı bayraklar disk-scan, ci, assert ve residue capture ile çalışır (scan ile değil: Android desteği yalnızca disk).

Sınırlar: yalnızca disk (henüz bellek veya Java heap sonucu yok), yalnızca debuggable build'ler (release build'ler açık bir hatayla reddedilir), yalnızca CLI. Bazı üreticilerin cihazları run-as'i kısıtlar; referans ortam emülatördür.

React Native, Flutter ve KMP

iOS Simulator'da debug build'lerle çalışırlar; Flutter, Simulator'da yalnızca debug (JIT) modunda çalışır. Her kayıt tespit ettiği runtime'ı (react-native, flutter, kmp veya native) ve kanıtını (örneğin hermes.framework) yazar.

Depolama bulguları depo ve anahtarı adlandırır: SDK:redux-persist › persist:root › auth › refreshToken (AsyncStorage'daki redux-persist), MMKV veya shared_preferences'taki flutter.session gibi. Her zamanki gibi kapıyı kırarlar.

JavaScript (Hermes) veya Dart heap'indeki yalnızca-bellek isabetleri yalnızca raporlanır. Bu heap'ler çöp toplayıcılıdır: serbest bırakılan bir string, toplayıcı sayfayı yeniden kullanana kadar kalır ve MallocScribble ona ulaşmaz; bunlarda başarısız olmak her çalıştırmayı başarısız yapardı. Önce depolamayı düzeltin.

Expo Go değil, bir development build kullanın (npx expo run:ios, flutter run): Expo Go kendi verisi olan farklı bir uygulamadır.

AI kod ajanları için MCP sunucusu

Claude Code, Cursor ve diğer MCP istemcileri check_environment, list_simulator_processes, memory_usage, scan_memory, scan_disk, compare_residue_captures ve assert_no_residue araçlarını çağırabilir. Ham değerler modele asla gönderilmez; yalnızca maskeli önizleme ve hash'ler.

claude mcp add watchmemory -- /Applications/WatchMemory.app/Contents/Resources/Engine/bin/watchmemory-mcp

OWASP MAS v2 eşlemesi

Her kalıntı: MASWE-0024 (oturum sonlandıktan sonra erişilebilen hassas veri), MASVS-AUTH-3.

Diskte saklanan sırlar: MASVS-STORAGE-1 ile MASWE-0001 veya MASWE-0002; iOS'ta MASTG-TEST-0302, Android'de MASTG-TEST-0207.

Bellek: MASVS-STORAGE-2. OWASP'ın güncel bir bellek testi yok; WatchMemory kullanımdan kaldırılmış MASTG-TEST-0060 veya MASTG-TEST-0052'ye atıf yapmaz.

WatchMemory, MASWE-0024 kontrolünü otomatikleştirir ve size kanıt verir. Hiçbir şeyi sertifikalandırmaz: OWASP uygulamaları veya araçları sertifikalandırmaz.

Sayıların anlamı ve sınırlar

Kapsam: uygulamanın yazılabilir belleğinin (heap, stack, data; kod veya salt okunur eşlemeler değil) okunan payı. Snapshot yaklaşık 10 sn sonra durur; Full scan ve CI hepsini okur.

--show-values vermediğiniz sürece değerler raporlarda asla görünmez. Hash'ler kuruluma özel bir anahtarla (veya WATCHMEMORY_HASH_KEY ile) HMAC'tir; kaba kuvvetle geri çözülemez.

İncelenmeyenler: release ve App Store build'leri (bilinçli olarak), fiziksel iPhone'lar (planlandı), Keychain (planlandı; logout kodunuzda Keychain öğelerini silin), Android belleği. Çok kısa NSString'ler (yaklaşık 11 karaktere kadar, örneğin bir PIN) tagged pointer içinde yaşayabilir ve hiçbir bellek taramasında görünmez.