apsa 1.2.0__tar.gz → 1.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (307) hide show
  1. {apsa-1.2.0 → apsa-1.3.0}/.agents/skills/apsa/SKILL.md +5 -3
  2. {apsa-1.2.0/src/mobile_audit/data → apsa-1.3.0/.agents}/skills/mobile-audit/SKILL.md +5 -3
  3. {apsa-1.2.0/src/mobile_audit/data → apsa-1.3.0/.agents}/skills/quaygate/SKILL.md +5 -3
  4. apsa-1.3.0/.github/workflows/dependency-evaluation.yml +47 -0
  5. apsa-1.3.0/.github/workflows/dependency-oracle.yml +77 -0
  6. apsa-1.3.0/.github/workflows/fpfn-evaluation.yml +43 -0
  7. {apsa-1.2.0 → apsa-1.3.0}/.github/workflows/hardening-replay.yml +1 -1
  8. {apsa-1.2.0 → apsa-1.3.0}/Makefile +3 -3
  9. {apsa-1.2.0 → apsa-1.3.0}/PKG-INFO +75 -9
  10. {apsa-1.2.0 → apsa-1.3.0}/README.ko.md +63 -7
  11. {apsa-1.2.0 → apsa-1.3.0}/README.md +74 -8
  12. {apsa-1.2.0 → apsa-1.3.0}/RELEASE_READINESS.md +36 -0
  13. apsa-1.3.0/benchmarks/DEPENDENCY_RESULTS.ko.md +158 -0
  14. apsa-1.3.0/benchmarks/DEPENDENCY_RESULTS.md +182 -0
  15. apsa-1.3.0/benchmarks/FPFN_RESULTS.ko.md +88 -0
  16. apsa-1.3.0/benchmarks/FPFN_RESULTS.md +100 -0
  17. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/competitive.py +7 -1
  18. apsa-1.3.0/benchmarks/dependency_cases.json +114 -0
  19. apsa-1.3.0/benchmarks/dependency_eval.py +187 -0
  20. apsa-1.3.0/benchmarks/dependency_locks/element-x.lockfile +704 -0
  21. apsa-1.3.0/benchmarks/dependency_locks/fossify-calculator.lockfile +404 -0
  22. apsa-1.3.0/benchmarks/dependency_locks/fossify-gallery.lockfile +484 -0
  23. apsa-1.3.0/benchmarks/dependency_locks/home-assistant.lockfile +705 -0
  24. apsa-1.3.0/benchmarks/dependency_locks/mihon.lockfile +583 -0
  25. apsa-1.3.0/benchmarks/dependency_locks/nextcloud.lockfile +734 -0
  26. apsa-1.3.0/benchmarks/dependency_locks/nowinandroid.lockfile +613 -0
  27. apsa-1.3.0/benchmarks/dependency_locks/pocket-casts.lockfile +618 -0
  28. apsa-1.3.0/benchmarks/dependency_locks/wikipedia.lockfile +624 -0
  29. apsa-1.3.0/benchmarks/dependency_oracle.py +176 -0
  30. apsa-1.3.0/benchmarks/dependency_truth.json +9874 -0
  31. apsa-1.3.0/benchmarks/dependency_truth_holdout2.json +9459 -0
  32. apsa-1.3.0/benchmarks/dependency_truth_holdout3.json +6935 -0
  33. apsa-1.3.0/benchmarks/fpfn_eval.py +189 -0
  34. apsa-1.3.0/benchmarks/fpfn_truth.json +273 -0
  35. apsa-1.3.0/benchmarks/fpfn_truth_amendments.json +17 -0
  36. apsa-1.3.0/benchmarks/results/2026-10-09-dependency-development-rerun.json +18341 -0
  37. apsa-1.3.0/benchmarks/results/2026-10-09-dependency-final-head.json +18337 -0
  38. apsa-1.3.0/benchmarks/results/2026-10-09-dependency-first-holdout1.json +6092 -0
  39. apsa-1.3.0/benchmarks/results/2026-10-09-dependency-first-holdout2.json +13271 -0
  40. apsa-1.3.0/benchmarks/results/2026-10-09-dependency-first-holdout3.json +18095 -0
  41. apsa-1.3.0/benchmarks/results/2026-10-09-dependency-frozen-replay.json +5360 -0
  42. apsa-1.3.0/benchmarks/results/2026-10-09-dependency-review-rerun.json +18337 -0
  43. apsa-1.3.0/benchmarks/results/2026-10-09-fpfn-first.json +911 -0
  44. apsa-1.3.0/benchmarks/results/2026-10-09-parser-fresh-repos.json +43 -0
  45. apsa-1.3.0/benchmarks/results/2026-10-09-release-130-harnesses.json +225 -0
  46. apsa-1.3.0/docs/DEVICE_EVIDENCE.md +31 -0
  47. {apsa-1.2.0 → apsa-1.3.0}/docs/INTEGRATION.md +1 -1
  48. apsa-1.3.0/docs/NEXT_ANALYSIS.md +271 -0
  49. {apsa-1.2.0 → apsa-1.3.0}/docs/OWASP_COVERAGE.md +1 -1
  50. {apsa-1.2.0 → apsa-1.3.0}/docs/ROADMAP.md +3 -2
  51. {apsa-1.2.0 → apsa-1.3.0}/docs/SUPPORTED_MATRIX.md +10 -9
  52. {apsa-1.2.0 → apsa-1.3.0}/docs/ci-example.yml +1 -1
  53. {apsa-1.2.0 → apsa-1.3.0}/pyproject.toml +1 -1
  54. {apsa-1.2.0 → apsa-1.3.0}/quaygate/__init__.py +1 -1
  55. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/audit.py +73 -10
  56. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/binary_analysis.py +153 -3
  57. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/cli.py +14 -0
  58. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/core.py +1 -1
  59. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/data/skills/apsa/SKILL.md +5 -3
  60. {apsa-1.2.0/.agents → apsa-1.3.0/src/mobile_audit/data}/skills/mobile-audit/SKILL.md +5 -3
  61. {apsa-1.2.0/.agents → apsa-1.3.0/src/mobile_audit/data}/skills/quaygate/SKILL.md +5 -3
  62. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/inputs.py +133 -3
  63. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/intel.py +152 -12
  64. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/objc_analysis.py +11 -2
  65. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/parser_compat.py +150 -0
  66. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/runtime.py +6 -0
  67. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/skills.py +3 -0
  68. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/source_analysis.py +5 -1
  69. apsa-1.3.0/src/mobile_audit/source_context.py +694 -0
  70. apsa-1.3.0/tests/fixtures/skills/apsa-1.3.0.md +52 -0
  71. apsa-1.3.0/tests/fixtures/skills/mobile-audit-1.3.0.md +52 -0
  72. apsa-1.3.0/tests/fixtures/skills/quaygate-1.3.0.md +52 -0
  73. apsa-1.3.0/tests/test_dependency_evidence.py +728 -0
  74. apsa-1.3.0/tests/test_intel_history.py +154 -0
  75. apsa-1.3.0/tests/test_parser_depth.py +373 -0
  76. {apsa-1.2.0 → apsa-1.3.0}/uv.lock +1 -1
  77. apsa-1.2.0/docs/NEXT_ANALYSIS.md +0 -128
  78. apsa-1.2.0/src/mobile_audit/source_context.py +0 -269
  79. {apsa-1.2.0 → apsa-1.3.0}/.github/workflows/benchmark-evidence.yml +0 -0
  80. {apsa-1.2.0 → apsa-1.3.0}/.github/workflows/ci.yml +0 -0
  81. {apsa-1.2.0 → apsa-1.3.0}/.github/workflows/competitive-benchmark.yml +0 -0
  82. {apsa-1.2.0 → apsa-1.3.0}/.github/workflows/generated-aab.yml +0 -0
  83. {apsa-1.2.0 → apsa-1.3.0}/.github/workflows/next-holdout.yml +0 -0
  84. {apsa-1.2.0 → apsa-1.3.0}/.github/workflows/public-evidence.yml +0 -0
  85. {apsa-1.2.0 → apsa-1.3.0}/.github/workflows/real-world-benchmark.yml +0 -0
  86. {apsa-1.2.0 → apsa-1.3.0}/.github/workflows/release.yml +0 -0
  87. {apsa-1.2.0 → apsa-1.3.0}/DESIGN.md +0 -0
  88. {apsa-1.2.0 → apsa-1.3.0}/LICENSE +0 -0
  89. {apsa-1.2.0 → apsa-1.3.0}/NAMING.md +0 -0
  90. {apsa-1.2.0 → apsa-1.3.0}/PRODUCT_REQUIREMENTS.md +0 -0
  91. {apsa-1.2.0 → apsa-1.3.0}/THIRD_PARTY_NOTICES.md +0 -0
  92. {apsa-1.2.0 → apsa-1.3.0}/apsa/__init__.py +0 -0
  93. {apsa-1.2.0 → apsa-1.3.0}/apsa/__main__.py +0 -0
  94. {apsa-1.2.0 → apsa-1.3.0}/apsa/cli.py +0 -0
  95. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/COMPETITIVE.md +0 -0
  96. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/COMPETITIVE_RESULTS.ko.md +0 -0
  97. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/COMPETITIVE_RESULTS.md +0 -0
  98. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/COVERAGE_RESULTS.ko.md +0 -0
  99. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/COVERAGE_RESULTS.md +0 -0
  100. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/HARDENING_RESULTS.ko.md +0 -0
  101. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/HARDENING_RESULTS.md +0 -0
  102. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/NEXT_RESULTS.ko.md +0 -0
  103. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/NEXT_RESULTS.md +0 -0
  104. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/README.md +0 -0
  105. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/REAL_WORLD.ko.md +0 -0
  106. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/REAL_WORLD.md +0 -0
  107. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/REAL_WORLD_RESULTS.ko.md +0 -0
  108. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/REAL_WORLD_RESULTS.md +0 -0
  109. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/__init__.py +0 -0
  110. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/java/bridge-fixed.java +0 -0
  111. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/java/bridge-vulnerable.java +0 -0
  112. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/java/cross-function-irrelevant.java +0 -0
  113. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/java/documentation-irrelevant.java +0 -0
  114. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/java/host-fixed.java +0 -0
  115. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/java/host-vulnerable.java +0 -0
  116. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/java/intent-fixed.java +0 -0
  117. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/java/intent-vulnerable.java +0 -0
  118. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/java/other-client-irrelevant.java +0 -0
  119. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/java/post-validation-mutation.java +0 -0
  120. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/java/ssl-fixed.java +0 -0
  121. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/java/ssl-vulnerable.java +0 -0
  122. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/kotlin/documentation-irrelevant.kt +0 -0
  123. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/kotlin/navigation-fixed.kt +0 -0
  124. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/kotlin/navigation-vulnerable.kt +0 -0
  125. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/kotlin/query-fixed.kt +0 -0
  126. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/kotlin/query-vulnerable.kt +0 -0
  127. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/kotlin/ssl-fixed.kt +0 -0
  128. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/kotlin/ssl-vulnerable.kt +0 -0
  129. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/kotlin/unrelated-shadow.kt +0 -0
  130. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/swift/documentation-irrelevant.swift +0 -0
  131. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/swift/navigation-fixed.swift +0 -0
  132. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/swift/navigation-vulnerable.swift +0 -0
  133. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/swift/query-javascript-fixed.swift +0 -0
  134. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/swift/query-javascript-vulnerable.swift +0 -0
  135. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/swift/unrelated-shadow.swift +0 -0
  136. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/swift/url-fixed.swift +0 -0
  137. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/cases/swift/url-vulnerable.swift +0 -0
  138. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/competitive_cases.py +0 -0
  139. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/corpus.json +0 -0
  140. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/coverage_replay.py +0 -0
  141. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/hardening_replay.py +0 -0
  142. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/ios_branch_cases.json +0 -0
  143. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/next_holdout.py +0 -0
  144. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/next_replay.py +0 -0
  145. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/next_truth.json +0 -0
  146. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/primary/CVE-2025-31200.json +0 -0
  147. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/primary/CVE-2025-31201.json +0 -0
  148. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/primary/CVE-2025-43300.json +0 -0
  149. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/real_world.py +0 -0
  150. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/real_world_advisories.json +0 -0
  151. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/real_world_cases.json +0 -0
  152. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/real_world_swift_advisory.json +0 -0
  153. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/results/2026-10-09-candidate-mobsf.json +0 -0
  154. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/results/2026-10-09-coverage-evidence.json +0 -0
  155. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/results/2026-10-09-hardening-evidence.json +0 -0
  156. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/results/2026-10-09-initial-candidate-mobsf.json +0 -0
  157. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/results/2026-10-09-initial-released-baseline.json +0 -0
  158. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/results/2026-10-09-next-evidence.json +0 -0
  159. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/results/2026-10-09-next-first-holdout.json +0 -0
  160. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/results/2026-10-09-next-first-replay.json +0 -0
  161. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/results/2026-10-09-next-generated-aab-verified.json +0 -0
  162. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/results/2026-10-09-next-generated-aab.json +0 -0
  163. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/results/2026-10-09-next-holdout-rerun.json +0 -0
  164. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/results/2026-10-09-next-replay-rerun.json +0 -0
  165. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/results/2026-10-09-public-coverage-extension.json +0 -0
  166. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/results/2026-10-09-public-evidence.json +0 -0
  167. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/results/2026-10-09-public-real-world-hardened.json +0 -0
  168. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/results/2026-10-09-public-real-world-initial.json +0 -0
  169. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/results/2026-10-09-released-baseline.json +0 -0
  170. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/reviews/2026-10-09-coverage-architecture.md +0 -0
  171. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/reviews/2026-10-09-coverage-code.md +0 -0
  172. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/reviews/2026-10-09-hardening-architecture.md +0 -0
  173. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/reviews/2026-10-09-hardening-code.md +0 -0
  174. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/reviews/2026-10-09-next-runtime-architecture.md +0 -0
  175. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/reviews/2026-10-09-next-runtime-code.json +0 -0
  176. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/reviews/2026-10-09-next-runtime-code.md +0 -0
  177. {apsa-1.2.0 → apsa-1.3.0}/benchmarks/run.py +0 -0
  178. {apsa-1.2.0 → apsa-1.3.0}/docs/MODEL_WORKFLOWS.md +0 -0
  179. {apsa-1.2.0 → apsa-1.3.0}/docs/OPERATIONS.md +0 -0
  180. {apsa-1.2.0 → apsa-1.3.0}/docs/PUBLISHING.md +0 -0
  181. {apsa-1.2.0 → apsa-1.3.0}/docs/THREAT_MODEL.md +0 -0
  182. {apsa-1.2.0 → apsa-1.3.0}/docs/legacy/MOBILE_AUDIT_1_0_READINESS.md +0 -0
  183. {apsa-1.2.0 → apsa-1.3.0}/docs/legacy/QUAYGATE_0_9.md +0 -0
  184. {apsa-1.2.0 → apsa-1.3.0}/examples/scenario.android.json +0 -0
  185. {apsa-1.2.0 → apsa-1.3.0}/quaygate/__main__.py +0 -0
  186. {apsa-1.2.0 → apsa-1.3.0}/quaygate/adb.py +0 -0
  187. {apsa-1.2.0 → apsa-1.3.0}/quaygate/apk.py +0 -0
  188. {apsa-1.2.0 → apsa-1.3.0}/quaygate/appchecks.py +0 -0
  189. {apsa-1.2.0 → apsa-1.3.0}/quaygate/apps.py +0 -0
  190. {apsa-1.2.0 → apsa-1.3.0}/quaygate/arsc.py +0 -0
  191. {apsa-1.2.0 → apsa-1.3.0}/quaygate/axml.py +0 -0
  192. {apsa-1.2.0 → apsa-1.3.0}/quaygate/cert.py +0 -0
  193. {apsa-1.2.0 → apsa-1.3.0}/quaygate/checks.py +0 -0
  194. {apsa-1.2.0 → apsa-1.3.0}/quaygate/cli.py +0 -0
  195. {apsa-1.2.0 → apsa-1.3.0}/quaygate/dex.py +0 -0
  196. {apsa-1.2.0 → apsa-1.3.0}/quaygate/dexcode.py +0 -0
  197. {apsa-1.2.0 → apsa-1.3.0}/quaygate/elf.py +0 -0
  198. {apsa-1.2.0 → apsa-1.3.0}/quaygate/indicators.py +0 -0
  199. {apsa-1.2.0 → apsa-1.3.0}/quaygate/ipa.py +0 -0
  200. {apsa-1.2.0 → apsa-1.3.0}/quaygate/legacy_cli.py +0 -0
  201. {apsa-1.2.0 → apsa-1.3.0}/quaygate/network_security.py +0 -0
  202. {apsa-1.2.0 → apsa-1.3.0}/quaygate/report.py +0 -0
  203. {apsa-1.2.0 → apsa-1.3.0}/requirements-release.txt +0 -0
  204. {apsa-1.2.0 → apsa-1.3.0}/scripts/licenses.py +0 -0
  205. {apsa-1.2.0 → apsa-1.3.0}/scripts/release-check.sh +0 -0
  206. {apsa-1.2.0 → apsa-1.3.0}/scripts/release.py +0 -0
  207. {apsa-1.2.0 → apsa-1.3.0}/scripts/verify_aab.py +0 -0
  208. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/__init__.py +0 -0
  209. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/__main__.py +0 -0
  210. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/_job_worker.py +0 -0
  211. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/_parser_worker.py +0 -0
  212. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/aab_manifest.py +0 -0
  213. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/baselines.py +0 -0
  214. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/data/demo/AndroidManifest.xml +0 -0
  215. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/data/demo/Demo.swift +0 -0
  216. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/data/demo/Info.plist +0 -0
  217. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/data/demo/MainActivity.kt +0 -0
  218. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/data/demo/build.gradle.kts +0 -0
  219. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/data/rules.json +0 -0
  220. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/data/structural-rules.json +0 -0
  221. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/engine.py +0 -0
  222. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/input_snapshot.py +0 -0
  223. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/ios_embedded.py +0 -0
  224. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/ios_ranges.py +0 -0
  225. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/jobs.py +0 -0
  226. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/mcp_server.py +0 -0
  227. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/model_context.py +0 -0
  228. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/output.py +0 -0
  229. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/parser_sandbox.py +0 -0
  230. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/policy.py +0 -0
  231. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/processes.py +0 -0
  232. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/quaygate_analysis.py +0 -0
  233. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/rules.py +0 -0
  234. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/selection.py +0 -0
  235. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/store.py +0 -0
  236. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/tools.py +0 -0
  237. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/tui.py +0 -0
  238. {apsa-1.2.0 → apsa-1.3.0}/src/mobile_audit/watch.py +0 -0
  239. {apsa-1.2.0 → apsa-1.3.0}/tests/__init__.py +0 -0
  240. {apsa-1.2.0 → apsa-1.3.0}/tests/conftest.py +0 -0
  241. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/ANDROGUARD-LICENCE +0 -0
  242. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/README.md +0 -0
  243. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/Test-debug.apk +0 -0
  244. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/binary_analysis/README.md +0 -0
  245. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/binary_analysis/build.py +0 -0
  246. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/binary_analysis/safe/Calls.java +0 -0
  247. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/binary_analysis/safe.apk +0 -0
  248. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/binary_analysis/unsafe/Calls.java +0 -0
  249. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/binary_analysis/unsafe.apk +0 -0
  250. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/runtime/README.md +0 -0
  251. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/runtime/android/AndroidManifest.xml +0 -0
  252. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/runtime/android/MainActivity.java +0 -0
  253. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/runtime/build.py +0 -0
  254. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/runtime/ios/Main.swift +0 -0
  255. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/runtime/verify.py +0 -0
  256. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/skills/apsa-1.0.3.md +0 -0
  257. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/skills/apsa-1.0.6.md +0 -0
  258. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/skills/apsa-1.1.0.md +0 -0
  259. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/skills/apsa-1.2.0.md +0 -0
  260. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/skills/mobile-audit-1.0.1.md +0 -0
  261. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/skills/mobile-audit-1.0.2.md +0 -0
  262. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/skills/mobile-audit-1.0.3.md +0 -0
  263. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/skills/mobile-audit-1.0.6.md +0 -0
  264. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/skills/mobile-audit-1.1.0.md +0 -0
  265. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/skills/mobile-audit-1.2.0.md +0 -0
  266. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/skills/quaygate-1.0.1.md +0 -0
  267. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/skills/quaygate-1.0.2.md +0 -0
  268. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/skills/quaygate-1.0.3.md +0 -0
  269. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/skills/quaygate-1.0.6.md +0 -0
  270. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/skills/quaygate-1.1.0.md +0 -0
  271. {apsa-1.2.0 → apsa-1.3.0}/tests/fixtures/skills/quaygate-1.2.0.md +0 -0
  272. {apsa-1.2.0 → apsa-1.3.0}/tests/helpers.py +0 -0
  273. {apsa-1.2.0 → apsa-1.3.0}/tests/test_apk_checks.py +0 -0
  274. {apsa-1.2.0 → apsa-1.3.0}/tests/test_apps.py +0 -0
  275. {apsa-1.2.0 → apsa-1.3.0}/tests/test_arsc.py +0 -0
  276. {apsa-1.2.0 → apsa-1.3.0}/tests/test_audit.py +0 -0
  277. {apsa-1.2.0 → apsa-1.3.0}/tests/test_axml.py +0 -0
  278. {apsa-1.2.0 → apsa-1.3.0}/tests/test_benchmark.py +0 -0
  279. {apsa-1.2.0 → apsa-1.3.0}/tests/test_binary_analysis.py +0 -0
  280. {apsa-1.2.0 → apsa-1.3.0}/tests/test_cert.py +0 -0
  281. {apsa-1.2.0 → apsa-1.3.0}/tests/test_competitive.py +0 -0
  282. {apsa-1.2.0 → apsa-1.3.0}/tests/test_coverage_extension.py +0 -0
  283. {apsa-1.2.0 → apsa-1.3.0}/tests/test_device_checks.py +0 -0
  284. {apsa-1.2.0 → apsa-1.3.0}/tests/test_dex.py +0 -0
  285. {apsa-1.2.0 → apsa-1.3.0}/tests/test_dexcode.py +0 -0
  286. {apsa-1.2.0 → apsa-1.3.0}/tests/test_elf.py +0 -0
  287. {apsa-1.2.0 → apsa-1.3.0}/tests/test_evidence106.py +0 -0
  288. {apsa-1.2.0 → apsa-1.3.0}/tests/test_foundations.py +0 -0
  289. {apsa-1.2.0 → apsa-1.3.0}/tests/test_intel.py +0 -0
  290. {apsa-1.2.0 → apsa-1.3.0}/tests/test_intel_product.py +0 -0
  291. {apsa-1.2.0 → apsa-1.3.0}/tests/test_interfaces.py +0 -0
  292. {apsa-1.2.0 → apsa-1.3.0}/tests/test_ipa.py +0 -0
  293. {apsa-1.2.0 → apsa-1.3.0}/tests/test_jobs.py +0 -0
  294. {apsa-1.2.0 → apsa-1.3.0}/tests/test_network_security.py +0 -0
  295. {apsa-1.2.0 → apsa-1.3.0}/tests/test_next_hardening.py +0 -0
  296. {apsa-1.2.0 → apsa-1.3.0}/tests/test_policy.py +0 -0
  297. {apsa-1.2.0 → apsa-1.3.0}/tests/test_product_review.py +0 -0
  298. {apsa-1.2.0 → apsa-1.3.0}/tests/test_real_world.py +0 -0
  299. {apsa-1.2.0 → apsa-1.3.0}/tests/test_real_world_hardening.py +0 -0
  300. {apsa-1.2.0 → apsa-1.3.0}/tests/test_release_hardening.py +0 -0
  301. {apsa-1.2.0 → apsa-1.3.0}/tests/test_report_cli.py +0 -0
  302. {apsa-1.2.0 → apsa-1.3.0}/tests/test_review3_regressions.py +0 -0
  303. {apsa-1.2.0 → apsa-1.3.0}/tests/test_runtime.py +0 -0
  304. {apsa-1.2.0 → apsa-1.3.0}/tests/test_security_primitives.py +0 -0
  305. {apsa-1.2.0 → apsa-1.3.0}/tests/test_source_analysis.py +0 -0
  306. {apsa-1.2.0 → apsa-1.3.0}/tests/test_unified.py +0 -0
  307. {apsa-1.2.0 → apsa-1.3.0}/tests/test_workflows11.py +0 -0
