使用 semgrep 检测 AndroidManifest 中的 debuggable 标志:MASTG-DEMO-0040 实战解析
文档教程网络安全【免费下载链接】mastgThe OWASP Mobile Application Security Testing Guide (MASTG) is a comprehensive manual for mobile app security testing and reverse engineering. It describes technical processes for verifying the OWASP Mobile Security Weakness Enumeration (MASWE) weaknesses, which are in alignment with the OWASP MASVS.项目地址https://gitcode.com/gh_mirrors/ow/mastg点击查看免费下载本篇文章以 OWASP MASTG 仓库中的 MASTG-DEMO-0040 演示用例为主线完整讲解如何利用静态分析工具 semgrep 与仓库内置规则检测 Android 应用AndroidManifest.xml中危险的android:debuggabletrue配置。读完本文你将掌握debuggable 标志的安全风险模型、semgrep 规则的编写与执行方法、manifest 的提取与分析流程以及该问题对应的 MASTG 测试用例、评估标准与修复建议可直接用于日常移动应用安全测试工作。背景为什么android:debuggable值得关注android:debuggable是 AndroidApplication元素上的一个布尔型属性用于声明应用是否允许被调试。当该标志被显式设置为true时应用进程会额外启动一个用于处理 JDWPJava Debug Wire Protocol协议数据包的线程——正如 MASTG-KNOW-0007 中所述每个启用调试的进程都会运行一个额外的 JDWP 线程而该线程只会为设置了android:debuggabletrue的应用启动。攻击者一旦接入 JDWP 通道即可附加调试器、读取内存中的敏感数据、设置断点、动态修改运行时行为甚至绕过应用内已有的安全控制。对应 MASTG-TEST-0226 的描述该测试用例检查应用是否在AndroidManifest.xml中将debuggable标志设置为true。虽然谷歌官方指出debuggable标志本身并不被视为一个直接的漏洞但它会显著扩大攻击面——在生产环境中它等于向攻击者敞开了访问应用数据与内部资源的大门。在 MASTG 的测试体系中该问题被归类为测试用例MASTG-TEST-0226static/code 类型对应 MASWE-0063最佳实践MASTG-BEST-0007——所有 release 构建中 debuggable 标志必须设为false旧版映射早期版本对应的 MASTG-TEST-0039MSTG-CODE-2已标记为 deprecated由 MASTG-TEST-0226 / 0227 覆盖。Demo 用例结构速览MASTG-DEMO-0040 演示了规则 → 样本 → 扫描 → 输出 → 评估的完整自动化静态检测闭环。该用例目录包含以下文件MASTG-DEMO-0040.md用例说明Sample / Steps / Observation / EvaluationAndroidManifest.xml原始源码态manifest 样本作为对比参照AndroidManifest_reversed.xml反编译后的 manifest即实际被扫描的对象模拟从 APK 中逆向提取出的形态run.sh执行 semgrep 扫描的脚本output.txt扫描结果输出关联规则rules/mastg-android-debuggable-flag.yml关联工具MASTG-TOOL-0110semgrep。样本分析源码态与反编译态 manifest 对比原始 manifest源码态AndroidManifest.xml 展示的是一个带有 debuggable 标志的示例 manifestapplication元素中显式声明了android:debuggabletrue?xml version1.0 encodingutf-8? manifest xmlns:androidhttp://schemas.android.com/apk/res/android xmlns:toolshttp://schemas.android.com/tools uses-permission android:nameandroid.permission.INTERNET / application android:allowBackuptrue android:debuggabletrue android:dataExtractionRulesxml/data_extraction_rules android:fullBackupContentxml/backup_rules android:iconmipmap/ic_launcher android:labelstring/app_name android:roundIconmipmap/ic_launcher_round android:supportsRtltrue android:themestyle/Theme.MASTestApp tools:targetApi31 activity android:name.MainActivity android:exportedtrue android:themestyle/Theme.MASTestApp intent-filter action android:nameandroid.intent.action.MAIN / category android:nameandroid.intent.category.LAUNCHER / /intent-filter /activity /application /manifest可以看到除了android:debuggabletrue这一风险点该样本还包含android:allowBackuptrue另一个常见安全关注点以及一个导出且带 LAUNCHER intent-filter 的MainActivity。作为测试样本它刻意保留了这些典型配置便于规则在真实形态的 manifest 上命中。反编译后的 manifest扫描对象AndroidManifest_reversed.xml 模拟了从 APK 中逆向提取出的二进制 XML 解码结果standaloneno、packageorg.owasp.mastestapp、compileSdkVersion35、compileSdkVersionCodename15、platformBuildVersionCode35。其application元素保留了原始源码中的全部属性其中第 5 行明确包含android:debuggabletrueapplication android:allowBackuptrue android:appComponentFactoryandroidx.core.app.CoreComponentFactory android:dataExtractionRulesxml/data_extraction_rules android:debuggabletrue android:extractNativeLibsfalse android:fullBackupContentxml/backup_rules android:iconmipmap/ic_launcher android:labelstring/app_name android:roundIconmipmap/ic_launcher_round android:supportsRtltrue android:themestyle/Theme.MASTestApp这份反编译 manifest 还展示了真实应用中常见的框架注入痕迹androidx.core.app.CoreComponentFactory、androidx.startup.InitializationProvider、ProfileInstallReceiver、DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION等。这意味着在实际测试中你扫描的 manifest 会包含大量与业务无关的框架声明——而 semgrep 规则恰恰能在不误报这些内容的前提下精准定位到debuggable属性。提示Android 的 AndroidManifest 以二进制 XML 格式存储在 APK 中无法通过直接解压读取必须先经过解码工具处理。关于如何获取并解码 manifest见下文获取待扫描的 manifest一节。semgrep 规则深度解析MASTG 为 debuggable 标志检测内置了一条 semgrep 规则位于 rules/mastg-android-debuggable-flag.yml完整内容如下rules: - id: mastg-android-debuggable-flag severity: WARNING languages: - xml metadata: summary: This rule inspects the AndroidManifest.xml for the debuggable flag. message: [MASVS-RESILIENCE-4] debuggable detected as $ARG. patterns: - pattern: android:debuggable$ARG逐项拆解这条规则的语义配置项取值含义idmastg-android-debuggable-flag规则的唯一标识符将出现在扫描结果中便于自动化流水线归类与去重severityWARNING告警级别。因为debuggable本身不是直接漏洞而是风险放大因素故定为 WARNING 而非 ERRORlanguagesxml声明规则匹配 XML 语言。虽然 MASTG-TOOL-0110 对 semgrep 的官方定位是能够扫描 Java、Kotlin 和 Swift 的静态代码扫描器但 semgrep 同样支持 XML这正是本规则能够分析 manifest 的原因message[MASVS-RESILIENCE-4] debuggable detected as $ARG.命中时输出的提示信息其中$ARG是捕获组将实际属性值true/false回填到消息中同时标注了对应的 MASVS 控制项patternspattern: android:debuggable$ARG核心匹配模式查找形如android:debuggable...的属性声明并通过$ARG元变量捕获引号内的具体取值这里有一个值得注意的设计细节规则捕获的是属性值本身$ARG而不仅仅是指纹匹配android:debuggable字符串。这使得规则的输出信息能够明确区分true与false——虽然生产环境的要求是false但测试人员仍可通过$ARG的值快速判断当前命中的究竟是配置错误还是合法配置避免机械式地报告所有命中项。执行步骤运行 semgrep 规则MASTG-DEMO-0040 通过 run.sh 执行扫描脚本内容只有一条命令NO_COLORtrue semgrep -c ../../../../rules/mastg-android-debuggable-flag.yml ./AndroidManifest_reversed.xml output.txt命令关键点逐一说明NO_COLORtrue禁用 semgrep 输出的 ANSI 颜色转义序列保证输出为纯文本便于写入output.txt文件、后续做 diff 或纳入 CI 日志semgrep -c rule-c/--config参数指定规则文件。这里指向仓库根目录rules/下的mastg-android-debuggable-flag.yml原文档中../../../../rules/...是从 demo 目录到仓库规则目录的相对路径实际文件位于 rules/mastg-android-debuggable-flag.yml扫描目标./AndroidManifest_reversed.xml——即反编译后的 manifest 文件输出重定向 output.txt将扫描结果持久化。从仓库规则目录结构看rules/ 下存放了数十条按平台与主题组织的 semgrep 规则mastg-android-*.yml/.yaml覆盖加密、网络、存储、WebView、root 检测等主题mastg-android-debuggable-flag.yml只是其中一条。这意味着你完全可以复用同一套方法论用相同的工作流批量扫描其他风险项。也可以按仓库惯例直接指定整个规则目录进行多规则扫描semgrep --config rules/ --lang xml AndroidManifest_reversed.xml观察扫描输出解读运行上述命令后output.txt 记录了 semgrep 的完整结果。核心内容如下┌────────────────┐ │ 1 Code Finding │ └────────────────┘ AndroidManifest_reversed.xml ❯❱ mastg-android-debuggable-flag [MASVS-RESILIENCE-4] debuggable detected as true. 5┆ application android:allowBackuptrue android:appComponentFactoryandroidx.core.app.CoreComponentFactory android:dataExtractionRulesxml/data_extraction_rules android:debuggabletrue android:extractNativeLibsfalse android:fullBackupContentxml/backup_rules android:iconmipmap/ic_launcher android:labelstring/app_name android:roundIconmipmap/ic_launcher_round android:supportsRtltrue android:themestyle/Theme.MASTestApp解读这份输出的几个要点1 Code Finding整个文件中恰好命中 1 处代码发现说明规则具备精准性——框架注入的众多属性声明appComponentFactory、extractNativeLibs等都没有触发误报唯一命中的正是android:debuggable规则标识❯❱ mastg-android-debuggable-flag表明命中的是仓库规则文件中的规则 id规则消息[MASVS-RESILIENCE-4] debuggable detected as true.——$ARG捕获到的值是true直接确认了风险配置的存在源码定位输出以5┆起始的代码片段精确指向AndroidManifest_reversed.xml第 5 行的application元素供测试人员快速人工复核。评估测试结论依据 MASTG-TEST-0226 的评估标准如果debuggable标志被显式设置为true测试用例失败——这表示应用被配置为允许调试对生产环境而言是不适当的。在本 Demo 中semgrep 规则明确识别出android:debuggabletrue因此MASTG-DEMO-0040 的评估结论为失败Fail。需要补充的是MASTG-TEST-0226 同时指出如果 manifest 中未指定该标志对于 release 构建默认按false处理即测试通过。纵深扩展从静态扫描到完整验证获取待扫描的 manifest静态扫描的第一步是拿到可读的AndroidManifest.xml。根据 MASTG-TECH-0117AndroidManifest 以二进制 XML 存储于 APK 中需要先用工具解码常用的三种方式jadxMASTG-TOOL-0018CLI 只解资源不解源码jadx --no-src -d out_dir app.apk输出位于out_dir/resources/AndroidManifest.xml且包含其他工具不输出的uses-sdk元素apktoolMASTG-TOOL-0011apktool d -s -f -o output_dir app.apk-s跳过 baksmali、只解资源速度更快解码结果在output_dir/AndroidManifest.xml注意uses-sdk会被移入apktool.yml的sdkInfo段aapt2MASTG-TOOL-0124aapt2 d badging app.apk注意其输出不是 XML而是自定义解码格式如application-debuggable。解码工具的差异会影响你后续的规则编写MASTG-TECH-0150 指出jadx / apktool 输出标准 XMLandroid:debuggabletrue形式而 aapt2 输出自定义格式application-debuggable形式。本 Demo 的规则针对标准 XML 形态编写若扫描对象来自 aapt2则需要调整匹配模式。手工分析 manifest 的补充手段除 semgrep 自动化扫描外MASTG-TECH-0150 提供了手工核查 debuggable 标志的多种方法grep直接检索解码后的 XMLgrep -i android:debuggable output_dir/AndroidManifest.xmlaapt2不解码直接查 badging 输出aapt2 d badging app.apk | grep -i debuggablexmllint / xmlstarlet结构化查询xmlstarlet sel -t -v //application/android:debuggable -n output_dir/AndroidManifest.xml动态验证方法静态发现之后可用动态手段确认应用实际以可调试状态运行。早期测试用例 MASTG-TEST-0039现已由 MASTG-TEST-0226 替代记录了以下实用技巧aapt快速检查编译产物中的标志位aapt d xmltree sieve.apk AndroidManifest.xml | grep -Ec android:debuggable\(0x[0-9a-f]\)\(type\s0x[0-9a-f]\)0xffffffff若输出为1说明android:debuggabletrue指令存在adb dumpsys检查运行时标志adb shell dumpsys package com.mwr.example.sieve | grep -c DEBUGGABLE输出大于 0 说明应用带 DEBUGGABLE 标志run-as验证调试特权——可调试应用允许直接以该应用身份执行命令run-as com.vulnerable.app idjdb附加调试会话通过adb jdwp找 PID →adb forward tcp:55555 jdwp:PID建立通道 →jdb -connect com.sun.jdi.SocketAttach:hostnamelocalhost,port55555附加调试器。若附加成功则证明调试已被激活。这些手段与 semgrep 静态扫描互为印证构成静态发现 → 动态确认的完整测试链路。修复与加固建议依据 MASTG-BEST-0007修复方法非常直接确保所有 release 构建中 AndroidManifest.xml 的 debuggable 标志设置为false。具体到工程实践检查构建脚本Gradle / CI 配置确认 release 变体未注入android:debuggabletrue发布前在构建产物上执行本文所述的 semgrep 规则或aapt2 d badging检查作为发布门禁将 rules/mastg-android-debuggable-flag.yml 集成进 CI 流水线对AndroidManifest_reversed.xml或解码后的 manifest持续扫描阻止携带该标志的构建进入生产环境。小结MASTG-DEMO-0040 完整展示了如何借助 MASTG-TOOL-0110semgrep与仓库内置规则 mastg-android-debuggable-flag.yml对 Android 应用的 manifest 进行自动化安全检测。整个工作流可归纳为提取解码 manifestMASTG-TECH-0117→ 编写/复用规则 → 执行扫描 → 解读输出 → 对照 MASTG-TEST-0226 评估 → 按 MASTG-BEST-0007 修复。该模式同样适用于仓库 rules/ 目录下其他数十条 Android 安全规则是 MASTG 将安全测试规范落地为可重复执行、可集成进 CI 的自动化方案的典型范例。赞分享文档教程网络安全【免费下载链接】mastgThe OWASP Mobile Application Security Testing Guide (MASTG) is a comprehensive manual for mobile app security testing and reverse engineering. It describes technical processes for verifying the OWASP Mobile Security Weakness Enumeration (MASWE) weaknesses, which are in alignment with the OWASP MASVS.项目地址https://gitcode.com/gh_mirrors/ow/mastg点击查看免费下载相关推荐OWASP MASTG 实战使用 semgrep 静态检测 AndroidManifest 中的危险权限MASTG-DEMO-0033OWASP MASTG 实战使用 semgrep 静态检测 AndroidManifest 中的危险权限MASTG DEMO 0033 本文围绕 OWAS文档教程网络安全MASTG-BEST-0007 解读在 AndroidManifest 中禁用 debuggable 标志的发布构建安全实践MASTG BEST 0007 解读在 AndroidManifest 中禁用 debuggable 标志的发布构建安全实践 导读 本指南以 OWASP M文档教程网络安全OWASP MASTG 实战用 Semgrep 静态检测 Android StrictMode 使用MASTG-DEMO-0039OWASP MASTG 实战用 Semgrep 静态检测 Android StrictMode 使用MASTG DEMO 0039 导读 本文基于 OW文档教程网络安全创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

