第3章 SDK隐私风险识别方法论

做SDK合规治理,第一步不是看条款,而是搞清楚你的SDK到底在做什么。我遇到过不少开发者,条款写得很漂亮,代码里却在偷偷传IMEI。这章我就带你捋一遍风险识别的方法论,把重点放在数据流映射、敏感信息识别和第三方SDK风险清单上。

3.1 数据流映射——把隐私流动画出来

说白了,数据流映射就是把你SDK内部的数据“旅行路线”画出来。我个人的习惯是,每次接手新SDK,第一件事就是画这个图。

数据流节点描述常见问题
采集点从哪获取数据(API调用、传感器、剪贴板)过度采集、非必要采集
处理逻辑数据如何变换(加密、聚合、匿名化)伪匿名化、残留日志
存储介质数据暂存在哪(内存、本地文件、SharePreference)明文存储、未及时清理
传输通道数据如何出去(HTTP、WebSocket、IPC)未加密、跨进程泄露
第三方落地最终发给谁(服务器、广告平台、统计分析)未知接收方、无合约
我建议用UML序列图或简单的流程图做映射。工具不重要,关键是把每条数据路径都标出来。曾经有个项目,画完才发现IMEI在启动阶段就被传给一个废弃的统计SDK,而那个SDK早已停止维护。
数据流映射的核心原则:谁、在哪、什么时候、采集了什么数据、发给了谁、存了多久、是否可删除。

3.2 敏感信息识别——盯紧IMEI、MAC、位置

敏感信息不是只有黑白名单。你想想看,IMEI获取可能只在一行代码里。

// 危险:直接读IMEI
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String imei = tm.getDeviceId(); // 需要READ_PHONE_STATE权限

我遇到过最隐蔽的是通过WiFi扫描间接推断位置。明明是“获取周围WiFi列表”的功能,结合几个基站信号强度,就能大致定位。

  • IMEI / IMSI / MEID:Android 10+无法直接获取,但getIccId()、getSubscriberId()仍可能被滥用。
  • MAC地址:Android 6+已随机化,但部分厂商会暴露真实MAC,尤其通过WifiManager.getConnectionInfo().getMacAddress()。
  • 位置:GPS、网络、基站。注意“附近设备扫描”可能触发位置权限。
  • 其他“灰色”信息:Android ID、OAID、SSAID、设备序列号。
【我曾踩坑】有一次SDK只在debug构建中打印了IMEI,release版本去掉了。结果用户反馈上线后仍有网络请求携带设备ID——因为混淆保留了Log,但Log被linker吞掉并不代表网络层也去掉了。所以,不要相信干掉的代码,要验证网络包。

3.3 第三方SDK潜在风险清单

你的SDK可能依赖其他SDK,它们之间会互相传递数据,形成风险链。我习惯做一张风险清单表,按优先级排序。

风险类型典型场景检查要点
权限升级父SDK声明了权限,子SDK直接使用检查AndroidManifest合并日志
数据重定向子SDK把IMEI上报给其自有服务器抓包、网络白名单验证
交互式接口子SDK暴露Activity,可能回传用户操作检查AAR中Activity声明
隐私政策冲突不同SDK对数据保留期限定义不一致对比各SDK隐私文档
版本过时老旧SDK使用已废弃的敏感API更新至最新合规版本

识别方法很简单:用gradle dependencies等工具查看传递依赖树,手动追踪每个子SDK的隐私行为。我曾经发现某个广告SDK内部使用了早期版本的友盟,而友盟又依赖一个日历读写库——整个链条里没人知道日历权限是被谁声明的。

3.4 知识体系总览图

下面这张图概括了整个风险识别方法论的核心逻辑。

SDK隐私风险识别方法论框架图 隐私风险识别方法论 数据流映射 敏感信息识别 第三方SDK潜在风险 采集 → 处理 → 存储 → 传输 → 落地 IMEI / MAC / 位置 权限升级 / 数据重定向 / 政策冲突 ⚠️ 实践建议: 1. 先做数据流映射,再识别敏感信息,最后评估第三方风险 2. 每次版本更新重新做一次数据流审计 3. 保持第三方SDK清单实时更新,重点关注传递依赖 4. 建议输出《SDK隐私风险自查表》,逐项打勾

3.5 实战流程:从代码到风险清单

光看理论没用,我分享一套我常用的操作步骤。

  1. 静态扫描:使用工具(例如开源的checkstyle或lint自定义规则)定位敏感API调用。
  2. 动态抓包:用Charles或Wireshark录制所有出站流量,过滤目标域名。
  3. 代码审计:重点关注assets/jniLibs/包装类等不易被扫描到的区域。
  4. 依赖分析:./gradlew :module:dependencies --configuration releaseRuntimeClasspath。
  5. 风险归类:把发现的问题填入风险清单表格,与合规条款逐一对照。
记住:没有元数据的数据流分析,只是假动作。你一定要结合实际的设备行为(比如IMEI是否真的被读取、网络请求是否真的携带了位置),不能只看代码声明。