Docker与Kubernetes安全的十大常见漏洞:从特权容器到未授权API访问的防护清单
Docker与Kubernetes安全的十大常见漏洞从特权容器到未授权API访问的防护清单一、容器安全现状被低估的威胁面容器化带来效率也带来了全新的攻击面。根据CNCF 2026年的安全报告容器环境相关的安全事件同比增长47%其中前三类漏洞是特权容器滥用占比31%、镜像供应链攻击占比24%、API Server未授权访问占比18%。更令人担忧的是68%的受调查团队在发现安全漏洞时漏洞已经存在了3个月以上。容器的威胁面可以从四个维度划分镜像安全构建阶段、运行时安全运行阶段、编排安全Kubernetes层、供应链安全依赖链层。本文覆盖这四大维度下最常见的十大漏洞每个漏洞都包含危险等级、检测方法和修复方案。二、镜像安全构建阶段的三大致命漏洞漏洞一基础镜像包含已知高危CVE危险等级严重 |影响面85%的容器镜像漏洞描述使用未扫描的公共基础镜像如node:16、python:3.9这些镜像可能包含数百个已知CVE包括远程代码执行RCE和权限提升漏洞。检测方法# 使用Trivy扫描镜像漏洞 trivy image --severity CRITICAL,HIGH python:3.9 # 预期输出应清空所有CRITICAL和HIGH漏洞修复方案使用官方维护的最小化镜像如distroless、alpine在CI Pipeline中集成镜像扫描Trivy/Grype阻断含高危CVE的镜像推送到仓库import logging import subprocess import json from typing import Dict, List, Optional from dataclasses import dataclass logger logging.getLogger(__name__) dataclass class ImageSecurityPolicy: 镜像安全策略 max_critical_cves: int 0 # 允许的Critical CVE数量 max_high_cves: int 5 # 允许的高危CVE数量 max_medium_cves: int 20 # 允许的中危CVE数量 block_on_policy_violation: bool True # 违反策略时是否阻断 class ImageSecurityScanner: 容器镜像安全扫描器 def __init__(self, policy: ImageSecurityPolicy None): self.policy policy or ImageSecurityPolicy() def scan_image(self, image_name: str) - Dict: 扫描镜像安全漏洞 Args: image_name: 镜像名称含标签 Returns: 扫描结果包含漏洞统计和策略合规性 result { image: image_name, scan_tool: trivy, passed: True, vulnerabilities: {}, violations: [] } try: # 执行Trivy扫描输出JSON格式 cmd [ trivy, image, --format, json, --severity, CRITICAL,HIGH,MEDIUM, --no-progress, image_name ] proc subprocess.run( cmd, capture_outputTrue, textTrue, timeout300 ) if proc.returncode ! 0 and proc.returncode ! 1: # returncode0: 无漏洞, 1: 有漏洞, 其他: 扫描错误 result[passed] False result[error] f扫描失败: {proc.stderr[:200]} logger.error(f镜像扫描失败: {image_name}) return result # 解析扫描结果 try: scan_data json.loads(proc.stdout) except json.JSONDecodeError: result[passed] False result[error] 扫描结果JSON解析失败 return result # 统计各等级漏洞数量 severity_counts {CRITICAL: 0, HIGH: 0, MEDIUM: 0, LOW: 0} for report in scan_data.get(Results, []): for vuln in report.get(Vulnerabilities, []): sev vuln.get(Severity, UNKNOWN) if sev in severity_counts: severity_counts[sev] 1 result[vulnerabilities] severity_counts # 策略合规性检查 if severity_counts[CRITICAL] self.policy.max_critical_cves: result[violations].append( fCRITICAL漏洞: {severity_counts[CRITICAL]} f(允许: {self.policy.max_critical_cves}) ) result[passed] False if severity_counts[HIGH] self.policy.max_high_cves: result[violations].append( fHIGH漏洞: {severity_counts[HIGH]} f(允许: {self.policy.max_high_cves}) ) result[passed] False if severity_counts[MEDIUM] self.policy.max_medium_cves: result[violations].append( fMEDIUM漏洞: {severity_counts[MEDIUM]} f(允许: {self.policy.max_medium_cves}) ) result[passed] False status_msg 通过 if result[passed] else 未通过 logger.info(f镜像扫描: {image_name} - {status_msg} f(C:{severity_counts[CRITICAL]}/H:{severity_counts[HIGH]} f/M:{severity_counts[MEDIUM]})) return result except subprocess.TimeoutExpired: logger.error(f镜像扫描超时: {image_name}) return {image: image_name, passed: False, error: 扫描超时} except Exception as e: logger.error(f镜像扫描异常: {image_name} - {e}, exc_infoTrue) return {image: image_name, passed: False, error: str(e)}漏洞二镜像中硬编码密钥和凭证危险等级严重典型场景Dockerfile中直接写入数据库密码、API Key等敏感信息# 危险做法硬编码密钥 ENV DATABASE_PASSWORDMySecretPass123 ENV AWS_ACCESS_KEY_IDAKIAXXXXXXXX这些密钥会永久保存在镜像层中即使后续删除ENV指令也无法从镜像历史中移除。任何人获取镜像后都可以通过docker history查看所有层的构建历史。检测方法# 使用TruffleHog扫描镜像中的密钥 trufflehog filesystem --directory/path/to/extracted/image # 或使用git-secrets扫描Dockerfile git-secrets --scan Dockerfile修复方案使用Kubernetes Secret或外部密钥管理服务Vault/AWS Secrets Manager在Dockerfile中使用.dockerignore排除含密钥的文件CI Pipeline中集成密钥扫描发现硬编码密钥立即阻断构建漏洞三使用latest标签和无版本化镜像危险等级中漏洞描述image: nginx:latest意味着每次部署可能拉取到不同版本的镜像。如果最新版本包含破坏性变更或新增安全漏洞你的服务会在不知情的情况下受到影响。此外回滚时无法确定之前的latest对应哪个具体版本。修复方案使用语义化版本标签如nginx:1.25.3-alpine或镜像摘要Digest并在CI Pipeline中禁止使用latest标签。三、运行时安全三大危险配置漏洞四特权容器privileged: true危险等级严重 |利用难度极低漏洞描述securityContext.privileged: true赋予容器几乎等同于宿主机的所有能力包括访问所有设备、加载内核模块、修改内核参数。一旦特权容器被攻破攻击者可以逃逸到宿主机。检测命令# 扫描集群中所有特权容器 kubectl get pods --all-namespaces -o json | \ jq .items[] | select(.spec.containers[].securityContext.privilegedtrue) | {namespace: .metadata.namespace, name: .metadata.name}修复方案99%的场景不需要特权容器。如果确实需要某些Linux Capability如NET_ADMIN用于网络配置使用细粒度的capability添加而非整个特权模式securityContext: capabilities: add: [NET_ADMIN, SYS_TIME] drop: [ALL] # 先删除所有能力再按需添加 privileged: false # 明确禁止特权模式漏洞五以root用户运行容器危险等级高 |影响面60%的容器漏洞描述默认情况下容器以root用户UID 0运行。如果容器内的应用被攻破攻击者获得的是容器内的root权限配合其他漏洞如挂载了Docker Socket可以直接控制宿主机。检测方法# 检查以root运行的Pod kubectl get pods --all-namespaces -o json | \ jq .items[] | select(.spec.containers[].securityContext.runAsUsernull or .spec.containers[].securityContext.runAsUser0) | [.metadata.namespace, .metadata.name]修复方案# Pod安全上下文配置 securityContext: runAsNonRoot: true # 强制非root运行 runAsUser: 1000 # 指定非root UID fsGroup: 1000 # 文件系统组IDDockerfile层面# 创建非root用户并切换 RUN addgroup -g 1000 appgroup \ adduser -u 1000 -G appgroup -D appuser USER appuser漏洞六敏感目录挂载Docker Socket、hostPath危险等级严重典型危险挂载/var/run/docker.sock允许容器完全控制Docker守护进程/proc暴露宿主机进程信息/sys允许修改内核参数/根目录完全访问宿主机文件系统检测方法# 检查敏感hostPath挂载 kubectl get pods --all-namespaces -o json | \ jq .items[] | select(.spec.volumes[].hostPath.path | test(/var/run/docker.sock|/proc|/sys|/etc)) | {ns: .metadata.namespace, pod: .metadata.name}import logging from typing import Dict, List logger logging.getLogger(__name__) class ContainerSecurityAuditor: 容器安全配置审计器 # 危险挂载路径列表 DANGEROUS_MOUNTS [ /var/run/docker.sock, # Docker Socket /proc, # 进程文件系统 /sys, # 内核参数 /etc/kubernetes, # K8s配置 /var/lib/kubelet, # Kubelet数据 /etc/shadow, # 密码文件 ] # 危险Capability列表 DANGEROUS_CAPABILITIES [ SYS_ADMIN, # 几乎所有系统管理操作 SYS_PTRACE, # 进程跟踪 SYS_MODULE, # 内核模块加载 NET_RAW, # 原始网络包 DAC_OVERRIDE, # 绕过文件权限 ] def audit_pod_security(self, pod_spec: Dict) - List[Dict]: 审计单个Pod的安全配置 Args: pod_spec: Pod的spec定义 Returns: 安全问题列表 issues [] try: containers pod_spec.get(containers, []) volumes pod_spec.get(volumes, []) for container in containers: container_name container.get(name, unknown) sec_ctx container.get(securityContext, {}) # 检查1特权容器 if sec_ctx.get(privileged): issues.append({ container: container_name, severity: critical, issue: 容器以特权模式运行, fix: 设置 securityContext.privilegedfalse按需添加Linux Capability }) # 检查2root用户运行 run_as_user sec_ctx.get(runAsUser) run_as_non_root sec_ctx.get(runAsNonRoot) if (run_as_user is None or run_as_user 0) and not run_as_non_root: issues.append({ container: container_name, severity: high, issue: 容器以root用户运行, fix: 设置 runAsNonRoottrue 和 runAsUser1000 }) # 检查3危险Capability capabilities sec_ctx.get(capabilities, {}).get(add, []) for cap in capabilities: if cap in self.DANGEROUS_CAPABILITIES: issues.append({ container: container_name, severity: high, issue: f容器具有危险Capability: {cap}, fix: f除非明确需要否则移除 {cap} }) # 检查4危险hostPath挂载 for volume in volumes: host_path volume.get(hostPath, {}).get(path, ) for dangerous_path in self.DANGEROUS_MOUNTS: if host_path.startswith(dangerous_path): issues.append({ container: pod-level, severity: critical, issue: f容器挂载了敏感路径: {host_path}, fix: f移除 {host_path} 的hostPath挂载使用其他方式替代 }) return issues except Exception as e: logger.error(fPod安全审计异常: {e}, exc_infoTrue) return [{severity: error, issue: str(e)}]四、编排层安全三大Kubernetes漏洞漏洞七API Server未授权访问危险等级严重 |影响面Kubernetes集群的上帝权限漏洞描述Kubernetes API Server对外开放且未配置RBAC认证或使用默认的--anonymous-authtrue且绑定system:anonymous到高权限ClusterRole。攻击者可以列举所有Pod、删除Deployment、甚至创建特权容器。检测方法# 测试匿名访问预期返回403 kubectl get pods --token --certificate-authority \ --serverhttps://api-server:6443 21修复方案确保API Server启动参数包含--anonymous-authfalse使用RBAC最小权限原则启用审计日志监控可疑的API调用模式使用网络策略限制API Server的访问来源IP漏洞八RBAC权限过度授予危险等级高典型问题为方便开发调试将cluster-admin权限绑定到defaultServiceAccount或开发团队的所有成员。一旦某个Pod的ServiceAccount Token泄露攻击者获得整个集群的管理权限。检测方法# 查找具有cluster-admin权限的ServiceAccount kubectl get clusterrolebindings -o json | \ jq .items[] | select(.roleRef.namecluster-admin) | .subjects[] | select(.kindServiceAccount)修复方案遵循RBAC最小权限原则为每个服务创建专属的Role命名空间级而非ClusterRole集群级。漏洞九Secret明文存储危险等级高Kubernetes Secret默认以Base64编码存储不是加密任何人能读取etcd数据或通过kubectl get secret -o yaml即可获取原始值。base64 -d即可解码。修复方案启用etcd静态加密EncryptionConfiguration使用外部密钥管理工具Vault External Secrets Operator限制Secret的RBAC读取权限非所有ServiceAccount都能读取Secret# Kubernetes etcd静态加密配置 apiVersion: apiserver.config.k8s.io/v1 kind: EncryptionConfiguration resources: - resources: - secrets providers: - aescbc: keys: - name: key1 secret: base64-encoded-32-byte-key - identity: {} # 兜底明文存储仅用于迁移过渡期五、供应链安全镜像来源的可信性漏洞十未签名的镜像和不可信镜像源危险等级中-高漏洞描述从不可信的镜像仓库拉取镜像没有签名验证无法确认镜像在构建到部署之间是否被篡改。修复方案使用私有镜像仓库Harbor/ACR/ECR并配置镜像签名Cosign/Notary在Kubernetes中使用Admission Controller如Kyverno/OPA验证镜像签名配置imagePullPolicy: IfNotPresent避免每次都从远程拉取import logging from typing import Dict, List logger logging.getLogger(__name__) class ImageSupplyChainValidator: 镜像供应链安全验证器 # 受信任的镜像仓库白名单 TRUSTED_REGISTRIES [ harbor.internal.company.com, docker.io/library, # 仅限官方镜像 registry.k8s.io, ] def validate_image_source(self, image_name: str) - Dict: 验证镜像来源的可信性 Args: image_name: 完整镜像名如 harbor.company.com/app:v1.0 Returns: 验证结果 result { image: image_name, trusted: False, issues: [] } try: # 检查1是否使用了latest标签 if : not in image_name or image_name.endswith(:latest): result[issues].append({ severity: high, issue: 使用了latest标签无法确定具体版本, fix: 指定具体的版本号或镜像摘要(Digest) }) # 检查2是否来自受信任的Registry registry image_name.split(/)[0] if / in image_name else docker.io is_trusted any(registry.startswith(t) for t in self.TRUSTED_REGISTRIES) if not is_trusted: result[issues].append({ severity: high, issue: f镜像来自非信任Registry: {registry}, fix: f使用受信任的Registry: {, .join(self.TRUSTED_REGISTRIES)} }) else: result[trusted] True # 检查3是否包含摘要最安全的引用方式 if sha256: in image_name: result[trusted] True result[note] 使用Digest引用安全性最高 return result except Exception as e: logger.error(f镜像供应链验证异常: {e}) return {image: image_name, trusted: False, error: str(e)}五、总结Docker和Kubernetes安全的十大常见漏洞本质上反映了便利性优先于安全性的默认配置哲学。从镜像构建阶段的CVE和密钥泄露到运行时的特权容器和root用户再到编排层的API Server暴露和RBAC滥用每个漏洞都有明确的检测方法和修复方案。三条核心安全原则最小权限原则贯穿始终容器不应以root运行、不应具有特权模式、不应挂载Docker Socket、RBAC不应授予cluster-admin。从构建到运行每一步都问这个容器/用户真的需要这个权限吗安全左移到CI/CD Pipeline镜像扫描、密钥扫描、安全配置检查必须在代码提交阶段就自动执行阻断不合规的配置进入生产环境。等待部署后再发现安全问题代价是指数级的。持续安全监控不可忽视安全不是一次性检查而是持续监控。启用Kubernetes审计日志、部署Falco做运行时异常检测、定期执行安全基线扫描CIS Benchmark是保障长期安全的基本要求。下一步在CI/CD Pipeline中集成自动化的容器安全检查工具链TrivyTruffleHogKyverno实现不安全的镜像无法构建、不合规的配置无法部署的安全硬约束。

