deepadb 1.0.0

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 (247) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +631 -0
  3. package/build/bridge/adb-bridge.d.ts +65 -0
  4. package/build/bridge/adb-bridge.d.ts.map +1 -0
  5. package/build/bridge/adb-bridge.js +164 -0
  6. package/build/bridge/adb-bridge.js.map +1 -0
  7. package/build/bridge/device-manager.d.ts +41 -0
  8. package/build/bridge/device-manager.d.ts.map +1 -0
  9. package/build/bridge/device-manager.js +109 -0
  10. package/build/bridge/device-manager.js.map +1 -0
  11. package/build/bridge/local-bridge.d.ts +92 -0
  12. package/build/bridge/local-bridge.d.ts.map +1 -0
  13. package/build/bridge/local-bridge.js +345 -0
  14. package/build/bridge/local-bridge.js.map +1 -0
  15. package/build/config/config.d.ts +39 -0
  16. package/build/config/config.d.ts.map +1 -0
  17. package/build/config/config.js +84 -0
  18. package/build/config/config.js.map +1 -0
  19. package/build/graphql-api.d.ts +36 -0
  20. package/build/graphql-api.d.ts.map +1 -0
  21. package/build/graphql-api.js +296 -0
  22. package/build/graphql-api.js.map +1 -0
  23. package/build/http-transport.d.ts +26 -0
  24. package/build/http-transport.d.ts.map +1 -0
  25. package/build/http-transport.js +105 -0
  26. package/build/http-transport.js.map +1 -0
  27. package/build/index.d.ts +14 -0
  28. package/build/index.d.ts.map +1 -0
  29. package/build/index.js +66 -0
  30. package/build/index.js.map +1 -0
  31. package/build/middleware/chipset.d.ts +29 -0
  32. package/build/middleware/chipset.d.ts.map +1 -0
  33. package/build/middleware/chipset.js +123 -0
  34. package/build/middleware/chipset.js.map +1 -0
  35. package/build/middleware/cleanup.d.ts +24 -0
  36. package/build/middleware/cleanup.d.ts.map +1 -0
  37. package/build/middleware/cleanup.js +53 -0
  38. package/build/middleware/cleanup.js.map +1 -0
  39. package/build/middleware/fetch-utils.d.ts +19 -0
  40. package/build/middleware/fetch-utils.d.ts.map +1 -0
  41. package/build/middleware/fetch-utils.js +64 -0
  42. package/build/middleware/fetch-utils.js.map +1 -0
  43. package/build/middleware/logger.d.ts +17 -0
  44. package/build/middleware/logger.d.ts.map +1 -0
  45. package/build/middleware/logger.js +38 -0
  46. package/build/middleware/logger.js.map +1 -0
  47. package/build/middleware/output-processor.d.ts +57 -0
  48. package/build/middleware/output-processor.d.ts.map +1 -0
  49. package/build/middleware/output-processor.js +162 -0
  50. package/build/middleware/output-processor.js.map +1 -0
  51. package/build/middleware/sanitize.d.ts +30 -0
  52. package/build/middleware/sanitize.d.ts.map +1 -0
  53. package/build/middleware/sanitize.js +46 -0
  54. package/build/middleware/sanitize.js.map +1 -0
  55. package/build/middleware/security.d.ts +52 -0
  56. package/build/middleware/security.d.ts.map +1 -0
  57. package/build/middleware/security.js +123 -0
  58. package/build/middleware/security.js.map +1 -0
  59. package/build/middleware/ui-dump.d.ts +23 -0
  60. package/build/middleware/ui-dump.d.ts.map +1 -0
  61. package/build/middleware/ui-dump.js +59 -0
  62. package/build/middleware/ui-dump.js.map +1 -0
  63. package/build/server.d.ts +18 -0
  64. package/build/server.d.ts.map +1 -0
  65. package/build/server.js +133 -0
  66. package/build/server.js.map +1 -0
  67. package/build/tool-context.d.ts +22 -0
  68. package/build/tool-context.d.ts.map +1 -0
  69. package/build/tool-context.js +9 -0
  70. package/build/tool-context.js.map +1 -0
  71. package/build/tools/accessibility.d.ts +10 -0
  72. package/build/tools/accessibility.d.ts.map +1 -0
  73. package/build/tools/accessibility.js +259 -0
  74. package/build/tools/accessibility.js.map +1 -0
  75. package/build/tools/at-commands.d.ts +20 -0
  76. package/build/tools/at-commands.d.ts.map +1 -0
  77. package/build/tools/at-commands.js +378 -0
  78. package/build/tools/at-commands.js.map +1 -0
  79. package/build/tools/baseband.d.ts +15 -0
  80. package/build/tools/baseband.d.ts.map +1 -0
  81. package/build/tools/baseband.js +323 -0
  82. package/build/tools/baseband.js.map +1 -0
  83. package/build/tools/build.d.ts +6 -0
  84. package/build/tools/build.d.ts.map +1 -0
  85. package/build/tools/build.js +80 -0
  86. package/build/tools/build.js.map +1 -0
  87. package/build/tools/ci.d.ts +9 -0
  88. package/build/tools/ci.d.ts.map +1 -0
  89. package/build/tools/ci.js +163 -0
  90. package/build/tools/ci.js.map +1 -0
  91. package/build/tools/control.d.ts +10 -0
  92. package/build/tools/control.d.ts.map +1 -0
  93. package/build/tools/control.js +197 -0
  94. package/build/tools/control.js.map +1 -0
  95. package/build/tools/device-farm.d.ts +10 -0
  96. package/build/tools/device-farm.d.ts.map +1 -0
  97. package/build/tools/device-farm.js +140 -0
  98. package/build/tools/device-farm.js.map +1 -0
  99. package/build/tools/device-profiles.d.ts +16 -0
  100. package/build/tools/device-profiles.d.ts.map +1 -0
  101. package/build/tools/device-profiles.js +272 -0
  102. package/build/tools/device-profiles.js.map +1 -0
  103. package/build/tools/device.d.ts +6 -0
  104. package/build/tools/device.d.ts.map +1 -0
  105. package/build/tools/device.js +72 -0
  106. package/build/tools/device.js.map +1 -0
  107. package/build/tools/diagnostics.d.ts +7 -0
  108. package/build/tools/diagnostics.d.ts.map +1 -0
  109. package/build/tools/diagnostics.js +153 -0
  110. package/build/tools/diagnostics.js.map +1 -0
  111. package/build/tools/emulator.d.ts +9 -0
  112. package/build/tools/emulator.d.ts.map +1 -0
  113. package/build/tools/emulator.js +223 -0
  114. package/build/tools/emulator.js.map +1 -0
  115. package/build/tools/files.d.ts +6 -0
  116. package/build/tools/files.d.ts.map +1 -0
  117. package/build/tools/files.js +78 -0
  118. package/build/tools/files.js.map +1 -0
  119. package/build/tools/firmware-analysis.d.ts +24 -0
  120. package/build/tools/firmware-analysis.d.ts.map +1 -0
  121. package/build/tools/firmware-analysis.js +623 -0
  122. package/build/tools/firmware-analysis.js.map +1 -0
  123. package/build/tools/forwarding.d.ts +7 -0
  124. package/build/tools/forwarding.d.ts.map +1 -0
  125. package/build/tools/forwarding.js +64 -0
  126. package/build/tools/forwarding.js.map +1 -0
  127. package/build/tools/health.d.ts +7 -0
  128. package/build/tools/health.d.ts.map +1 -0
  129. package/build/tools/health.js +112 -0
  130. package/build/tools/health.js.map +1 -0
  131. package/build/tools/logcat-watch.d.ts +11 -0
  132. package/build/tools/logcat-watch.d.ts.map +1 -0
  133. package/build/tools/logcat-watch.js +209 -0
  134. package/build/tools/logcat-watch.js.map +1 -0
  135. package/build/tools/logs.d.ts +6 -0
  136. package/build/tools/logs.d.ts.map +1 -0
  137. package/build/tools/logs.js +83 -0
  138. package/build/tools/logs.js.map +1 -0
  139. package/build/tools/mirroring.d.ts +14 -0
  140. package/build/tools/mirroring.d.ts.map +1 -0
  141. package/build/tools/mirroring.js +243 -0
  142. package/build/tools/mirroring.js.map +1 -0
  143. package/build/tools/multi-device.d.ts +9 -0
  144. package/build/tools/multi-device.d.ts.map +1 -0
  145. package/build/tools/multi-device.js +138 -0
  146. package/build/tools/multi-device.js.map +1 -0
  147. package/build/tools/network-capture.d.ts +10 -0
  148. package/build/tools/network-capture.d.ts.map +1 -0
  149. package/build/tools/network-capture.js +143 -0
  150. package/build/tools/network-capture.js.map +1 -0
  151. package/build/tools/network-discovery.d.ts +21 -0
  152. package/build/tools/network-discovery.d.ts.map +1 -0
  153. package/build/tools/network-discovery.js +284 -0
  154. package/build/tools/network-discovery.js.map +1 -0
  155. package/build/tools/ota-monitor.d.ts +16 -0
  156. package/build/tools/ota-monitor.d.ts.map +1 -0
  157. package/build/tools/ota-monitor.js +211 -0
  158. package/build/tools/ota-monitor.js.map +1 -0
  159. package/build/tools/packages.d.ts +6 -0
  160. package/build/tools/packages.d.ts.map +1 -0
  161. package/build/tools/packages.js +237 -0
  162. package/build/tools/packages.js.map +1 -0
  163. package/build/tools/plugins.d.ts +22 -0
  164. package/build/tools/plugins.d.ts.map +1 -0
  165. package/build/tools/plugins.js +118 -0
  166. package/build/tools/plugins.js.map +1 -0
  167. package/build/tools/prompts.d.ts +9 -0
  168. package/build/tools/prompts.d.ts.map +1 -0
  169. package/build/tools/prompts.js +94 -0
  170. package/build/tools/prompts.js.map +1 -0
  171. package/build/tools/qemu.d.ts +18 -0
  172. package/build/tools/qemu.d.ts.map +1 -0
  173. package/build/tools/qemu.js +791 -0
  174. package/build/tools/qemu.js.map +1 -0
  175. package/build/tools/registry.d.ts +13 -0
  176. package/build/tools/registry.d.ts.map +1 -0
  177. package/build/tools/registry.js +221 -0
  178. package/build/tools/registry.js.map +1 -0
  179. package/build/tools/regression.d.ts +10 -0
  180. package/build/tools/regression.d.ts.map +1 -0
  181. package/build/tools/regression.js +215 -0
  182. package/build/tools/regression.js.map +1 -0
  183. package/build/tools/resources.d.ts +10 -0
  184. package/build/tools/resources.d.ts.map +1 -0
  185. package/build/tools/resources.js +77 -0
  186. package/build/tools/resources.js.map +1 -0
  187. package/build/tools/ril-intercept.d.ts +24 -0
  188. package/build/tools/ril-intercept.d.ts.map +1 -0
  189. package/build/tools/ril-intercept.js +273 -0
  190. package/build/tools/ril-intercept.js.map +1 -0
  191. package/build/tools/screen-record.d.ts +9 -0
  192. package/build/tools/screen-record.d.ts.map +1 -0
  193. package/build/tools/screen-record.js +95 -0
  194. package/build/tools/screen-record.js.map +1 -0
  195. package/build/tools/screenshot-diff.d.ts +13 -0
  196. package/build/tools/screenshot-diff.d.ts.map +1 -0
  197. package/build/tools/screenshot-diff.js +370 -0
  198. package/build/tools/screenshot-diff.js.map +1 -0
  199. package/build/tools/selinux-audit.d.ts +17 -0
  200. package/build/tools/selinux-audit.d.ts.map +1 -0
  201. package/build/tools/selinux-audit.js +301 -0
  202. package/build/tools/selinux-audit.js.map +1 -0
  203. package/build/tools/shell.d.ts +6 -0
  204. package/build/tools/shell.d.ts.map +1 -0
  205. package/build/tools/shell.js +63 -0
  206. package/build/tools/shell.js.map +1 -0
  207. package/build/tools/snapshot.d.ts +9 -0
  208. package/build/tools/snapshot.d.ts.map +1 -0
  209. package/build/tools/snapshot.js +192 -0
  210. package/build/tools/snapshot.js.map +1 -0
  211. package/build/tools/split-apk.d.ts +13 -0
  212. package/build/tools/split-apk.d.ts.map +1 -0
  213. package/build/tools/split-apk.js +229 -0
  214. package/build/tools/split-apk.js.map +1 -0
  215. package/build/tools/test-gen.d.ts +14 -0
  216. package/build/tools/test-gen.d.ts.map +1 -0
  217. package/build/tools/test-gen.js +252 -0
  218. package/build/tools/test-gen.js.map +1 -0
  219. package/build/tools/testing.d.ts +9 -0
  220. package/build/tools/testing.d.ts.map +1 -0
  221. package/build/tools/testing.js +144 -0
  222. package/build/tools/testing.js.map +1 -0
  223. package/build/tools/thermal-power.d.ts +19 -0
  224. package/build/tools/thermal-power.d.ts.map +1 -0
  225. package/build/tools/thermal-power.js +330 -0
  226. package/build/tools/thermal-power.js.map +1 -0
  227. package/build/tools/ui.d.ts +6 -0
  228. package/build/tools/ui.d.ts.map +1 -0
  229. package/build/tools/ui.js +266 -0
  230. package/build/tools/ui.js.map +1 -0
  231. package/build/tools/wireless.d.ts +7 -0
  232. package/build/tools/wireless.d.ts.map +1 -0
  233. package/build/tools/wireless.js +78 -0
  234. package/build/tools/wireless.js.map +1 -0
  235. package/build/tools/workflow-market.d.ts +17 -0
  236. package/build/tools/workflow-market.d.ts.map +1 -0
  237. package/build/tools/workflow-market.js +237 -0
  238. package/build/tools/workflow-market.js.map +1 -0
  239. package/build/tools/workflow.d.ts +32 -0
  240. package/build/tools/workflow.d.ts.map +1 -0
  241. package/build/tools/workflow.js +374 -0
  242. package/build/tools/workflow.js.map +1 -0
  243. package/build/ws-transport.d.ts +30 -0
  244. package/build/ws-transport.d.ts.map +1 -0
  245. package/build/ws-transport.js +133 -0
  246. package/build/ws-transport.js.map +1 -0
  247. package/package.json +37 -0