2026年GEO源码搭建实战常见问题与踩坑汇总 环境配置依赖兼容及部署运维详细避坑指南

2026年GEO源码搭建实战常见问题与踩坑汇总 环境配置依赖兼容及部署运维详细避坑指南

做GEO地理信息系统源码搭建快5年,从最早手动编译各个GIS模块,到现在标准化的部署方案,见过太多开发者在环境配置、依赖兼容上反复踩坑。尤其是2026年主流GEO框架和底层依赖都完成了大版本迭代,网上不少三四年前的老教程已经完全失…

2026/10/7 8:06:01 阅读更多 →
HarmonyOS 7 MQTT:QoS1离线发件箱与会话续接

HarmonyOS 7 MQTT:QoS1离线发件箱与会话续接

一、网络恢复了,八条指令却发出了九次 RelayMeter 是一个现场电表控制 Demo。页面上点“读取参数”“校准时钟”“切换采样档位”,命令通过 MQTT over WSS 发给设备。实验室 Wi-Fi 稳定时一切正常,到了地下配电间,网络会在 5G、无…

2026/10/7 8:06:00 阅读更多 →
【路径规划】基于matlab强化学习的改进蚁群算法RBIACO机器人路径规划【含Matlab源码 16026期】

【路径规划】基于matlab强化学习的改进蚁群算法RBIACO机器人路径规划【含Matlab源码 16026期】