@@ -15,7 +15,7 @@ For a local audit, run `scan TARGET`. Source folders, APK, AAB and IPA are accep
15
15
 
16
16
  Use `scan TARGET --background` or MCP `audit_start` for long scans. Keep the returned job ID; poll `jobs status ID` / `jobs_status`, and use the corresponding cancel tool when requested. A completed job supplies a report ID. Failed, cancelled and interrupted jobs do not establish a successful audit. Closing the TUI or MCP client does not itself cancel persistent jobs.
17
17
 
18
- CLI analysis runs locally and does not upload app source or builds. Online OSV queries send dependency names and versions. MCP context sends finding metadata to the invoking client, which may forward it to a hosted model. Follow the user's model/data policy; local analysis is separate from whether the product is open source.
18
+ CLI analysis runs locally and does not upload app source or builds. Online OSV queries send dependency names and versions, including Gradle catalog aliases used in shipped configurations and release-runtime lockfile coordinates from any module (private group IDs too). One online run queries at most 100 packages: those without a recent OSV result first, declared packages and non-Gradle manifests before transitive Gradle lockfile coordinates. The rest without such a result stay not-run and the audit incomplete; repeated runs advance through them. MCP context sends finding metadata to the invoking client, which may forward it to a hosted model. Follow the user's model/data policy; local analysis is separate from whether the product is open source.
19
19
 