@@ -0,0 +1,301 @@
1
+ /**
2
+ * SELinux & Permission Auditing — OS-level security inspection.
3
+ *
4
+ * Inspects SELinux enforcement mode, queries policy denials from
5
+ * kernel audit logs, and audits runtime permission grants against
6
+ * actual usage to detect over-provisioning.
7
+ *
8
+ * Extends the existing accessibility and security auditing capabilities
9
+ * to the Android OS permission layer. Useful for security hardening,
10
+ * compliance checks, and understanding app permission behavior.
11
+ *
12
+ * Root access recommended for full audit log access; basic SELinux
13
+ * mode and permission grant queries work without root.
14
+ */
15
+ import { z } from "zod";
16
+ import { OutputProcessor } from "../middleware/output-processor.js";
17
+ import { validateShellArg } from "../middleware/sanitize.js";
18
+ function parsePermissions(dumpsysOutput) {
19
+ const grants = [];
20
+ const lines = dumpsysOutput.split("\n");
21
+ for (const line of lines) {
22
+ // Format: "android.permission.CAMERA: granted=true, flags=[ USER_SET ]"
23
+ // or "android.permission.CAMERA granted=true"
24
+ const match = line.match(/(android\.permission\.\S+)[:\s]+granted=(\w+)(?:.*flags=\[([^\]]*)\])?/);
25
+ if (match) {
26
+ grants.push({
27
+ permission: match[1],
28
+ granted: match[2] === "true",
29
+ flags: match[3]?.trim() ?? "",
30
+ });
31
+ }
32
+ }
33
+ return grants;
34
+ }
35
+ /** Well-known dangerous permissions grouped by category. */
36
+ const DANGEROUS_PERMISSION_GROUPS = {
37
+ "Camera": ["android.permission.CAMERA"],
38
+ "Microphone": ["android.permission.RECORD_AUDIO"],
39
+ "Location": [
40
+ "android.permission.ACCESS_FINE_LOCATION",
41
+ "android.permission.ACCESS_COARSE_LOCATION",
42
+ "android.permission.ACCESS_BACKGROUND_LOCATION",
43
+ ],
44
+ "Storage": [
45
+ "android.permission.READ_EXTERNAL_STORAGE",
46
+ "android.permission.WRITE_EXTERNAL_STORAGE",
47
+ "android.permission.READ_MEDIA_IMAGES",
48
+ "android.permission.READ_MEDIA_VIDEO",
49
+ "android.permission.READ_MEDIA_AUDIO",
50
+ "android.permission.MANAGE_EXTERNAL_STORAGE",
51
+ ],
52
+ "Contacts": [
53
+ "android.permission.READ_CONTACTS",
54
+ "android.permission.WRITE_CONTACTS",
55
+ "android.permission.GET_ACCOUNTS",
56
+ ],
57
+ "Phone": [
58
+ "android.permission.READ_PHONE_STATE",
59
+ "android.permission.READ_PHONE_NUMBERS",
60
+ "android.permission.CALL_PHONE",
61
+ "android.permission.READ_CALL_LOG",
62
+ "android.permission.WRITE_CALL_LOG",
63
+ ],
64
+ "SMS": [
65
+ "android.permission.SEND_SMS",
66
+ "android.permission.RECEIVE_SMS",
67
+ "android.permission.READ_SMS",
68
+ ],
69
+ "Calendar": [
70
+ "android.permission.READ_CALENDAR",
71
+ "android.permission.WRITE_CALENDAR",
72
+ ],
73
+ "Body Sensors": [
74
+ "android.permission.BODY_SENSORS",
75
+ "android.permission.BODY_SENSORS_BACKGROUND",
76
+ ],
77
+ "Nearby Devices": [
78
+ "android.permission.BLUETOOTH_CONNECT",
79
+ "android.permission.BLUETOOTH_SCAN",
80
+ "android.permission.BLUETOOTH_ADVERTISE",
81
+ "android.permission.NEARBY_WIFI_DEVICES",
82
+ "android.permission.UWB_RANGING",
83
+ ],
84
+ "Notifications": ["android.permission.POST_NOTIFICATIONS"],
85
+ };
86
+ export function registerSelinuxAuditTools(ctx) {
87
+ ctx.server.tool("adb_selinux_status", "Check SELinux enforcement mode, policy version, and recent denial count. Shows whether the device is in Enforcing, Permissive, or Disabled mode. Root access provides additional policy details from dmesg audit logs.", {
88
+ device: z.string().optional().describe("Device serial"),
89
+ }, async ({ device }) => {
90
+ try {
91
+ const resolved = await ctx.deviceManager.resolveDevice(device);
92
+ const serial = resolved.serial;
93
+ const sections = [];
94
+ sections.push("=== SELinux Status ===");
95
+ // Get SELinux mode via getenforce
96
+ const enforceResult = await ctx.bridge.shell("getenforce", {
97
+ device: serial, ignoreExitCode: true,
98
+ });
99
+ const mode = enforceResult.stdout.trim() || "unknown";
100
+ sections.push(`Mode: ${mode}`);
101
+ // Get SELinux context of the shell
102
+ const contextResult = await ctx.bridge.shell("id -Z 2>/dev/null || echo 'unavailable'", {
103
+ device: serial, ignoreExitCode: true,
104
+ });
105
+ const context = contextResult.stdout.trim();
106
+ if (context && context !== "unavailable") {
107
+ sections.push(`Shell context: ${context}`);
108
+ }
109
+ // SELinux-related properties
110
+ const props = await ctx.deviceManager.getDeviceProps(serial);
111
+ const selinuxProps = [
112
+ "ro.build.selinux",
113
+ "ro.boot.selinux",
114
+ "selinux.reload_policy",
115
+ ];
116
+ for (const prop of selinuxProps) {
117
+ const val = props[prop];
118
+ if (val)
119
+ sections.push(`${prop}: ${val}`);
120
+ }
121
+ // Try to get policy version and stats
122
+ const policyResult = await ctx.bridge.shell("cat /sys/fs/selinux/policyvers 2>/dev/null && echo '---' && cat /sys/fs/selinux/status 2>/dev/null", { device: serial, ignoreExitCode: true });
123
+ if (policyResult.stdout.includes("---")) {
124
+ const parts = policyResult.stdout.split("---");
125
+ const policyVer = parts[0].trim();
126
+ if (policyVer)
127
+ sections.push(`Policy version: ${policyVer}`);
128
+ }
129
+ // Count recent denials from logcat (doesn't require root)
130
+ const denialResult = await ctx.bridge.shell("logcat -d -b events -t 500 | grep -c 'avc.*denied' 2>/dev/null || echo 0", { device: serial, ignoreExitCode: true });
131
+ const denialCount = parseInt(denialResult.stdout.trim(), 10) || 0;
132
+ sections.push(`\nRecent AVC denials (last 500 events): ${denialCount}`);
133
+ // Try root access for dmesg denials
134
+ let hasRoot = false;
135
+ try {
136
+ const rootResult = await ctx.bridge.shell("su -c 'dmesg | grep -c avc 2>/dev/null || echo 0'", {
137
+ device: serial, timeout: 5000, ignoreExitCode: true,
138
+ });
139
+ if (rootResult.stdout.trim() && !rootResult.stdout.includes("Permission denied")) {
140
+ hasRoot = true;
141
+ const dmesgDenials = parseInt(rootResult.stdout.trim(), 10) || 0;
142
+ sections.push(`Kernel AVC denials (dmesg): ${dmesgDenials}`);
143
+ }
144
+ }
145
+ catch { /* no root */ }
146
+ if (!hasRoot) {
147
+ sections.push("\nNote: Root access provides additional kernel audit log details.");
148
+ }
149
+ return { content: [{ type: "text", text: sections.join("\n") }] };
150
+ }
151
+ catch (error) {
152
+ return { content: [{ type: "text", text: OutputProcessor.formatError(error) }], isError: true };
153
+ }
154
+ });
155
+ ctx.server.tool("adb_selinux_denials", "List recent SELinux AVC denial messages from logcat and kernel logs. Shows which processes were blocked, what they tried to do, and the SELinux contexts involved. Useful for diagnosing permission issues and understanding security policy enforcement.", {
156
+ lines: z.number().min(1).max(1000).optional().default(50).describe("Max denial entries to return (1-1000, default 50)"),
157
+ process: z.string().optional().describe("Filter denials by process/source context name"),
158
+ device: z.string().optional().describe("Device serial"),
159
+ }, async ({ lines, process: processFilter, device }) => {
160
+ try {
161
+ const resolved = await ctx.deviceManager.resolveDevice(device);
162
+ const serial = resolved.serial;
163
+ if (processFilter) {
164
+ const filterErr = validateShellArg(processFilter, "process");
165
+ if (filterErr)
166
+ return { content: [{ type: "text", text: filterErr }], isError: true };
167
+ }
168
+ const maxLines = Math.min(lines, 500);
169
+ const sections = [];
170
+ sections.push("=== SELinux AVC Denials ===\n");
171
+ // Logcat denials
172
+ const grepFilter = processFilter ? ` | grep -iF '${processFilter}'` : "";
173
+ const logcatResult = await ctx.bridge.shell(`logcat -d -b events,main -t 2000 | grep 'avc.*denied'${grepFilter} | tail -${maxLines}`, { device: serial, timeout: 15000, ignoreExitCode: true });
174
+ const logcatDenials = logcatResult.stdout.trim().split("\n").filter((l) => l.trim().length > 0);
175
+ if (logcatDenials.length > 0) {
176
+ sections.push(`Logcat denials (${logcatDenials.length}):\n`);
177
+ for (const denial of logcatDenials) {
178
+ // Parse the AVC denial for readable output
179
+ const scontextMatch = denial.match(/scontext=(\S+)/);
180
+ const tcontextMatch = denial.match(/tcontext=(\S+)/);
181
+ const tclassMatch = denial.match(/tclass=(\S+)/);
182
+ const permMatch = denial.match(/\{\s*([^}]+)\s*\}/);
183
+ if (scontextMatch && tcontextMatch) {
184
+ const source = scontextMatch[1];
185
+ const target = tcontextMatch[1];
186
+ const tclass = tclassMatch ? tclassMatch[1] : "?";
187
+ const perms = permMatch ? permMatch[1].trim() : "?";
188
+ sections.push(` ${perms} [${tclass}] ${source} → ${target}`);
189
+ }
190
+ else {
191
+ // Raw line if parsing fails
192
+ sections.push(` ${denial.substring(0, 200)}`);
193
+ }
194
+ }
195
+ }
196
+ else {
197
+ sections.push("No AVC denials found in logcat.");
198
+ }
199
+ // Try dmesg for kernel-level denials (root)
200
+ try {
201
+ const dmesgGrepFilter = processFilter ? ` | grep -iF "${processFilter}"` : "";
202
+ const dmesgResult = await ctx.bridge.shell(`su -c 'dmesg | grep "avc.*denied"${dmesgGrepFilter} | tail -20'`, { device: serial, timeout: 10000, ignoreExitCode: true });
203
+ const dmesgDenials = dmesgResult.stdout.trim().split("\n").filter((l) => l.includes("avc"));
204
+ if (dmesgDenials.length > 0) {
205
+ sections.push(`\nKernel denials (${dmesgDenials.length}):\n`);
206
+ for (const d of dmesgDenials.slice(0, 20)) {
207
+ sections.push(` ${d.substring(0, 200)}`);
208
+ }
209
+ }
210
+ }
211
+ catch { /* no root — skip silently */ }
212
+ return { content: [{ type: "text", text: OutputProcessor.process(sections.join("\n")) }] };
213
+ }
214
+ catch (error) {
215
+ return { content: [{ type: "text", text: OutputProcessor.formatError(error) }], isError: true };
216
+ }
217
+ });
218
+ ctx.server.tool("adb_permission_audit", "Audit runtime permission grants for a package. Lists all granted dangerous permissions grouped by category (Camera, Location, Phone, SMS, etc.) and flags potentially over-provisioned permissions. Compares grants against the dangerous permission manifest to identify unnecessary access.", {
219
+ packageName: z.string().describe("Package name to audit (e.g., 'com.example.app')"),
220
+ device: z.string().optional().describe("Device serial"),
221
+ }, async ({ packageName, device }) => {
222
+ try {
223
+ const pkgErr = validateShellArg(packageName, "packageName");
224
+ if (pkgErr)
225
+ return { content: [{ type: "text", text: pkgErr }], isError: true };
226
+ const resolved = await ctx.deviceManager.resolveDevice(device);
227
+ const serial = resolved.serial;
228
+ // Get permission state from dumpsys
229
+ const dumpResult = await ctx.bridge.shell(`dumpsys package ${packageName} | grep -A 200 'runtime permissions'`, { device: serial, timeout: 15000, ignoreExitCode: true });
230
+ if (!dumpResult.stdout || dumpResult.stdout.trim().length === 0) {
231
+ return { content: [{ type: "text", text: `Package "${packageName}" not found or has no runtime permissions section.` }], isError: true };
232
+ }
233
+ const grants = parsePermissions(dumpResult.stdout);
234
+ // Also get requested permissions from the manifest
235
+ const requestedResult = await ctx.bridge.shell(`dumpsys package ${packageName} | grep -A 500 'requested permissions:' | grep 'android.permission' | head -100`, { device: serial, timeout: 10000, ignoreExitCode: true });
236
+ const requestedPerms = requestedResult.stdout.split("\n")
237
+ .map((l) => l.trim())
238
+ .filter((l) => l.startsWith("android.permission."));
239
+ const sections = [];
240
+ sections.push(`=== Permission Audit: ${packageName} ===\n`);
241
+ const granted = grants.filter((g) => g.granted);
242
+ const denied = grants.filter((g) => !g.granted);
243
+ sections.push(`Runtime permissions: ${grants.length} total, ${granted.length} granted, ${denied.length} denied`);
244
+ if (requestedPerms.length > 0) {
245
+ sections.push(`Manifest-requested permissions: ${requestedPerms.length}`);
246
+ }
247
+ // Group granted permissions by category
248
+ sections.push(`\n--- Granted Dangerous Permissions ---`);
249
+ let dangerousGrantedCount = 0;
250
+ for (const [category, perms] of Object.entries(DANGEROUS_PERMISSION_GROUPS)) {
251
+ const grantedInCategory = granted.filter((g) => perms.includes(g.permission));
252
+ if (grantedInCategory.length > 0) {
253
+ dangerousGrantedCount += grantedInCategory.length;
254
+ sections.push(`\n[${category}]`);
255
+ for (const g of grantedInCategory) {
256
+ const flags = g.flags ? ` (${g.flags})` : "";
257
+ sections.push(` ✓ ${g.permission}${flags}`);
258
+ }
259
+ }
260
+ }
261
+ // Show non-categorized grants
262
+ const allDangerousPerms = Object.values(DANGEROUS_PERMISSION_GROUPS).flat();
263
+ const uncategorizedGrants = granted.filter((g) => !allDangerousPerms.includes(g.permission));
264
+ if (uncategorizedGrants.length > 0) {
265
+ sections.push(`\n[Other Granted]`);
266
+ for (const g of uncategorizedGrants) {
267
+ sections.push(` ✓ ${g.permission}`);
268
+ }
269
+ }
270
+ if (dangerousGrantedCount === 0 && uncategorizedGrants.length === 0) {
271
+ sections.push(" (none)");
272
+ }
273
+ // Denied permissions
274
+ if (denied.length > 0) {
275
+ sections.push(`\n--- Denied Permissions (${denied.length}) ---`);
276
+ for (const d of denied) {
277
+ sections.push(` ✗ ${d.permission}`);
278
+ }
279
+ }
280
+ // Over-provisioning analysis
281
+ sections.push(`\n--- Analysis ---`);
282
+ sections.push(`Dangerous permissions granted: ${dangerousGrantedCount}`);
283
+ const highRisk = granted.filter((g) => g.permission.includes("BACKGROUND_LOCATION") ||
284
+ g.permission.includes("MANAGE_EXTERNAL_STORAGE") ||
285
+ g.permission.includes("BODY_SENSORS_BACKGROUND") ||
286
+ g.permission.includes("READ_CALL_LOG") ||
287
+ g.permission.includes("READ_SMS"));
288
+ if (highRisk.length > 0) {
289
+ sections.push(`\nHigh-sensitivity permissions granted:`);
290
+ for (const hr of highRisk) {
291
+ sections.push(` ⚠ ${hr.permission}`);
292
+ }
293
+ }
294
+ return { content: [{ type: "text", text: sections.join("\n") }] };
295
+ }
296
+ catch (error) {
297
+ return { content: [{ type: "text", text: OutputProcessor.formatError(error) }], isError: true };
298
+ }
299
+ });
300
+ }
301
+ //# sourceMappingURL=selinux-audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selinux-audit.js","sourceRoot":"","sources":["../../src/tools/selinux-audit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Shell Tools — Execute arbitrary shell commands on the device.
3
+ */
4
+ import { ToolContext } from "../tool-context.js";
5
+ export declare function registerShellTools(ctx: ToolContext): void;
6
+ //# sourceMappingURL=shell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../src/tools/shell.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAkEzD"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Shell Tools — Execute arbitrary shell commands on the device.
3
+ */
4
+ import { z } from "zod";
5
+ import { OutputProcessor } from "../middleware/output-processor.js";
6
+ export function registerShellTools(ctx) {
7
+ ctx.server.tool("adb_shell", "Execute a shell command on the Android device. Returns stdout and stderr.", {
8
+ command: z.string().describe("Shell command to execute on the device"),
9
+ device: z.string().optional().describe("Device serial"),
10
+ timeout: z.number().min(1000).max(600000).optional().describe("Timeout in milliseconds (1s-10min)"),
11
+ }, async ({ command, device, timeout }) => {
12
+ try {
13
+ // Security check
14
+ const blocked = ctx.security.checkCommand(command, device);
15
+ if (blocked) {
16
+ return { content: [{ type: "text", text: blocked }], isError: true };
17
+ }
18
+ const resolved = await ctx.deviceManager.resolveDevice(device);
19
+ const result = await ctx.bridge.shell(command, {
20
+ device: resolved.serial,
21
+ timeout,
22
+ ignoreExitCode: true,
23
+ });
24
+ let output = result.stdout;
25
+ if (result.stderr) {
26
+ output += `\n--- STDERR ---\n${result.stderr}`;
27
+ }
28
+ if (result.exitCode !== 0) {
29
+ output += `\n--- Exit code: ${result.exitCode} ---`;
30
+ }
31
+ return { content: [{ type: "text", text: OutputProcessor.process(output) }] };
32
+ }
33
+ catch (error) {
34
+ return { content: [{ type: "text", text: OutputProcessor.formatError(error) }], isError: true };
35
+ }
36
+ });
37
+ ctx.server.tool("adb_root_shell", "Execute a command as root via su. Requires rooted device.", {
38
+ command: z.string().describe("Command to run as root"),
39
+ device: z.string().optional().describe("Device serial"),
40
+ }, async ({ command, device }) => {
41
+ try {
42
+ // Security check (root commands get extra scrutiny)
43
+ const blocked = ctx.security.checkCommand(`su: ${command}`, device);
44
+ if (blocked) {
45
+ return { content: [{ type: "text", text: blocked }], isError: true };
46
+ }
47
+ const resolved = await ctx.deviceManager.resolveDevice(device);
48
+ const result = await ctx.bridge.rootShell(command, {
49
+ device: resolved.serial,
50
+ ignoreExitCode: true,
51
+ });
52
+ let output = result.stdout;
53
+ if (result.stderr) {
54
+ output += `\n--- STDERR ---\n${result.stderr}`;
55
+ }
56
+ return { content: [{ type: "text", text: OutputProcessor.process(output) }] };
57
+ }
58
+ catch (error) {
59
+ return { content: [{ type: "text", text: OutputProcessor.formatError(error) }], isError: true };
60
+ }
61
+ });
62
+ }
63
+ //# sourceMappingURL=shell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.js","sourceRoot":"","sources":["../../src/tools/shell.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAEpE,MAAM,UAAU,kBAAkB,CAAC,GAAgB;IAEjD,GAAG,CAAC,MAAM,CAAC,IAAI,CACb,WAAW,EACX,2EAA2E,EAC3E;QACE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC;QACtE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC;QACvD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;KACpG,EACD,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;QACrC,IAAI,CAAC;YACH,iBAAiB;YACjB,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC3D,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YACvE,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,aAAa,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;YAC/D,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE;gBAC7C,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,OAAO;gBACP,cAAc,EAAE,IAAI;aACrB,CAAC,CAAC;YACH,IAAI,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;YAC3B,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClB,MAAM,IAAI,qBAAqB,MAAM,CAAC,MAAM,EAAE,CAAC;YACjD,CAAC;YACD,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gBAC1B,MAAM,IAAI,oBAAoB,MAAM,CAAC,QAAQ,MAAM,CAAC;YACtD,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;QAChF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAClG,CAAC;IACH,CAAC,CACF,CAAC;IAEF,GAAG,CAAC,MAAM,CAAC,IAAI,CACb,gBAAgB,EAChB,2DAA2D,EAC3D;QACE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;QACtD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC;KACxD,EACD,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE;QAC5B,IAAI,CAAC;YACH,oDAAoD;YACpD,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,OAAO,OAAO,EAAE,EAAE,MAAM,CAAC,CAAC;YACpE,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YACvE,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,aAAa,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;YAC/D,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE;gBACjD,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,cAAc,EAAE,IAAI;aACrB,CAAC,CAAC;YACH,IAAI,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;YAC3B,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClB,MAAM,IAAI,qBAAqB,MAAM,CAAC,MAAM,EAAE,CAAC;YACjD,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;QAChF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAClG,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Snapshot Tools — Save and compare device state for reproducible testing.
3
+ *
4
+ * Captures a comprehensive device state snapshot (packages, settings, properties)
5
+ * and can compare the current state against a saved snapshot to detect drift.
6
+ */
7
+ import { ToolContext } from "../tool-context.js";
8
+ export declare function registerSnapshotTools(ctx: ToolContext): void;
9
+ //# sourceMappingURL=snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../src/tools/snapshot.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAejD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAsM5D"}
@@ -0,0 +1,192 @@
1
+ /**
2
+ * Snapshot Tools — Save and compare device state for reproducible testing.
3
+ *
4
+ * Captures a comprehensive device state snapshot (packages, settings, properties)
5
+ * and can compare the current state against a saved snapshot to detect drift.
6
+ */
7
+ import { z } from "zod";
8
+ import { join } from "path";
9
+ import { mkdirSync, writeFileSync, readFileSync, existsSync } from "fs";
10
+ import { OutputProcessor } from "../middleware/output-processor.js";
11
+ import { validateShellArgs } from "../middleware/sanitize.js";
12
+ export function registerSnapshotTools(ctx) {
13
+ ctx.server.tool("adb_snapshot_capture", "Capture a comprehensive device state snapshot: installed packages, key settings, and system properties. Saves to a JSON file.", {
14
+ name: z.string().optional().describe("Snapshot name (default: auto-generated timestamp)"),
15
+ device: z.string().optional().describe("Device serial"),
16
+ }, async ({ name, device }) => {
17
+ try {
18
+ const resolved = await ctx.deviceManager.resolveDevice(device);
19
+ const serial = resolved.serial;
20
+ // Gather state in parallel
21
+ const [pkgResult, globalResult, secureResult, systemResult, propResult] = await Promise.allSettled([
22
+ ctx.bridge.shell("pm list packages -3", { device: serial }),
23
+ ctx.bridge.shell("settings list global", { device: serial }),
24
+ ctx.bridge.shell("settings list secure", { device: serial }),
25
+ ctx.bridge.shell("settings list system", { device: serial }),
26
+ ctx.bridge.shell("getprop", { device: serial }),
27
+ ]);
28
+ const parsePackages = (r) => {
29
+ if (r.status !== "fulfilled")
30
+ return [];
31
+ return r.value.stdout.split("\n")
32
+ .map((l) => l.replace("package:", "").trim())
33
+ .filter((l) => l.length > 0).sort();
34
+ };
35
+ const parseSettings = (r) => {
36
+ if (r.status !== "fulfilled")
37
+ return {};
38
+ const map = {};
39
+ for (const line of r.value.stdout.split("\n")) {
40
+ const idx = line.indexOf("=");
41
+ if (idx > 0)
42
+ map[line.substring(0, idx)] = line.substring(idx + 1).trim();
43
+ }
44
+ return map;
45
+ };
46
+ const parseProps = (r) => {
47
+ if (r.status !== "fulfilled")
48
+ return {};
49
+ const map = {};
50
+ for (const line of r.value.stdout.split("\n")) {
51
+ const match = line.trim().match(/^\[(.+?)\]: \[(.*)?\]$/);
52
+ if (match)
53
+ map[match[1]] = match[2] ?? "";
54
+ }
55
+ return map;
56
+ };
57
+ const props = parseProps(propResult);
58
+ const snapshot = {
59
+ timestamp: new Date().toISOString(),
60
+ device: serial,
61
+ model: props["ro.product.model"] ?? "unknown",
62
+ androidVersion: props["ro.build.version.release"] ?? "unknown",
63
+ sdkLevel: props["ro.build.version.sdk"] ?? "unknown",
64
+ packages: parsePackages(pkgResult),
65
+ settings: {
66
+ global: parseSettings(globalResult),
67
+ secure: parseSettings(secureResult),
68
+ system: parseSettings(systemResult),
69
+ },
70
+ properties: props,
71
+ };
72
+ const safeName = (name ?? `snapshot_${Date.now()}`).replace(/[^a-zA-Z0-9_-]/g, "_");
73
+ const filePath = join(ctx.config.tempDir, "snapshots", `${safeName}.json`);
74
+ const dir = join(ctx.config.tempDir, "snapshots");
75
+ if (!existsSync(dir)) {
76
+ mkdirSync(dir, { recursive: true });
77
+ }
78
+ writeFileSync(filePath, JSON.stringify(snapshot, null, 2));
79
+ return {
80
+ content: [{
81
+ type: "text",
82
+ text: `Snapshot captured: ${filePath}\nDevice: ${snapshot.model} (Android ${snapshot.androidVersion})\nPackages: ${snapshot.packages.length}\nSettings: ${Object.keys(snapshot.settings.global).length} global, ${Object.keys(snapshot.settings.secure).length} secure, ${Object.keys(snapshot.settings.system).length} system\nProperties: ${Object.keys(snapshot.properties).length}`,
83
+ }],
84
+ };
85
+ }
86
+ catch (error) {
87
+ return { content: [{ type: "text", text: OutputProcessor.formatError(error) }], isError: true };
88
+ }
89
+ });
90
+ ctx.server.tool("adb_snapshot_compare", "Compare current device state against a saved snapshot. Shows added/removed packages, changed settings, and property differences.", {
91
+ snapshotPath: z.string().describe("Path to the saved snapshot JSON file"),
92
+ device: z.string().optional().describe("Device serial"),
93
+ }, async ({ snapshotPath, device }) => {
94
+ try {
95
+ if (!existsSync(snapshotPath)) {
96
+ return { content: [{ type: "text", text: `Snapshot file not found: ${snapshotPath}` }], isError: true };
97
+ }
98
+ const saved = JSON.parse(readFileSync(snapshotPath, "utf-8"));
99
+ const resolved = await ctx.deviceManager.resolveDevice(device);
100
+ const serial = resolved.serial;
101
+ // Get current packages
102
+ const pkgResult = await ctx.bridge.shell("pm list packages -3", { device: serial });
103
+ const currentPkgs = pkgResult.stdout.split("\n")
104
+ .map((l) => l.replace("package:", "").trim())
105
+ .filter((l) => l.length > 0).sort();
106
+ const added = currentPkgs.filter((p) => !saved.packages.includes(p));
107
+ const removed = saved.packages.filter((p) => !currentPkgs.includes(p));
108
+ // Compare key settings
109
+ const settingsChanges = [];
110
+ for (const ns of ["global", "secure"]) {
111
+ const savedNs = saved.settings[ns];
112
+ const currentResult = await ctx.bridge.shell(`settings list ${ns}`, { device: serial });
113
+ const currentNs = {};
114
+ for (const line of currentResult.stdout.split("\n")) {
115
+ const idx = line.indexOf("=");
116
+ if (idx > 0)
117
+ currentNs[line.substring(0, idx)] = line.substring(idx + 1).trim();
118
+ }
119
+ for (const [key, val] of Object.entries(savedNs)) {
120
+ if (currentNs[key] !== undefined && currentNs[key] !== val) {
121
+ settingsChanges.push(`${ns}/${key}: "${val}" → "${currentNs[key]}"`);
122
+ }
123
+ }
124
+ }
125
+ const sections = [];
126
+ sections.push(`Comparing against: ${saved.timestamp}`);
127
+ sections.push(`Snapshot device: ${saved.model} (Android ${saved.androidVersion})`);
128
+ if (added.length === 0 && removed.length === 0 && settingsChanges.length === 0) {
129
+ sections.push("\nNo differences detected.");
130
+ }
131
+ else {
132
+ if (added.length > 0)
133
+ sections.push(`\nPackages added (+${added.length}):\n ${added.join("\n ")}`);
134
+ if (removed.length > 0)
135
+ sections.push(`\nPackages removed (-${removed.length}):\n ${removed.join("\n ")}`);
136
+ if (settingsChanges.length > 0)
137
+ sections.push(`\nSettings changed (${settingsChanges.length}):\n ${settingsChanges.join("\n ")}`);
138
+ }
139
+ return { content: [{ type: "text", text: sections.join("\n") }] };
140
+ }
141
+ catch (error) {
142
+ return { content: [{ type: "text", text: OutputProcessor.formatError(error) }], isError: true };
143
+ }
144
+ });
145
+ ctx.server.tool("adb_snapshot_restore_settings", "Restore settings from a saved snapshot to the current device. Only restores global and secure settings — does not install/uninstall packages.", {
146
+ snapshotPath: z.string().describe("Path to the saved snapshot JSON file"),
147
+ namespace: z.enum(["global", "secure", "both"]).optional().default("both")
148
+ .describe("Which settings namespace to restore"),
149
+ device: z.string().optional().describe("Device serial"),
150
+ }, async ({ snapshotPath, namespace, device }) => {
151
+ try {
152
+ if (!existsSync(snapshotPath)) {
153
+ return { content: [{ type: "text", text: `Snapshot file not found: ${snapshotPath}` }], isError: true };
154
+ }
155
+ const saved = JSON.parse(readFileSync(snapshotPath, "utf-8"));
156
+ const resolved = await ctx.deviceManager.resolveDevice(device);
157
+ const serial = resolved.serial;
158
+ const namespaces = namespace === "both" ? ["global", "secure"] : [namespace];
159
+ let restored = 0;
160
+ const errors = [];
161
+ for (const ns of namespaces) {
162
+ const savedSettings = saved.settings[ns];
163
+ for (const [key, value] of Object.entries(savedSettings)) {
164
+ try {
165
+ // Validate deserialized JSON values before shell interpolation
166
+ const argErr = validateShellArgs([[key, "setting key"], [value, "setting value"]]);
167
+ if (argErr) {
168
+ errors.push(`${ns}/${key}: skipped — ${argErr}`);
169
+ continue;
170
+ }
171
+ await ctx.bridge.shell(`settings put ${ns} ${key} ${value}`, { device: serial });
172
+ restored++;
173
+ }
174
+ catch (err) {
175
+ errors.push(`${ns}/${key}: ${err instanceof Error ? err.message : err}`);
176
+ }
177
+ }
178
+ }
179
+ let output = `Restored ${restored} settings from snapshot (${saved.timestamp})`;
180
+ if (errors.length > 0) {
181
+ output += `\n${errors.length} errors:\n ${errors.slice(0, 10).join("\n ")}`;
182
+ if (errors.length > 10)
183
+ output += `\n ... and ${errors.length - 10} more`;
184
+ }
185
+ return { content: [{ type: "text", text: output }] };
186
+ }
187
+ catch (error) {
188
+ return { content: [{ type: "text", text: OutputProcessor.formatError(error) }], isError: true };
189
+ }
190
+ });
191
+ }
192
+ //# sourceMappingURL=snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/tools/snapshot.ts"],"names":[],"mappings":"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"}