💥💥💥💥💥💥💞💞💞💞💞💞💞💞欢迎来到海神之光博客之家💞💞💞&#x1f49…

2026/10/7 8:05:00 阅读更多 →

最新新闻

射频通信基础实战指南:从S参数到链路预算的工程核心

射频通信基础实战指南:从S参数到链路预算的工程核心

做射频调试这些年,我最大的感受是:射频通信基础这门课,学校教的和工程上用的,中间隔着一道很深的沟。书本上讲麦克斯韦方程组、讲电磁波传播,但实际调试时你面对的是S参数、是阻抗匹配、是屏蔽罩谐振这种能把人逼疯的细…

2026/10/7 9:05:52 阅读更多 →
AnyPS5 PS5移植工具:libSceHttp HTTP客户端移植与URI解析完整实录

AnyPS5 PS5移植工具:libSceHttp HTTP客户端移植与URI解析完整实录

AnyPS5 PS5移植工具:libSceHttp HTTP客户端移植与URI解析完整实录 【免费下载链接】AnyPS5 Tool for automatic PS5 executables porting to Linux and Windows 项目地址: https://gitcode.com/GitHub_Trending/an/AnyPS5 AnyPS5 是一款PS5可执行文件自动移植…

2026/10/7 9:05:52 阅读更多 →
superpowers:让多人实时协作开发从底层难题变成SDK调用