20
20
  Read exact finding evidence with `reports get REPORT_ID --finding FINDING_ID`, or MCP `reports_get`. Use `reports list` to resolve saved IDs. Keep app defects, included dependency CVEs and device/OS CVEs separate. Never infer device patch status from targetSdk/minSdk. Distinguish candidate, configuration-confirmed, version-affected and runtime-confirmed; a package match does not establish reachability or reproduction. Not-run, inconclusive and empty results do not establish safety.
21
21
 
@@ -43,8 +43,10 @@ Model report context is bounded and paginated. After resolving latest once, use
43
43
 
44
44
  Portable team baselines require explicit authorized approved_by and approval_reference metadata. Export with reports export --format baseline or MCP reports_export_baseline, then pin its returned SHA-256 in independently reviewed CI configuration. Evaluate with --baseline-file/--baseline-sha256 or MCP baseline_path/baseline_sha256; do not derive the expected hash from an untrusted artifact in CI. The hash proves integrity against the approved value, not approver identity or a digital signature. scan --policy with --out writes a separate .decision.json; --decision-out selects another path. The decision includes policy/report hashes, approval provenance and waiver details.
45
45
 
46
- AST coverage reports recognized/analyzed/skipped/bodyless function declarations; errors and unsupported syntax can hide additional functions. Local exports retain per-file inventory.source_analysis metadata. Kotlin open identifiers and Swift nonisolated(unsafe) variable compatibility keep files partial and original evidence offsets. For Apple mobile device-info JSON, os_product=ipados explicitly selects iPadOS; default ios does not match iPadOS-only ranges. Apple custom ranges require CNA identity plus matching official bulletin branch/reference. Outside-published-affected-range does not prove patching; older CVE cache entries without identity need refetching.
46
+ AST coverage reports recognized/analyzed/skipped/bodyless function declarations; errors and unsupported syntax can hide additional functions. Local exports retain per-file inventory.source_analysis metadata. Kotlin open identifiers and Swift nonisolated(unsafe) variable compatibility keep files partial and original evidence offsets. For Apple mobile device-info JSON, os_product=ipados explicitly selects iPadOS; default ios does not match iPadOS-only ranges. Apple custom ranges require CNA identity plus matching official bulletin branch/reference. Outside-published-affected-range does not prove patching; older CVE cache entries without identity need refetching. Android device-info may add soc_manufacturer, soc_model and vendor_security_patch; chipset and kernel bulletin entries use the older of the platform and vendor patch levels, and chipset_vendor match/mismatch is recorded beside the patch-level state without replacing it. `intel backfill --source android --since YYYY-MM` fetches an explicit bounded month range; Apple history is not backfilled.
47
47
 