相关新闻

智能告警系统的常见失败模式:阈值漂移、基线失真与告警疲劳的根因分析与根治方案

智能告警系统的常见失败模式:阈值漂移、基线失真与告警疲劳的根因分析与根治方案

智能告警系统的常见失败模式:阈值漂移、基线失真与告警疲劳的根因分析与根治方案 一、告警系统的悖论 告警系统有一个残酷的悖论:告警越多,可靠性越低。当运维团队每天接收500条告警时,告警就变成了噪音——真正重要的P0告警被淹没…

2026/10/19 4:13:24 阅读更多 →
Linux性能调优中的十大致命误操作:从错误的内核参数调整到危险的sysctl永久化配置

Linux性能调优中的十大致命误操作:从错误的内核参数调整到危险的sysctl永久化配置

Linux性能调优中的十大致命误操作:从错误的内核参数调整到危险的sysctl永久化配置 一、误操作的代价:一个真实案例 在一次线上故障中,工程师为了"优化网络吞吐量",执行了以下命令: sysctl -w net.core.rm…

2026/10/18 8:12:41 阅读更多 →
碧蓝幻想Relink DPS分析工具:从新手到高手的完整指南

碧蓝幻想Relink DPS分析工具:从新手到高手的完整指南

碧蓝幻想Relink DPS分析工具:从新手到高手的完整指南 【免费下载链接】gbfr-logs GBFR Logs lets you track damage statistics with a nice overlay DPS meter for Granblue Fantasy: Relink. 项目地址: https://gitcode.com/gh_mirrors/gb/gbfr-logs 想要真…