superpowers:让多人实时协作开发从底层难题变成SDK调用

上个月有个朋友让我帮忙做一个"上线就能用"的协作白板,说是给周末线上工作坊用的。我第一反应是:WebSocket、消息广播、冲突处理、在线状态、断线重连……这些整套搞下来,别说一个周末,一周都够呛。直到我在技术社区里翻…

2026/10/7 9:05:52 阅读更多 →
HTTP/2分帧解析:用Python hyperframe库轻松编解码帧

HTTP/2分帧解析:用Python hyperframe库轻松编解码帧

第一次在 Wireshark 里跟踪 HTTP/2 请求,估计很多人跟我一样被那一串十六进制弄懵了:明明只是一个 GET 请求,怎么变成了 DATA、HEADERS、SETTINGS、WINDOW_UPDATE 一堆帧,每个帧前面还挂着一个 9 字节的二进制头。如果你恰好需要自…

2026/10/7 9:05:52 阅读更多 →
IGBT从原理到实战:驱动电路、栅极波形与选型散热全解析

IGBT从原理到实战:驱动电路、栅极波形与选型散热全解析

IGBT这几年在新能源、工业变频、电驱系统里出镜率实在太高了,从几百瓦的家电变频器到几兆瓦的储能变流器,几乎都能看到它。但很多人学IGBT都是靠手册硬啃,对它的结构、工作原理、驱动电路、栅极波形这些核心知识其实是一知半解的,…

2026/10/7 9:05:51 阅读更多 →
MOS管五维测试法:告别万用表误判

MOS管五维测试法:告别万用表误判

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 9:04:50 阅读更多 →

日新闻

ROS2机械臂仿真与运动控制:从URDF建模到Gazebo实战全解析

ROS2机械臂仿真与运动控制:从URDF建模到Gazebo实战全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 1:01:58 阅读更多 →
用浏览器直接改ESP32的WiFi密码:NVS键值配置工具设计与实现

用浏览器直接改ESP32的WiFi密码:NVS键值配置工具设计与实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 1:02:00 阅读更多 →
芯片封装缺陷检测:扫描声学显微镜(SAT)原理与实操指南

芯片封装缺陷检测:扫描声学显微镜(SAT)原理与实操指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 1:02:00 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/6 7:15:40 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/6 5:29:09 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/6 6:26:51 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/6 8:21:32 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/6 4:21:51 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/6 1:18:13 阅读更多 →