48
- AAB analysis decodes the base AAPT2 protobuf manifest and reads module DEX with module provenance. Resource/feature-manifest merging and the installed split set remain unverified; bundle audits stay partial. IPA embedded framework, extension and dylib metadata retain separate roles and hashes without replacing the main identity. Native code paths and signature authenticity remain unverified. Objective-C .m has bounded CST navigation/weak-digest candidates, always partial; .mm, macros, dispatch and interprocedural flow remain unsupported.
48
+ Gradle catalog aliases referenced from shipped dependency configurations become declared candidates; unreferenced, test and build-tooling aliases stay unresolved usage. Application-module gradle.lockfile runtime coordinates are exact, so their matches are version-affected; other modules' lockfile coordinates stay declared candidates. A declared candidate is superseded (not-applicable) only when every shipping application that reaches it resolved the package; partial inputs keep every candidate, and with unparsed project references only an application's own declarations can be superseded. Lockfile-resolved findings get a new identity, so baselines and waivers need re-approval.
49
+
50
+ AAB analysis decodes the base and feature-module AAPT2 protobuf manifests and reads module DEX with module provenance. Feature components and deep links carry their module and declared delivery; identity and application flags come only from the base manifest. Resource merging and the installed split set remain unverified; bundle audits stay partial. IPA embedded framework, extension and dylib metadata retain separate roles and hashes without replacing the main identity. CodeDirectory page and entitlement hashes are recomputed for BINARY-IOS-CODE-INTEGRITY: a mismatch is modified, while encrypted or unsigned executables stay not-run or unverifiable. The CMS signature, certificate chain, team and provisioning are not authenticated, so signature_verified stays false. Native code paths remain unverified. Objective-C .m has bounded CST navigation/weak-digest candidates, always partial. NS_ENUM-family macros and one branch per preprocessor conditional are adapted; a function overlapping a normalized conditional is skipped as uncertain. .mm, other macros, dispatch and interprocedural flow remain unsupported.
49
51
 
50
52
  The parser reports inventory.parser_isolation. APSA_PARSER_SANDBOX=auto uses system Seatbelt/bubblewrap when an input-free activation probe succeeds and otherwise records unavailable with the reason; required refuses unavailable isolation; off reports resource-limits-only. Once the parser has launched under isolation, a failure never retries unsandboxed. Availability in doctor is not activation evidence. Only a successful worker launch records enforced isolation.
@@ -15,7 +15,7 @@ For a local audit, run `scan TARGET`. Source folders, APK, AAB and IPA are accep
15
15
 
16
16
  Use `scan TARGET --background` or MCP `audit_start` for long scans. Keep the returned job ID; poll `jobs status ID` / `jobs_status`, and use the corresponding cancel tool when requested. A completed job supplies a report ID. Failed, cancelled and interrupted jobs do not establish a successful audit. Closing the TUI or MCP client does not itself cancel persistent jobs.
17
17
 
18
- CLI analysis runs locally and does not upload app source or builds. Online OSV queries send dependency names and versions. MCP context sends finding metadata to the invoking client, which may forward it to a hosted model. Follow the user's model/data policy; local analysis is separate from whether the product is open source.
18
+ CLI analysis runs locally and does not upload app source or builds. Online OSV queries send dependency names and versions, including Gradle catalog aliases used in shipped configurations and release-runtime lockfile coordinates from any module (private group IDs too). One online run queries at most 100 packages: those without a recent OSV result first, declared packages and non-Gradle manifests before transitive Gradle lockfile coordinates. The rest without such a result stay not-run and the audit incomplete; repeated runs advance through them. MCP context sends finding metadata to the invoking client, which may forward it to a hosted model. Follow the user's model/data policy; local analysis is separate from whether the product is open source.
19
19
 
20
20
  Read exact finding evidence with `reports get REPORT_ID --finding FINDING_ID`, or MCP `reports_get`. Use `reports list` to resolve saved IDs. Keep app defects, included dependency CVEs and device/OS CVEs separate. Never infer device patch status from targetSdk/minSdk. Distinguish candidate, configuration-confirmed, version-affected and runtime-confirmed; a package match does not establish reachability or reproduction. Not-run, inconclusive and empty results do not establish safety.
21
21
 
@@ -43,8 +43,10 @@ Model report context is bounded and paginated. After resolving latest once, use
43
43
 
44
44
  Portable team baselines require explicit authorized approved_by and approval_reference metadata. Export with reports export --format baseline or MCP reports_export_baseline, then pin its returned SHA-256 in independently reviewed CI configuration. Evaluate with --baseline-file/--baseline-sha256 or MCP baseline_path/baseline_sha256; do not derive the expected hash from an untrusted artifact in CI. The hash proves integrity against the approved value, not approver identity or a digital signature. scan --policy with --out writes a separate .decision.json; --decision-out selects another path. The decision includes policy/report hashes, approval provenance and waiver details.
45
45
 
46
- AST coverage reports recognized/analyzed/skipped/bodyless function declarations; errors and unsupported syntax can hide additional functions. Local exports retain per-file inventory.source_analysis metadata. Kotlin open identifiers and Swift nonisolated(unsafe) variable compatibility keep files partial and original evidence offsets. For Apple mobile device-info JSON, os_product=ipados explicitly selects iPadOS; default ios does not match iPadOS-only ranges. Apple custom ranges require CNA identity plus matching official bulletin branch/reference. Outside-published-affected-range does not prove patching; older CVE cache entries without identity need refetching.
46
+ AST coverage reports recognized/analyzed/skipped/bodyless function declarations; errors and unsupported syntax can hide additional functions. Local exports retain per-file inventory.source_analysis metadata. Kotlin open identifiers and Swift nonisolated(unsafe) variable compatibility keep files partial and original evidence offsets. For Apple mobile device-info JSON, os_product=ipados explicitly selects iPadOS; default ios does not match iPadOS-only ranges. Apple custom ranges require CNA identity plus matching official bulletin branch/reference. Outside-published-affected-range does not prove patching; older CVE cache entries without identity need refetching. Android device-info may add soc_manufacturer, soc_model and vendor_security_patch; chipset and kernel bulletin entries use the older of the platform and vendor patch levels, and chipset_vendor match/mismatch is recorded beside the patch-level state without replacing it. `intel backfill --source android --since YYYY-MM` fetches an explicit bounded month range; Apple history is not backfilled.
47
47
 
48
- AAB analysis decodes the base AAPT2 protobuf manifest and reads module DEX with module provenance. Resource/feature-manifest merging and the installed split set remain unverified; bundle audits stay partial. IPA embedded framework, extension and dylib metadata retain separate roles and hashes without replacing the main identity. Native code paths and signature authenticity remain unverified. Objective-C .m has bounded CST navigation/weak-digest candidates, always partial; .mm, macros, dispatch and interprocedural flow remain unsupported.
48
+ Gradle catalog aliases referenced from shipped dependency configurations become declared candidates; unreferenced, test and build-tooling aliases stay unresolved usage. Application-module gradle.lockfile runtime coordinates are exact, so their matches are version-affected; other modules' lockfile coordinates stay declared candidates. A declared candidate is superseded (not-applicable) only when every shipping application that reaches it resolved the package; partial inputs keep every candidate, and with unparsed project references only an application's own declarations can be superseded. Lockfile-resolved findings get a new identity, so baselines and waivers need re-approval.
49
+
50
+ AAB analysis decodes the base and feature-module AAPT2 protobuf manifests and reads module DEX with module provenance. Feature components and deep links carry their module and declared delivery; identity and application flags come only from the base manifest. Resource merging and the installed split set remain unverified; bundle audits stay partial. IPA embedded framework, extension and dylib metadata retain separate roles and hashes without replacing the main identity. CodeDirectory page and entitlement hashes are recomputed for BINARY-IOS-CODE-INTEGRITY: a mismatch is modified, while encrypted or unsigned executables stay not-run or unverifiable. The CMS signature, certificate chain, team and provisioning are not authenticated, so signature_verified stays false. Native code paths remain unverified. Objective-C .m has bounded CST navigation/weak-digest candidates, always partial. NS_ENUM-family macros and one branch per preprocessor conditional are adapted; a function overlapping a normalized conditional is skipped as uncertain. .mm, other macros, dispatch and interprocedural flow remain unsupported.
49
51
 
50
52
  The parser reports inventory.parser_isolation. APSA_PARSER_SANDBOX=auto uses system Seatbelt/bubblewrap when an input-free activation probe succeeds and otherwise records unavailable with the reason; required refuses unavailable isolation; off reports resource-limits-only. Once the parser has launched under isolation, a failure never retries unsandboxed. Availability in doctor is not activation evidence. Only a successful worker launch records enforced isolation.
@@ -15,7 +15,7 @@ For a local audit, run `scan TARGET`. Source folders, APK, AAB and IPA are accep
15
15
 
16
16
  Use `scan TARGET --background` or MCP `audit_start` for long scans. Keep the returned job ID; poll `jobs status ID` / `jobs_status`, and use the corresponding cancel tool when requested. A completed job supplies a report ID. Failed, cancelled and interrupted jobs do not establish a successful audit. Closing the TUI or MCP client does not itself cancel persistent jobs.
17
17
 
18
- CLI analysis runs locally and does not upload app source or builds. Online OSV queries send dependency names and versions. MCP context sends finding metadata to the invoking client, which may forward it to a hosted model. Follow the user's model/data policy; local analysis is separate from whether the product is open source.
18
+ CLI analysis runs locally and does not upload app source or builds. Online OSV queries send dependency names and versions, including Gradle catalog aliases used in shipped configurations and release-runtime lockfile coordinates from any module (private group IDs too). One online run queries at most 100 packages: those without a recent OSV result first, declared packages and non-Gradle manifests before transitive Gradle lockfile coordinates. The rest without such a result stay not-run and the audit incomplete; repeated runs advance through them. MCP context sends finding metadata to the invoking client, which may forward it to a hosted model. Follow the user's model/data policy; local analysis is separate from whether the product is open source.
19
19
 
20
20
  Read exact finding evidence with `reports get REPORT_ID --finding FINDING_ID`, or MCP `reports_get`. Use `reports list` to resolve saved IDs. Keep app defects, included dependency CVEs and device/OS CVEs separate. Never infer device patch status from targetSdk/minSdk. Distinguish candidate, configuration-confirmed, version-affected and runtime-confirmed; a package match does not establish reachability or reproduction. Not-run, inconclusive and empty results do not establish safety.
21
21
 
@@ -43,8 +43,10 @@ Model report context is bounded and paginated. After resolving latest once, use
43
43
 