2026/10/18 8:13:33 阅读更多 →

最新新闻

ObjectARX自定义实体开发:从绘制、夹点到对象捕捉的完整实现

ObjectARX自定义实体开发:从绘制、夹点到对象捕捉的完整实现

简介:ObjectARX自定义实体简单实例是一套面向AutoCAD二次开发者的C示例工程,聚焦ObjectARX自定义实体的核心开发流程。其中以一条自定义直线实体为主线,完整演示了实体类继承、DXF/DWG数据读写、worldDraw屏幕绘制、数据库注册以及扩展命令调…

2026/10/19 4:13:37 阅读更多 →
ObjectARX自定义实体实例:从AcDbEntity派生到CAD原生图元

ObjectARX自定义实体实例:从AcDbEntity派生到CAD原生图元

简介:ObjectARX自定义实体是AutoCAD二次开发中的核心环节,这份实例以创建简单直线实体为切入点,面向熟悉C和VC的CAD开发者,完整展示从项目初始化到实体注册的编码流程。资源压缩包共含70个文件,以头文件h、源文件cpp、…

2026/10/19 4:13:37 阅读更多 →
穿缝抓杯、拿瓶浇花:南洋理工团队让无人机从“会飞”走向“会干活”

穿缝抓杯、拿瓶浇花:南洋理工团队让无人机从“会飞”走向“会干活”

