* Harden path traversal checks for Windows root-relative escapes.
Reject POSIX/Windows absolute paths in is_path_traversal and require post-join containment at icon, network-config, and archive extraction sinks.
Co-authored-by: Cursor <[email protected]>
* Restrict network security config names to a basename.
CodeQL flagged the manifest-derived join; reduce the resource name first so path construction cannot escape xml_dir.
Co-authored-by: Cursor <[email protected]>
* Use os.path.basename for CodeQL-recognized path sanitization.
Path.name did not clear py/path-injection taint; basename plus existing containment checks keep the network-config read inside xml_dir.
Co-authored-by: Cursor <[email protected]>
* Drop CodeQL-appeasement basename sanitization from network config reads.
is_safe_path after join already rejects traversal, absolute, and Windows root-relative names; CodeQL py/path-injection is a false positive.
Co-authored-by: Cursor <[email protected]>
* Bound androguard ZIP member decompression
Use the configured per-file ZIP limit for apkinspector reads and cap
actual raw-DEFLATE output. Keep decompression-limit failures out of the
tampered-entry fallback so malicious compressed data cannot be treated
as stored bytes.
Co-authored-by: Cursor <[email protected]>
* Reject inactive SAML users before ACS group updates.
Existing accounts mapped from a valid IdP assertion should not have groups replaced or be passed to login() when is_active is False.
Co-authored-by: Cursor <[email protected]>
* Return the ACS error page for inactive users instead of raising Exception.
Co-authored-by: Cursor <[email protected]>
---------
Co-authored-by: Cursor <[email protected]>
* Harden path traversal checks for Windows root-relative escapes.
Reject POSIX/Windows absolute paths in is_path_traversal and require post-join containment at icon, network-config, and archive extraction sinks.
Co-authored-by: Cursor <[email protected]>
* Restrict network security config names to a basename.
CodeQL flagged the manifest-derived join; reduce the resource name first so path construction cannot escape xml_dir.
Co-authored-by: Cursor <[email protected]>
* Use os.path.basename for CodeQL-recognized path sanitization.
Path.name did not clear py/path-injection taint; basename plus existing containment checks keep the network-config read inside xml_dir.
Co-authored-by: Cursor <[email protected]>
* Drop CodeQL-appeasement basename sanitization from network config reads.
is_safe_path after join already rejects traversal, absolute, and Windows root-relative names; CodeQL py/path-injection is a false positive.
Co-authored-by: Cursor <[email protected]>
* Bound androguard ZIP member decompression
Use the configured per-file ZIP limit for apkinspector reads and cap
actual raw-DEFLATE output. Keep decompression-limit failures out of the
tampered-entry fallback so malicious compressed data cannot be treated
as stored bytes.
Co-authored-by: Cursor <[email protected]>
---------
Co-authored-by: Cursor <[email protected]>
* Harden path traversal checks for Windows root-relative escapes.
Reject POSIX/Windows absolute paths in is_path_traversal and require post-join containment at icon, network-config, and archive extraction sinks.
Co-authored-by: Cursor <[email protected]>
* Restrict network security config names to a basename.
CodeQL flagged the manifest-derived join; reduce the resource name first so path construction cannot escape xml_dir.
Co-authored-by: Cursor <[email protected]>
* Use os.path.basename for CodeQL-recognized path sanitization.
Path.name did not clear py/path-injection taint; basename plus existing containment checks keep the network-config read inside xml_dir.
Co-authored-by: Cursor <[email protected]>
* Drop CodeQL-appeasement basename sanitization from network config reads.
is_safe_path after join already rejects traversal, absolute, and Windows root-relative names; CodeQL py/path-injection is a false positive.
Co-authored-by: Cursor <[email protected]>
---------
Co-authored-by: Cursor <[email protected]>
gh pr comment fails with "not a git repository" because this workflow
intentionally skips checkout; GH_REPO and -R keep pull_request_target
from needing a clone of untrusted PR code.
Co-authored-by: Cursor <[email protected]>
Use pull_request_target only for posting fixed welcome text, with no
checkout or PR code execution, so fork PRs can be commented on without
exposing a stolen write token.
Co-authored-by: Cursor <[email protected]>
* Fix DNS rebinding SSRF with pinned safe HTTP requests.
Add shared SSRF-safe request helpers that resolve once, connect to validated public IPs while preserving Host/SNI, reject redirects and internal addresses, and fail closed when upstream proxies would bypass pinning. Migrate assetlinks, Firebase, APK downloader, malware geolocation, and httptools shutdown to the hardened paths.
Co-authored-by: Cursor <[email protected]>
* remove test file
* Address SSRF hardening review feedback
Co-authored-by: Cursor <[email protected]>
* Avoid reassigning stop_httptools url parameter.
Use a dedicated proxy_kill_url so SonarCloud no longer flags
parameter reassignment before the initial value is used.
Co-authored-by: Cursor <[email protected]>
* bump version + deps
---------
Co-authored-by: Cursor <[email protected]>
Replace deprecated v2 endpoints with v3 report/upload flows, add
large-file upload_url support up to 650MB, and normalize responses
for existing report templates. Refs #2560.
Co-authored-by: Cursor <[email protected]>
Add a shared high-confidence secret detector (secret_detection.py) for known credential formats.
Integrate it into Android/iOS string, resource, binary, and plist secret extraction.
Keep labeled known secrets at the top of Hardcoded Secrets reports.
Remove Amazon LWA rules from android_rules.yaml so SAST stays focused on code-level issues.
Co-authored-by: Ajin Abraham <[email protected]>
Co-authored-by: Cursor <[email protected]>
The world readable/writable patterns matched any argument list ending with 1 or 2, so decompiled identifiers such as var1, var2 or mode2 were reported as world permissions.
Signed-off-by: Eljees <[email protected]>
Co-authored-by: Ajin Abraham <[email protected]>
SAML identity providers (e.g., Keycloak) do not include the Origin header in their SAML requests. This causes Django's CSRF middleware to reject the request with a "null origin" error.
To resolve this, we disable CSRF validation for the SAML login endpoint, as the SAML protocol itself provides its own security mechanisms (signature and assertion validation), making the CSRF check redundant in this specific flow.
---------
Co-authored-by: Khabarov Konstantin Olegovich <[email protected]>
Co-authored-by: Ajin Abraham <[email protected]>
Co-authored-by: Cursor <[email protected]>
Cert Analysis:
- updated apksigner.jar: was from build-tools 32.0.0, now from build-tools 37.0.0
- modified cert_analysis.py to be more apksigner-version-agnostic via get_signature_versions (backward compatible)
- cleaned up apksigtool_cert / get_cert_data for more generic shape handling
Apktool:
- updated apktool (now 3.0.3) and converter.py CLI args for apktool 3.x (order / deprecated flags)
Maintainer follow-ups:
- apktool bumped further to 3.0.3 (SHA256 verified against Bitbucket)
- apksigner checked against developer.android.com / build-tools — latest stable still 37.0.0; jar SHA256 matches Google zip
- Failsafe rework: always keep v1–v4 keys; merge apksigner results instead of replacing the dict; soft-fail (no re-raise) so apksigtool/androguard fallbacks still run
- Graceful degradation for malformed attacker-controlled certs/files:
- safe wrappers around cert/pubkey parsing so one bad entry does not wipe all findings
- apksigner subprocess timeout (BINARY_ANALYSIS_TIMEOUT)
- tolerant minSdkVersion parsing
- MANIFEST.MF read with errors='ignore'
- cert_info failure return keeps a shaped dict (certificate_info / certificate_findings / certificate_summary)
Co-authored-by: Cursor <[email protected]>
---------
Co-authored-by: Ajin Abraham <[email protected]>
Co-authored-by: Cursor <[email protected]>
Security Fixes
[GHSA-8j49-mmcx-4mp5] Arbitrary File Read via Path Traversal in ZIP/APK Icon Extraction
The android:icon attribute from an APK manifest was interpolated into file paths without validation, allowing a crafted APK to read arbitrary files from the server. Fixed by adding is_path_traversal() and is_safe_path() guards in find_icon_path_zip. Dependency bump included.
[GHSA-3p54-567p-2wpr] CSRF Checks Not Enforced After Django Middleware Migration
The migration from the deprecated MIDDLEWARE_CLASSES to MIDDLEWARE omitted CsrfViewMiddleware, SecurityMiddleware, and XFrameOptionsMiddleware, leaving CSRF, HSTS, and clickjacking protections silently disabled. All three have been restored to the active MIDDLEWARE tuple. The now-dead MIDDLEWARE_CLASSES block has been removed to prevent future confusion.
[GHSA-x768-8642-mmq9] Zip Bomb Denial of Service via Per-File Size Limit Bypass
The per-file size check in ZIP extraction logged a warning on oversized members but was missing a continue, allowing files exceeding ZIP_MAX_UNCOMPRESSED_FILE_SIZE to be extracted anyway as long as the aggregate limit was not reached. Fixed by adding the missing continue.
[GHSA-95px-34x5-p37h] SSRF Port Restriction Bypass in assetlinks_check
valid_host() was called with only the bare hostname, allowing android:port to be appended afterward without going through port validation, bypassing the HTTP/HTTPS-only restriction. Fixed with a two-layer approach: primary port allowlist check before URL assembly in get_browsable_activities, and a defence-in-depth re-check in _check_url.
Hardening
The hand-rolled safe_extract used os.path.abspath (symlink-blind) instead of os.path.realpath, creating a TOCTOU window where a symlink could redirect extraction outside the destination directory. Replaced with Python 3.12's tarfile.extractall(filter='data') (PEP 706), which rejects symlinks, hardlinks, absolute paths, and traversal members per-member before extraction. A robust realpath-based fallback is included for older Python versions.
Both download_app_data call sites in the iOS dynamic analyser now wrap app_container and tarfile with shlex.quote when building the SSH tar command, as defensive coding hygiene.
Refactoring
is_path_traversal, is_safe_path, clean_filename, cmd_injection_check, is_pipe_or_link, and is_attack_pattern were scattered across utils.py and shared.py. All have been moved to mobsf/MobSF/security.py as the single authoritative location for security primitives.
Developer Tooling
AGENTS.md / CLAUDE.md - AI agent guidelines
Added a coding-standards document for AI coding agents (Cursor, Claude, Codex) covering MobSF-specific secure-by-default patterns: path traversal guards, archive extraction safety, Django middleware active-tuple hygiene, split-validation anti-patterns (SSRF port bypass), guard completeness (continue/return/raise after every security check), and Django-specific security features (form validators, decorators, middleware). CLAUDE.md is a symlink to AGENTS.md.
Adds android_webview_mixed_content to the Android static-analysis ruleset.
It flags WebViews configured with MIXED_CONTENT_ALWAYS_ALLOW, which lets a
page loaded over HTTPS pull resources from insecure HTTP origins, exposing
the app to man-in-the-middle content injection (CWE-319 / OWASP-Mobile M3 /
MASVS-NETWORK-1).
The pattern matches only the insecure MIXED_CONTENT_ALWAYS_ALLOW mode and
not the safe MIXED_CONTENT_NEVER_ALLOW or MIXED_CONTENT_COMPATIBILITY_MODE
values. Verified with libsast: fires on the insecure mode and produces no
false positives on the safe modes.
Co-authored-by: Ajin Abraham <[email protected]>
Enables dynamic analysis on real jailbroken iOS devices connected via USB or WiFi SSH, complementing the existing Corellium-based iOS analysis.
- SSH connectivity — connects to jailbroken devices over USB (via iproxy port forwarding) or WiFi using Paramiko SSH
- Frida instrumentation — spawns/attaches Frida on-device, with full hook support matching the existing Corellium flow
- Environment setup — installs AppSync Unified and Frida server on first run; supports both arm and arm64 devices
- Dynamic analysis — app file extraction, system log streaming (oslog), screenshot capture, process listing, and report generation
- SSH terminal — execute shell commands on the device over SSH
---------
Co-authored-by: CylentSec <[email protected]>
Co-authored-by: Oz <[email protected]>
Bug 2491, which stated that the URLs were being converted to lowercase, which potentially caused issues for URLs with uppercase characters.
Co-authored-by: Sai Prathik R <[email protected]>
* fix(ios_analyzer): Correctly resolve executable path in .app bundles
The previous method for locating the executable within an IPA file was failing for apps with spaces in their `.app` bundle name. The logic incorrectly performed a string replacement on the full path of the bundle, resulting in an invalid path to the binary.
This commit refactors the path resolution logic to use `pathlib` features correctly. It now finds the `.app` directory as a `Path` object and uses the `.stem` attribute to reliably determine the executable's name. This approach is more robust, properly handles spaces and special characters in filenames, and avoids fragile string manipulation.
* Add doc string back
* Update mobsf/StaticAnalyzer/views/ios/binary_analysis.py
Co-authored-by: Copilot <[email protected]>
---------
Co-authored-by: Ajin Abraham <[email protected]>
Co-authored-by: Copilot <[email protected]>
Fixed an issue where the average CVSS score calculation was incorrect due to improper access to the findings key within the JSON structure. The calculation logic was bypassing the findings key and therefore failing to extract valid CVSS scores.
Co-authored-by: Ajin Abraham <[email protected]>
* Fix false positives caused in Android manifest analysis
* Dep bumps + Support HTTPS upgrade for Assetlinks check
* MobSF version bump to 4.3.0
---------
Co-authored-by: Nick Lupien <[email protected]>