44
44
  Portable team baselines require explicit authorized approved_by and approval_reference metadata. Export with reports export --format baseline or MCP reports_export_baseline, then pin its returned SHA-256 in independently reviewed CI configuration. Evaluate with --baseline-file/--baseline-sha256 or MCP baseline_path/baseline_sha256; do not derive the expected hash from an untrusted artifact in CI. The hash proves integrity against the approved value, not approver identity or a digital signature. scan --policy with --out writes a separate .decision.json; --decision-out selects another path. The decision includes policy/report hashes, approval provenance and waiver details.
45
45
 
46
- AST coverage reports recognized/analyzed/skipped/bodyless function declarations; errors and unsupported syntax can hide additional functions. Local exports retain per-file inventory.source_analysis metadata. Kotlin open identifiers and Swift nonisolated(unsafe) variable compatibility keep files partial and original evidence offsets. For Apple mobile device-info JSON, os_product=ipados explicitly selects iPadOS; default ios does not match iPadOS-only ranges. Apple custom ranges require CNA identity plus matching official bulletin branch/reference. Outside-published-affected-range does not prove patching; older CVE cache entries without identity need refetching.
46
+ AST coverage reports recognized/analyzed/skipped/bodyless function declarations; errors and unsupported syntax can hide additional functions. Local exports retain per-file inventory.source_analysis metadata. Kotlin open identifiers and Swift nonisolated(unsafe) variable compatibility keep files partial and original evidence offsets. For Apple mobile device-info JSON, os_product=ipados explicitly selects iPadOS; default ios does not match iPadOS-only ranges. Apple custom ranges require CNA identity plus matching official bulletin branch/reference. Outside-published-affected-range does not prove patching; older CVE cache entries without identity need refetching. Android device-info may add soc_manufacturer, soc_model and vendor_security_patch; chipset and kernel bulletin entries use the older of the platform and vendor patch levels, and chipset_vendor match/mismatch is recorded beside the patch-level state without replacing it. `intel backfill --source android --since YYYY-MM` fetches an explicit bounded month range; Apple history is not backfilled.
47
47
 
48
- AAB analysis decodes the base AAPT2 protobuf manifest and reads module DEX with module provenance. Resource/feature-manifest merging and the installed split set remain unverified; bundle audits stay partial. IPA embedded framework, extension and dylib metadata retain separate roles and hashes without replacing the main identity. Native code paths and signature authenticity remain unverified. Objective-C .m has bounded CST navigation/weak-digest candidates, always partial; .mm, macros, dispatch and interprocedural flow remain unsupported.
48
+ Gradle catalog aliases referenced from shipped dependency configurations become declared candidates; unreferenced, test and build-tooling aliases stay unresolved usage. Application-module gradle.lockfile runtime coordinates are exact, so their matches are version-affected; other modules' lockfile coordinates stay declared candidates. A declared candidate is superseded (not-applicable) only when every shipping application that reaches it resolved the package; partial inputs keep every candidate, and with unparsed project references only an application's own declarations can be superseded. Lockfile-resolved findings get a new identity, so baselines and waivers need re-approval.
49
+
50
+ AAB analysis decodes the base and feature-module AAPT2 protobuf manifests and reads module DEX with module provenance. Feature components and deep links carry their module and declared delivery; identity and application flags come only from the base manifest. Resource merging and the installed split set remain unverified; bundle audits stay partial. IPA embedded framework, extension and dylib metadata retain separate roles and hashes without replacing the main identity. CodeDirectory page and entitlement hashes are recomputed for BINARY-IOS-CODE-INTEGRITY: a mismatch is modified, while encrypted or unsigned executables stay not-run or unverifiable. The CMS signature, certificate chain, team and provisioning are not authenticated, so signature_verified stays false. Native code paths remain unverified. Objective-C .m has bounded CST navigation/weak-digest candidates, always partial. NS_ENUM-family macros and one branch per preprocessor conditional are adapted; a function overlapping a normalized conditional is skipped as uncertain. .mm, other macros, dispatch and interprocedural flow remain unsupported.
49
51
 
50
52
  The parser reports inventory.parser_isolation. APSA_PARSER_SANDBOX=auto uses system Seatbelt/bubblewrap when an input-free activation probe succeeds and otherwise records unavailable with the reason; required refuses unavailable isolation; off reports resource-limits-only. Once the parser has launched under isolation, a failure never retries unsandboxed. Availability in doctor is not activation evidence. Only a successful worker launch records enforced isolation.