「打通空中机械臂完整任务链」 目录 01 机身也参与操作——QuadHand 的全身运动规划 一只“手”伸出去,整架飞机都要配合 用机器人自身的几何,判断离障碍还有多远 02 让连续技能学得出来——关键状态课程与视觉学生 关键状态课程&#xff1a…

2026/10/19 4:13:37 阅读更多 →
AI+OCR名片管理:一键将纸质名片结构化存入手机通讯录

AI+OCR名片管理:一键将纸质名片结构化存入手机通讯录

先把手从手机屏幕上挪开,说说我抽屉里的那些名片。做效率工具这些年,我给自己写过不少“一键搞定”的脚本,但真正让我觉得解决了大问题的,是这套名片管理方案:AIOCR,人脉一键存手机。简单说,就是…

2026/10/19 4:13:37 阅读更多 →
基于Stonefish的水下机器人仿真:传感器融合与定深控制实战

基于Stonefish的水下机器人仿真:传感器融合与定深控制实战

简介:这是一份基于Python与ROS Noetic的石鱼生态仿真项目资源包,面向研究海洋生物行为、机器人仿真及多智能体系统的开发者与学生。包内共223个文件,主体为205个obj三维模型(覆盖石鱼、锚链、岩石等场景物件)&#xff…

2026/10/19 4:13:37 阅读更多 →
open-code-review实战:把团队评审规范变成自动化规则引擎

open-code-review实战:把团队评审规范变成自动化规则引擎

最近接手了一个维护了两年多的老项目,团队 Review 慢慢变成了“LGTM 复读机”,CI 只查格式和单测,真正的问题全靠评审人肉眼硬扛。我试着把一个叫 open-code-review 的开源工具接进仓库,让机器人在每次 Push 和 Pull Request 上都…

2026/10/19 4:12:36 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介:本资源为电源技术方向的学术研究文档,聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略,面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 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/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址: https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集,共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 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/19 2:54:50 阅读更多 →
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/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练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/18 12:16:16 阅读更多 →