@@ -0,0 +1,47 @@
1
+ name: Catalog usage and lockfile evidence against the Gradle oracle
2
+
3
+ on:
4
+ push:
5
+ branches: ["dev/dependency-evidence", "dev/evidence-depth"]
6
+ paths: ["src/**", "benchmarks/dependency_eval.py", "benchmarks/dependency_truth*.json", "benchmarks/dependency_locks/**", ".github/workflows/dependency-evaluation.yml"]
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+ actions: read
12
+
13
+ jobs:
14
+ evaluate:
15
+ runs-on: ubuntu-24.04
16
+ timeout-minutes: 30
17
+ steps:
18
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
19
+ with:
20
+ persist-credentials: false
21
+ - uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7
22
+ with:
23
+ version: "0.12.1"
24
+ python-version: "3.12.13"
25
+ enable-cache: false
26
+ - run: uv sync --locked --extra dev
27
+ - name: Download the frozen oracle source archives
28
+ env:
29
+ GH_TOKEN: ${{ github.token }}
30
+ run: |
31
+ for RUN_ID in $(python3 -c 'import glob, json; print(" ".join(sorted({str(json.load(open(p))["oracle_run"]) for p in glob.glob("benchmarks/dependency_truth*.json")})))'); do
32
+ gh run download "$RUN_ID" --repo "$GITHUB_REPOSITORY" --pattern 'dependency-oracle-*' --dir "$RUNNER_TEMP/oracle/$RUN_ID"
33
+ done
34
+ - name: Scan pinned sources with APSA only; no Gradle or upstream code runs
35
+ env:
36
+ APSA_PARSER_LOCK_DIR: ${{ runner.temp }}/dependency-parser-locks
37
+ run: |
38
+ uv run --locked python -m benchmarks.dependency_eval \
39
+ --archives "$RUNNER_TEMP/oracle" --work "$RUNNER_TEMP/eval-work" \
40
+ --out "$RUNNER_TEMP/dependency-evidence/results.json"
41
+ - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
42
+ if: always()
43
+ with:
44
+ name: dependency-evidence-evaluation
45
+ path: ${{ runner.temp }}/dependency-evidence
46
+ retention-days: 90
47
+ if-no-files-found: error
@@ -0,0 +1,77 @@
1
+ name: Gradle dependency resolution oracle
2
+
3
+ on:
4
+ push:
5
+ branches: ["dev/dependency-evidence"]
6
+ paths: ["benchmarks/dependency_cases.json", "benchmarks/dependency_oracle.py", ".github/workflows/dependency-oracle.yml"]
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ oracle:
14
+ name: Resolve ${{ matrix.case }} with Gradle
15
+ runs-on: ubuntu-24.04
16
+ timeout-minutes: 40
17
+ strategy:
18
+ fail-fast: false
19
+ matrix:
20
+ include:
21
+ - case: owncloud
22
+ java: "21"
23
+ - case: nextcloud
24
+ java: "21"
25
+ - case: home-assistant
26
+ java: "21"
27
+ - case: signal
28
+ java: "21"
29
+ - case: amaze
30
+ java: "21"
31
+ steps:
32
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
33
+ with:
34
+ persist-credentials: false
35
+ path: apsa
36
+ - uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1
37
+ with:
38
+ distribution: temurin
39
+ java-version: ${{ matrix.java }}
40
+ - name: Fetch the pinned public source archive
41
+ id: fetch
42
+ working-directory: apsa
43
+ run: |
44
+ SHA="$(python3 -I benchmarks/dependency_oracle.py prepare --case "${{ matrix.case }}" --work "$RUNNER_TEMP/oracle")"
45
+ echo "sha256=$SHA" >> "$GITHUB_OUTPUT"
46
+ - name: Let Gradle resolve and lock every configuration of the app module
47
+ run: |
48
+ cat > "$RUNNER_TEMP/lock-all.gradle" <<'GRADLE'
49
+ // Isolated-projects compatible (Gradle 8.8+): lock every configuration of every project.
50
+ gradle.lifecycle.beforeProject { project ->
51
+ project.dependencyLocking { lockAllConfigurations() }
52
+ }
53
+ GRADLE
54
+ cd "$(find "$RUNNER_TEMP/oracle/source" -mindepth 1 -maxdepth 1 -type d)"
55
+ grep -h distributionUrl gradle/wrapper/gradle-wrapper.properties
56
+ MODULE="$(python3 -c 'import json,sys; print(next(c["module"] for c in json.load(open(sys.argv[1]))["cases"] if c["id"] == sys.argv[2]))' "$GITHUB_WORKSPACE/apsa/benchmarks/dependency_cases.json" "${{ matrix.case }}")"
57
+ rm -f "$(echo "${MODULE#:}" | tr : /)/gradle.lockfile"
58
+ ./gradlew --no-daemon --init-script "$RUNNER_TEMP/lock-all.gradle" \
59
+ "$MODULE:dependencies" --write-locks > "$RUNNER_TEMP/oracle/${{ matrix.case }}.dependencies.txt" 2>&1 \
60
+ || { tail -80 "$RUNNER_TEMP/oracle/${{ matrix.case }}.dependencies.txt"; exit 1; }
61
+ java -version 2>&1 | head -1 > "$RUNNER_TEMP/oracle/${{ matrix.case }}.java.txt"
62
+ ./gradlew --no-daemon --version >> "$RUNNER_TEMP/oracle/${{ matrix.case }}.java.txt"
63
+ - name: Record the resolved oracle without running APSA
64
+ working-directory: apsa
65
+ run: python3 -I benchmarks/dependency_oracle.py record --case "${{ matrix.case }}" --work "$RUNNER_TEMP/oracle" --expected-sha256 "${{ steps.fetch.outputs.sha256 }}"
66
+ - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
67
+ if: always()
68
+ with:
69
+ name: dependency-oracle-${{ matrix.case }}
70
+ path: |
71
+ ${{ runner.temp }}/oracle/*.zip
72
+ ${{ runner.temp }}/oracle/*.json
73
+ ${{ runner.temp }}/oracle/*.lockfile
74
+ ${{ runner.temp }}/oracle/*.txt
75
+ retention-days: 90
76
+ if-no-files-found: error
77
+ # APSA is not installed or executed here; upstream Gradle build logic runs on this disposable runner without secrets.
@@ -0,0 +1,43 @@
1
+ name: Independent vulnerable and fixed source pairs
2
+
3
+ on:
4
+ push:
5
+ branches: ["dev/evidence-depth"]
6
+ paths: ["src/**", "benchmarks/fpfn_eval.py", "benchmarks/fpfn_truth*.json", ".github/workflows/fpfn-evaluation.yml"]
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ evaluate:
14
+ runs-on: ubuntu-24.04
15
+ timeout-minutes: 90
16
+ steps:
17
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
18
+ with:
19
+ persist-credentials: false
20
+ - uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7
21
+ with:
22
+ version: "0.12.1"
23
+ python-version: "3.12.13"
24
+ enable-cache: false
25
+ - run: uv sync --locked --extra dev
26
+ - name: Scan each pinned vulnerable and fixed commit with APSA only
27
+ run: |
28
+ uv run --locked python -m benchmarks.fpfn_eval \
29
+ --work "$RUNNER_TEMP/fpfn-work" --out "$RUNNER_TEMP/fpfn/results.json"
30
+ - name: Keep the captured public archives and reports
31
+ if: always()
32
+ run: |
33
+ mkdir -p "$RUNNER_TEMP/fpfn/captures"
34
+ cd "$RUNNER_TEMP/fpfn-work" 2>/dev/null && find . \( -name source.zip -o -name report.json \) -print0 \
35
+ | xargs -0 -I{} cp --parents {} "$RUNNER_TEMP/fpfn/captures/" || true
36
+ - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
37
+ if: always()
38
+ with:
39
+ name: independent-fpfn-pairs
40
+ path: ${{ runner.temp }}/fpfn
41
+ retention-days: 90
42
+ if-no-files-found: error
43
+ # Only APSA executes. No upstream app build, backend, device, private data or publishing.
@@ -2,7 +2,7 @@ name: Replay frozen public evidence and coverage extension
2
2
 
3
3
  on:
4
4
  push:
5
- branches: ["hardening/real-app-cve-v1"]
5
+ branches: ["hardening/real-app-cve-v1", "dev/dependency-evidence", "dev/evidence-depth"]
6
6
  paths:
7
7
  - "src/**"
8
8
  - "benchmarks/hardening_replay.py"
@@ -11,9 +11,9 @@ install-skill:
11
11
 
12
12
  test:
13
13
  $(UV_RUN) pytest -q
14
- $(UV_RUN) ruff check apsa src benchmarks scripts quaygate/cli.py tests/test_audit.py tests/test_benchmark.py tests/test_binary_analysis.py tests/test_foundations.py tests/test_intel.py tests/test_intel_product.py tests/test_interfaces.py tests/test_jobs.py tests/test_policy.py tests/test_runtime.py tests/test_source_analysis.py tests/test_unified.py tests/test_product_review.py tests/test_release_hardening.py tests/test_evidence106.py tests/test_workflows11.py tests/test_real_world_hardening.py tests/test_coverage_extension.py tests/test_next_hardening.py
15
- $(UV_RUN) ruff format --check apsa src benchmarks scripts quaygate/cli.py tests/test_audit.py tests/test_benchmark.py tests/test_binary_analysis.py tests/test_foundations.py tests/test_intel.py tests/test_intel_product.py tests/test_interfaces.py tests/test_jobs.py tests/test_policy.py tests/test_runtime.py tests/test_source_analysis.py tests/test_unified.py tests/test_product_review.py tests/test_release_hardening.py tests/test_evidence106.py tests/test_workflows11.py tests/test_real_world_hardening.py tests/test_coverage_extension.py tests/test_next_hardening.py
16
- $(UV_RUN) pyright apsa src benchmarks scripts quaygate/cli.py tests/test_audit.py tests/test_benchmark.py tests/test_binary_analysis.py tests/test_foundations.py tests/test_intel.py tests/test_intel_product.py tests/test_interfaces.py tests/test_jobs.py tests/test_policy.py tests/test_runtime.py tests/test_source_analysis.py tests/test_unified.py tests/test_product_review.py tests/test_release_hardening.py tests/test_evidence106.py tests/test_workflows11.py tests/test_real_world_hardening.py tests/test_coverage_extension.py tests/test_next_hardening.py
14
+ $(UV_RUN) ruff check apsa src benchmarks scripts quaygate/cli.py tests/test_audit.py tests/test_benchmark.py tests/test_binary_analysis.py tests/test_foundations.py tests/test_intel.py tests/test_intel_product.py tests/test_interfaces.py tests/test_jobs.py tests/test_policy.py tests/test_runtime.py tests/test_source_analysis.py tests/test_unified.py tests/test_product_review.py tests/test_release_hardening.py tests/test_evidence106.py tests/test_workflows11.py tests/test_real_world_hardening.py tests/test_coverage_extension.py tests/test_next_hardening.py tests/test_dependency_evidence.py tests/test_parser_depth.py tests/test_intel_history.py
15
+ $(UV_RUN) ruff format --check apsa src benchmarks scripts quaygate/cli.py tests/test_audit.py tests/test_benchmark.py tests/test_binary_analysis.py tests/test_foundations.py tests/test_intel.py tests/test_intel_product.py tests/test_interfaces.py tests/test_jobs.py tests/test_policy.py tests/test_runtime.py tests/test_source_analysis.py tests/test_unified.py tests/test_product_review.py tests/test_release_hardening.py tests/test_evidence106.py tests/test_workflows11.py tests/test_real_world_hardening.py tests/test_coverage_extension.py tests/test_next_hardening.py tests/test_dependency_evidence.py tests/test_parser_depth.py tests/test_intel_history.py
16
+ $(UV_RUN) pyright apsa src benchmarks scripts quaygate/cli.py tests/test_audit.py tests/test_benchmark.py tests/test_binary_analysis.py tests/test_foundations.py tests/test_intel.py tests/test_intel_product.py tests/test_interfaces.py tests/test_jobs.py tests/test_policy.py tests/test_runtime.py tests/test_source_analysis.py tests/test_unified.py tests/test_product_review.py tests/test_release_hardening.py tests/test_evidence106.py tests/test_workflows11.py tests/test_real_world_hardening.py tests/test_coverage_extension.py tests/test_next_hardening.py tests/test_dependency_evidence.py tests/test_parser_depth.py tests/test_intel_history.py
17
17
 
18
18
  benchmark:
19
19
  $(UV_RUN) python benchmarks/run.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: apsa
3
- Version: 1.2.0
3
+ Version: 1.3.0
4
4
  Summary: APSA (앱사): evidence-first security audits for Android and iOS
5
5
  Project-URL: Homepage, https://github.com/ictechgy/apsa
6
6
  Project-URL: Repository, https://github.com/ictechgy/apsa
@@ -69,14 +69,69 @@ CVE matches until build usage or resolved versions are supplied. New rules
69
69
  `OBJC-CRYPTO-WEAK-HASH`, `OBJC-WEBVIEW-UNTRUSTED-REQUEST`) can add findings
70
70
  relative to existing 1.1 baselines.
71
71
 
72
+ APSA 1.3 links Gradle version-catalog aliases to the shipped dependency
73
+ configurations that use them and reads application-module `gradle.lockfile`
74
+ coordinates as resolved versions. It also decodes AAB feature-module manifests,
75
+ recomputes Mach-O CodeDirectory page and entitlement hashes without
76
+ authenticating the signature, adapts more Swift and Objective-C syntax, and can
77
+ backfill an explicit range of Android security bulletins with SoC vendor and
78
+ vendor patch-level context. See the
79
+ [dependency evidence results](https://github.com/ictechgy/apsa/blob/main/benchmarks/DEPENDENCY_RESULTS.md),
80
+ the [independent source pairs](https://github.com/ictechgy/apsa/blob/main/benchmarks/FPFN_RESULTS.md)
81
+ and [analysis scope and limits](https://github.com/ictechgy/apsa/blob/main/docs/NEXT_ANALYSIS.md).
82
+
83
+ **Upgrading from 1.2.**
84
+
85
+ - Catalog aliases referenced from shipped configurations become `declared`
86
+ candidates and can receive CVE matches again; unreferenced, test-only and
87
+ build-tooling aliases stay unresolved. Application-module lockfile coordinates
88
+ are exact, so their matches are `version-affected`, and the default policy
89
+ fails on high and critical ones; other modules' lockfile coordinates stay
90
+ `declared` candidates. A declared candidate that every shipping application
91
+ resolved is superseded and leaves CVE correlation. Partial inputs keep every
92
+ candidate, and with unparsed project references only an application's own
93
+ declarations can be superseded.
94
+ - Lockfile assumptions: APSA does not check that dependency locking is enabled
95
+ or that the lockfile is current, and it merges the release runtime classpaths
96
+ of every application module (flavors and wear, TV or automotive apps).
97
+ `--source-module` scans only that module's directory, so a root version
98
+ catalog and library-module declarations outside it are not read.
99
+ - Baselines and waivers: a lockfile-resolved finding has a new location
100
+ (`gradle.lockfile`) and status, so `only_new` treats it as new and waivers for
101
+ the old finding ID no longer match. Re-approve baselines after upgrading.
102
+ - `--online` sends catalog aliases used in shipped configurations and the
103
+ release-runtime lockfile coordinates of every module, transitive ones and
104
+ private group IDs included, to OSV; there is no exclusion list. One run
105
+ queries at most 100 packages: those without an OSV result from the last day
106
+ first, and among them build-file declarations before lockfile coordinates in
107
+ lockfile order. Measured application lockfiles hold 179–412 shipped
108
+ coordinates, so a single run leaves the rest `not-run`: a required
109
+ `DEPENDENCY-CVE` rule cannot pass, the online audit is incomplete and the
110
+ default `fail_on_partial` policy exits 3. Repeated runs within a day advance
111
+ through the remainder, and a package with an OSV result from the last day
112
+ counts as checked. Unresolved catalog aliases and ecosystems OSV does not
113
+ support are reported as online errors on every run, so they keep the online
114
+ audit incomplete however many runs follow.
115
+ - IPA reports gain `BINARY-IOS-CODE-INTEGRITY`. Consistent hashes do not prove
116
+ authenticity, because a modified binary that was re-signed is consistent. A
117
+ mismatch adds a warning, not a finding; App Store encrypted and unsigned
118
+ executables stay `not-run`.
119
+ - `intel sync` refreshes only the recent Android bulletin window; use
120
+ `intel backfill` for older months. Records cached by 1.2 derive their vendor
121
+ scope from the component name; entries outside chipset and kernel sections use
122
+ the platform patch level only. AAB feature-module installation stays unknown.
123
+ - Adapted Swift and Objective-C files stay partial, and an Objective-C function
124
+ overlapping a normalized preprocessor conditional is skipped as uncertain.
125
+ Unmodified 1.2 skills upgrade with `apsa skill install`.
126
+
72
127
  ## What it checks
73
128
 
74
129
  | Area | Available checks |
75
130
  | --- | --- |
76
- | Source code | Java/Kotlin/Swift AST analysis; bounded Objective-C `.m` candidates; WebView and deep-link patterns; Manifest, Info.plist, storage, and dependency inspection |
77
- | Android builds | DEX calls and constant flow; AAB base manifest and module DEX (always partial); resources and network configuration; exported components/providers; signing-block and v1 certificate evidence; ELF hardening |
78
- | iOS builds | Mach-O headers, including embedded framework/extension metadata; limited entitlement/configuration checks (embedded XML entitlements, ATS exceptions, provisioning indicators); PIE, canary, and string evidence |
79
- | Public intelligence | Apple/Android advisories, CVE, CISA KEV, OWASP guidance, and OSV dependency correlation |
131
+ | Source code | Java/Kotlin/Swift AST analysis; bounded Objective-C `.m` candidates; WebView and deep-link patterns; Manifest, Info.plist, storage, and dependency inspection, including Gradle catalog usage and application lockfiles |
132
+ | Android builds | DEX calls and constant flow; AAB base and feature-module manifests and module DEX (always partial); resources and network configuration; exported components/providers; signing-block and v1 certificate evidence; ELF hardening |
133
+ | iOS builds | Mach-O headers, including embedded framework/extension metadata; CodeDirectory page and entitlement hash integrity (not signature authentication); limited entitlement/configuration checks (embedded XML entitlements, ATS exceptions, provisioning indicators); PIE, canary, and string evidence |
134
+ | Public intelligence | Apple/Android advisories with bounded Android bulletin backfill, CVE, CISA KEV, OWASP guidance, and OSV dependency correlation |
80
135
  | Reports and CI | SQLite history, comparison and reassessment, JSON/Markdown/SARIF export, coverage requirements, and expiring waivers |
81
136
  | Runtime | Prepared scenarios for owned Android test apps and iOS simulator apps; physical iOS devices are unsupported |
82
137
  | Model integration | stdio MCP tools/resources and packaged skills, without a required model provider or LLM API key |
@@ -92,7 +147,7 @@ Install **uv** on **macOS or Linux**. APSA targets **CPython 3.11 and 3.12**; no
92
147
  Install the published package from [PyPI](https://pypi.org/project/apsa/):
93
148
 
94
149
  ```sh
95
- uv tool install --python 3.12 apsa==1.2.0
150
+ uv tool install --python 3.12 apsa==1.3.0
96
151
  apsa --version
97
152
  apsa doctor --json
98
153
  apsa demo --out ./apsa-demo
@@ -139,8 +194,9 @@ A default `scan` reads local files and cached intelligence without uploading sou
139
194
  | `apsa scan TARGET` | Uses local inputs and cached intelligence |
140
195
  | `apsa intel sync` | Fetches public vulnerability sources |
141
196
  | `apsa intel watch` | Polls public sources and reassesses saved inventories; does not reread app files or implicitly query OSV |
142
- | `apsa scan TARGET --online` | Sends discovered dependency names and versions to OSV |
143
- | `apsa intel watch --online` | Also sends saved dependency names and versions to OSV |
197
+ | `apsa intel backfill --source android --since YYYY-MM` | Fetches an explicit, bounded range of monthly Android security bulletins |
198
+ | `apsa scan TARGET --online` | Sends discovered dependency names and versions to OSV, including Gradle catalog aliases used in shipped configurations and release-runtime lockfile coordinates of every module; at most 100 packages per run, unchecked build-file declarations first |
199
+ | `apsa intel watch --online` | Also sends saved dependency names and versions to OSV, with the same budget |
144
200
 
145
201
  ```sh
146
202
  apsa intel sync
@@ -259,7 +315,9 @@ A reproducible [APSA/MobSF comparison](benchmarks/COMPETITIVE.md) and its
259
315
  [recorded results](benchmarks/COMPETITIVE_RESULTS.md) use freshly generated
260
316
  synthetic source projects and APKs. They measure development candidates
261
317
  recorded before APSA 1.2.0, not the published package; these results are not
262
- production accuracy estimates.
318
+ production accuracy estimates. A rerun on the APSA 1.3.0 release runtime with
319
+ newly generated inputs reproduced the candidate figures (see
320
+ [RELEASE_READINESS.md](https://github.com/ictechgy/apsa/blob/main/RELEASE_READINESS.md)).
263
321
 
264
322
  A separate [public-source and CVE evaluation](benchmarks/REAL_WORLD.md) records
265
323
  [initial results](benchmarks/REAL_WORLD_RESULTS.md) on six pinned app source
@@ -281,4 +339,12 @@ covers AAB/IPA metadata, Objective-C, parser isolation and two independently
281
339
  labeled public sources. It records selected CVE boundary agreement, unresolved
282
340
  catalog usage and remaining parser gaps separately.
283
341
 
342
+ The [dependency evidence evaluation](benchmarks/DEPENDENCY_RESULTS.md) compares
343
+ APSA's Gradle catalog usage and lockfile coordinates with Gradle's own
344
+ resolution on three frozen holdouts of public apps, keeping first blind results
345
+ separate from reruns after the truth was seen. The
346
+ [independent source pairs](benchmarks/FPFN_RESULTS.md) score vulnerable and
347
+ fixed commits of public projects against truth frozen before scanning. Both are
348
+ narrow samples, not general accuracy estimates.
349
+
284
350
  The source is publicly available on [GitHub](https://github.com/ictechgy/apsa). [LICENSE](https://github.com/ictechgy/apsa/blob/main/LICENSE) preserves the original Quaygate MIT notice. This publication does not declare an additional license for the combined product.
@@ -31,14 +31,61 @@ version catalog에만 선언된 의존성은 빌드 사용 근거나 해결 버
31
31
  `OBJC-CRYPTO-WEAK-HASH`, `OBJC-WEBVIEW-UNTRUSTED-REQUEST`)은 기존 1.1 기준선 대비
32
32
  새 발견 항목을 추가할 수 있습니다.
33
33
 
34
+ APSA 1.3은 Gradle version catalog alias를 실제로 사용하는 출하 의존성 구성과
35
+ 연결하고, application 모듈의 `gradle.lockfile` 좌표를 해결된 버전으로 읽습니다.
36
+ AAB feature 모듈 매니페스트를 해석하고, 서명을 인증하지 않은 채 Mach-O
37
+ CodeDirectory의 페이지·entitlement 해시를 다시 계산하며, 더 많은 Swift·Objective-C
38
+ 구문을 호환 처리합니다. 지정한 기간의 Android 보안 공지를 SoC 제조사·vendor 패치
39
+ 수준 정보와 함께 소급 수집할 수 있습니다.
40
+ [의존성 근거 결과](https://github.com/ictechgy/apsa/blob/main/benchmarks/DEPENDENCY_RESULTS.ko.md),
41
+ [독립 취약·수정 소스 쌍](https://github.com/ictechgy/apsa/blob/main/benchmarks/FPFN_RESULTS.ko.md),
42
+ [분석 범위와 한계](https://github.com/ictechgy/apsa/blob/main/docs/NEXT_ANALYSIS.md)를 참고하세요.
43
+
44
+ **1.2에서 업그레이드할 때.**
45
+
46
+ - 출하 구성에서 참조하는 catalog alias는 `declared` 후보가 되어 다시 CVE를 대조할 수
47
+ 있습니다. 참조되지 않거나 테스트·빌드 도구용인 alias는 미확인으로 남습니다.
48
+ application 모듈 lockfile 좌표는 정확한 버전이므로 대조 결과가 `version-affected`가
49
+ 되며, 기본 정책은 high·critical 항목에서 실패합니다. 다른 모듈의 lockfile 좌표는
50
+ `declared` 후보로 남습니다. 모든 출하 앱이 해결한 선언 후보는 대체(superseded)되어 CVE
51
+ 대조에서 빠집니다. 부분 입력에서는 모든 후보를 유지하며, 해석하지 못한 project 참조가
52
+ 있으면 application 자신의 선언만 대체될 수 있습니다.
53
+ - lockfile 전제: APSA는 dependency locking 활성화나 lockfile 최신 여부를 확인하지 않으며,
54
+ 모든 application 모듈(flavor, wear·TV·automotive 앱 포함)의 release runtime classpath를
55
+ 합칩니다. `--source-module`은 해당 모듈 폴더만 검사하므로 그 밖의 루트 version catalog와
56
+ library 모듈 선언은 읽지 않습니다.
57
+ - 기준선·예외: lockfile로 해결된 발견 항목은 위치(`gradle.lockfile`)와 상태가 바뀌므로
58
+ `only_new`는 새 항목으로 보고, 이전 발견 ID에 대한 예외는 더 이상 일치하지 않습니다.
59
+ 업그레이드 후 기준선을 다시 승인하세요.
60
+ - `--online`은 출하 구성에서 쓰는 catalog alias와 모든 모듈 lockfile의 release runtime
61
+ 좌표(전이 좌표·비공개 group ID 포함)를 OSV에 보내며 제외 목록은 없습니다. 한 번에 최대
62
+ 100개 패키지를 조회하며, 최근 하루 안의 OSV 결과가 없는 패키지를 먼저, 그중에서는 빌드
63
+ 파일 선언을 lockfile 좌표보다 먼저 조회합니다. 측정한 application lockfile은 출하 좌표가
64
+ 179~412개였으므로 한 번의 실행으로는 나머지가 `not-run`으로 남아, 필수 `DEPENDENCY-CVE`
65
+ 규칙은 통과할 수 없고 온라인 감사는 불완전하며 기본 `fail_on_partial` 정책은 종료 코드 3을
66
+ 반환합니다. 하루 안에 반복 실행하면 남은 패키지를 이어서 조회하며, 최근 하루 안의 OSV
67
+ 결과가 있는 패키지는 검사된 것으로 봅니다. 미확인 catalog alias와 OSV가 지원하지 않는
68
+ 생태계는 매 실행마다 온라인 오류로 보고되므로, 반복 실행해도 온라인 감사는 불완전하게
69
+ 남습니다.
70
+ - IPA 보고서에 `BINARY-IOS-CODE-INTEGRITY`가 추가됩니다. 해시가 일치해도 진위를 증명하지
71
+ 않습니다. 수정 후 다시 서명한 바이너리도 일치하기 때문입니다. 불일치는 발견 항목이 아닌
72
+ 경고를 추가하며, App Store 암호화·서명 없는 실행 파일은 `not-run`입니다.
73
+ - `intel sync`는 최근 Android 공지 범위만 갱신하므로 이전 달은 `intel backfill`을
74
+ 사용하세요. 1.2가 캐시한 공지는 컴포넌트 이름에서 vendor 범위를 도출하며, 칩셋·커널
75
+ 절이 아닌 항목은 플랫폼 패치 수준만 사용합니다. AAB feature 모듈의 설치 여부는 알 수
76
+ 없습니다.
77
+ - 호환 처리한 Swift·Objective-C 파일은 부분 분석으로 남고, 정규화한 전처리 조건부와
78
+ 겹치는 Objective-C 함수는 불확실로 분석에서 제외합니다. 수정하지 않은 1.2 스킬은
79
+ `apsa skill install`로 업그레이드됩니다.
80
+
34
81
  ## 검사 범위
35
82
 
36
83
  | 영역 | 제공하는 검사 |
37
84
  | --- | --- |
38
- | 소스 코드 | Java·Kotlin·Swift AST 분석, 제한된 Objective-C `.m` 후보, WebView·딥링크 패턴, Manifest·Info.plist·저장소·의존성 검사 |
39
- | Android 빌드 | DEX 호출·상수 흐름, AAB base 매니페스트·모듈 DEX(항상 부분 감사), 리소스·네트워크 설정, exported 컴포넌트·provider, 서명 블록·v1 인증서 근거, ELF 하드닝 |
40
- | iOS 빌드 | 내장 framework·확장 메타데이터를 포함한 Mach-O 헤더, 제한적인 entitlement·설정 검사(내장 XML entitlement, ATS 예외, provisioning 지표), PIE·카나리·문자열 근거 |
41
- | 공개 취약점 정보 | Apple·Android 공지, CVE, CISA KEV, OWASP 가이드, OSV 의존성 대조 |
85
+ | 소스 코드 | Java·Kotlin·Swift AST 분석, 제한된 Objective-C `.m` 후보, WebView·딥링크 패턴, Manifest·Info.plist·저장소·의존성 검사(Gradle catalog 사용 근거·application lockfile 포함) |
86
+ | Android 빌드 | DEX 호출·상수 흐름, AAB base·feature 모듈 매니페스트와 모듈 DEX(항상 부분 감사), 리소스·네트워크 설정, exported 컴포넌트·provider, 서명 블록·v1 인증서 근거, ELF 하드닝 |
87
+ | iOS 빌드 | 내장 framework·확장 메타데이터를 포함한 Mach-O 헤더, CodeDirectory 페이지·entitlement 해시 무결성(서명 인증 아님), 제한적인 entitlement·설정 검사(내장 XML entitlement, ATS 예외, provisioning 지표), PIE·카나리·문자열 근거 |
88
+ | 공개 취약점 정보 | Apple·Android 공지(지정 기간의 Android 공지 소급 수집 포함), CVE, CISA KEV, OWASP 가이드, OSV 의존성 대조 |
42
89
  | 보고서와 CI | SQLite 이력, 비교·재평가, JSON·Markdown·SARIF 내보내기, 필수 검사 범위, 만료일이 있는 예외 |
43
90
  | 런타임 | 소유한 Android 테스트 앱과 iOS 시뮬레이터 앱의 준비된 시나리오. 실제 iOS 기기는 미지원 |
44
91
  | 모델 연결 | stdio MCP 도구·리소스와 패키지 스킬. 특정 모델 제공자나 LLM API 키는 필수가 아님 |
@@ -54,7 +101,7 @@ OWASP 매핑은 관련 검사를 설명합니다. APSA는 MASVS 준수를 인증
54
101
  [PyPI](https://pypi.org/project/apsa/)에서 배포 패키지를 설치합니다.
55
102
 
56
103
  ```sh
57
- uv tool install --python 3.12 apsa==1.2.0
104
+ uv tool install --python 3.12 apsa==1.3.0
58
105
  apsa --version
59
106
  apsa doctor --json
60
107
  apsa demo --out ./apsa-demo
@@ -101,8 +148,9 @@ apsa tui
101
148
  | `apsa scan TARGET` | 로컬 입력과 캐시 사용 |
102
149
  | `apsa intel sync` | 공개 취약점 정보 수집 |
103
150
  | `apsa intel watch` | 공개 피드를 폴링하고 저장된 인벤토리를 재평가. 앱 파일을 다시 읽거나 OSV를 자동 조회하지 않음 |
104
- | `apsa scan TARGET --online` | 발견한 의존성 이름·버전을 OSV에 전송 |
105
- | `apsa intel watch --online` | 저장된 의존성 이름·버전도 OSV에 전송 |
151
+ | `apsa intel backfill --source android --since YYYY-MM` | 지정한 제한된 기간의 월별 Android 보안 공지를 수집 |
152
+ | `apsa scan TARGET --online` | 발견한 의존성 이름·버전을 OSV에 전송. 출하 구성에서 쓰는 Gradle catalog alias와 모든 모듈 lockfile의 release runtime 좌표를 포함하며 한 번에 최대 100개 패키지, 미검사 빌드 파일 선언 우선 |
153
+ | `apsa intel watch --online` | 저장된 의존성 이름·버전도 같은 한도로 OSV에 전송 |
106
154
 
107
155
  ```sh
108
156
  apsa intel sync
@@ -220,6 +268,8 @@ make release RELEASE_OUT=dist/apsa-local-release
220
268
  새로 생성한 합성 소스 프로젝트와 APK를 사용하는 [APSA/MobSF 비교](benchmarks/COMPETITIVE.md)(영문)와
221
269
  [측정 결과](benchmarks/COMPETITIVE_RESULTS.ko.md)를 제공합니다. APSA 1.2.0 배포 전의
222
270
  개발 후보를 측정한 결과이며 배포 패키지의 측정이나 운영 앱의 정확도를 나타내지 않습니다.
271
+ APSA 1.3.0 릴리스 런타임에서 새로 생성한 입력으로 다시 실행해 후보 수치를 재현했습니다
272
+ ([RELEASE_READINESS.md](https://github.com/ictechgy/apsa/blob/main/RELEASE_READINESS.md)).
223
273
 
224
274
  별도의 [공개 소스·CVE 평가](benchmarks/REAL_WORLD.ko.md)와
225
275
  [최초 결과](benchmarks/REAL_WORLD_RESULTS.ko.md)는 커밋을 고정한 앱 소스 6개,
@@ -240,4 +290,10 @@ make release RELEASE_OUT=dist/apsa-local-release
240
290
  Objective-C, 파서 격리와 독립 라벨의 새 공개 소스 2개를 다룹니다.
241
291
  선택한 CVE 경계 일치, catalog 사용 미확인과 남은 구문 누락을 별도로 기록합니다.
242
292
 
293
+ [의존성 근거 평가](benchmarks/DEPENDENCY_RESULTS.ko.md)는 APSA의 Gradle catalog 사용 근거와
294
+ lockfile 좌표를 공개 앱 holdout 3개에서 Gradle 자체 해석과 비교하며, 최초 블라인드 결과와
295
+ 정답을 본 뒤의 재실행을 구분합니다. [독립 취약·수정 소스 쌍](benchmarks/FPFN_RESULTS.ko.md)은
296
+ 공개 프로젝트의 취약·수정 커밋을 스캔 전에 고정한 정답으로 채점합니다. 둘 다 좁은 표본이며
297
+ 일반적인 정확도 추정이 아닙니다.
298
+
243
299
  소스는 [GitHub](https://github.com/ictechgy/apsa)에 공개되어 있습니다. [LICENSE](https://github.com/ictechgy/apsa/blob/main/LICENSE)는 원래 Quaygate의 MIT 고지를 보존합니다. 이번 공개는 통합 제품에 추가 라이선스를 선언하지 않습니다.