静态分析SAST应用安全漏洞扫描代码质量【免费下载链接】codeqlCodeQL: the libraries and queries that power security researchers around the world, as well as code scanning in GitHub Advanced Security项目地址https://gitcode.com/gh_mirrors/co/codeql点击查看免费下载本篇技术指南聚焦 CodeQL 仓库中 C# 分析库Modifiable类的三个可见性谓词——isEffectivelyPrivate、isEffectivelyInternal与isEffectivelyPublic。这一组谓词曾在 2021-06-15 的变更说明csharp/old-change-notes/2021-06-15-effective-visibility.md中宣告重做核心目的是正确处理 C# 的private protected、internal protected组合可见性以及显式接口实现成员的可见性。读完本文你将理解有效可见性effective visibility与声明可见性的区别、三个谓词的判定规则与实现细节以及如何通过测试用例验证这些规则从而在你的自定义查询中准确过滤掉实际上不可从当前程序集外部访问的成员。变更背景从声明修饰符到有效可见性在 C# 中一个成员的实际可访问范围并不总是与它声明的访问修饰符一一对应。典型例子包括嵌套类型中的成员一个声明为public的成员如果它所在的类型本身是internal或private那么该成员实际上不可能被程序集外部引用受保护成员的可重写性protected成员虽然可以被派生类访问但private protected与protected internal在跨程序集场景下行为不同显式接口实现void I.Foo() { }这样的成员没有普通意义上的可见性它只能通过接口引用访问因此其有效可见性取决于被实现的接口本身。为此CodeQL 的 C# 库在 csharp/ql/lib/semmle/code/csharp/Member.qll 的Modifiable类中提供了三个有效可见性谓词回答的不是这个成员写了什么修饰符而是这个成员在程序语义上到底能被谁引用。谓词语义三个判定规则有效私有isEffectivelyPrivate在 Member.qll 中isEffectivelyPrivate()的定义为该声明只能从以下位置引用——声明它的类型及其嵌套类型与普通private一致以及它的封闭类型enclosing types。其实现包含三条判定路径predicate isEffectivelyPrivate() { this.isReallyPrivate() or this.getDeclaringType().(Modifiable).isReallyPrivate() or this.(Virtualizable).getExplicitlyImplementedInterface().isEffectivelyPrivate() }自身为私有isReallyPrivate()是一个私有辅助谓词要求isPrivate()且不是isProtected()同时排除极少数同名成员跨程序集以不同可见性定义的情况Member.qll封闭类型链私有this.getDeclaringType()沿声明类型逐级向上查找表示一个或多个步骤只要任一封闭类型真正私有成员即视为有效私有显式接口实现通过getExplicitlyImplementedInterface()取得显式实现的接口若接口本身有效私有则该实现成员同样有效私有。文档注释特别强调两点显式接口实现在接口本身有效私有时被视为有效私有而private protected成员不被视为有效私有因为它可以在声明程序集内被重写override。有效内部isEffectivelyInternalisEffectivelyInternal()的语义是该声明只能从声明它的程序集内部引用Member.qllpredicate isEffectivelyInternal() { this.isReallyInternal() or this.getDeclaringType().(Modifiable).isReallyInternal() or this.(Virtualizable).getExplicitlyImplementedInterface().isEffectivelyInternal() }其辅助谓词isReallyInternal()判定两条路径Member.qllinternal且非protected即普通internalprivate且protected即private protected——注意它与internal的可达范围相同都限于本程序集。同样需要排除同名成员跨程序集不同可见性的稀有情况。文档注释中的两个关键限定通过InternalsVisibleToAttribute声明的友元程序集friend assemblies不在考虑范围内——即只要理论上可能被其他程序集看到就归为有效内部之外internal protected即protected internal成员不被视为有效内部因为它可以在声明程序集之外被派生类重写显式接口实现成员若实现的接口本身有效内部则该成员同样被视为有效内部。有效公开isEffectivelyPublicisEffectivelyPublic()是一个兜底定义Member.qll凡不是有效私有、也不是有效内部的声明即可从程序集外部引用predicate isEffectivelyPublic() { not this.isEffectivelyPrivate() and not this.isEffectivelyInternal() }因此对任意Modifiable三个谓词构成穷尽且互斥的三分任何成员必然恰好落在有效私有有效内部有效公开之一。测试验证库测试 Modifiers仓库在 csharp/ql/test/library-tests/modifiers/ 提供了完整的库测试来锁定这些语义。被测代码Modifiers.csModifiers.cs 构造了覆盖各类修饰符组合的样例其中与本次重做直接相关的成员包括internal protected readonly int F3; // 内部保护字段 public int P1 { get; set; } // 公开属性 public int P2 { get; private set; } // 公开属性、私有 setter internal interface I2 { void M1(); } // 内部接口 public class C2 : I2 { void I2.M1() throw null; // 显式接口实现 protected private void M2() { } // private protected protected internal void M3() { } // internal protected }测试查询Effectively.qlEffectively.ql 专门用于本组谓词它找出三种声明可见性与有效可见性不一致的情况并标记实际的有效可见性from Modifiable m, string s where m.fromSource() and ( m.isEffectivelyInternal() and not m.isInternal() and s internal or m.isEffectivelyPrivate() and not m.isPrivate() and s private or m.isEffectivelyPublic() and s public ) select m, s即对每个源码中的声明若isEffectivelyInternal()成立但声明中并没有internal修饰符就报告为internal若isEffectivelyPrivate()成立但没有private修饰符报告为private凡有效公开者报告为public。预期结果Effectively.expected对照 Effectively.expected可以看到重做后的判定结果Modifiers.cs:12:14的M1注释标记的私有方法→internal因为其封闭类型C默认是internalunsafe class C无可见性修饰符默认为 internal成员随类型被限制在程序集内Modifiers.cs:24:22的C1被同时报告为internal与privatesealed class C1声明于internal类内其构造器C1()是public但随类型降至 internal而类本身随内部类 C 降至有效私有Modifiers.cs:52:19的Spublic struct→publicModifiers.cs:68:14的I2.M1内部接口的默认实现方法→internalModifiers.cs:73:17的显式接口实现void I2.M1()→internal这正是本次重做新增的判定——显式实现成员的可见性继承自被实现接口I2的可见性Modifiers.cs:75:32的protected private void M2()private protected→internal证明private protected被纳入有效内部而非有效私有Modifiers.cs:76:33的protected internal void M3()→public因为internal protected可以被程序集外的派生类重写故不归为有效内部。这些预期输出同时验证了重做后的三条核心规则显式接口实现的可见性跟随接口、private protected归入有效内部、internal protected归入有效公开。谓词在查询中的实际应用这一组谓词在仓库的多个查询与库模块中被广泛使用用于过滤从外部实际不可达的成员提升查询精度。csharp/ql/lib/semmle/code/csharp/telemetry/ExternalApi.qll在统计外部 API 使用情况时需要区分真正暴露给外部的成员与内部实现细节isEffectivelyPublic()等谓词正是判定的基础csharp/ql/src/Useless code/DefaultToStringQuery.qll、csharp/ql/src/Language Abuse/MissedReadonlyOpportunity.ql、csharp/ql/src/Likely Bugs/Collections/WriteOnlyContainer.ql这些查询在判断成员是否可被外部观察时使用有效可见性避免把仅程序集内部可见的成员当作公开 API 处理csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll 与 csharp/ql/src/utils/modeleditor/ModelEditor.qll模型生成工具需要按可见性决定是否为成员生成数据流模型csharp/ql/lib/semmle/code/csharp/dataflow/internal/Steps.qll、csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll数据流与派发分析中跨程序集边界的数据流需要以有效可见性为准private protected/internal protected的可重写性直接影响跨程序集调用图的构造。从源码结构看重做后的谓词通过统一收敛到isReallyPrivate/isReallyInternal两个私有辅助谓词并把封闭类型链与显式接口实现两类场景显式建模使得三个公开谓词在所有Modifiable声明上构成互斥且完备的划分任何后续查询只需选择其一即可得到精确的可见性分类。小结isEffectivelyPrivate、isEffectivelyInternal、isEffectivelyPublic是 CodeQL C# 库中关于成员可见性的核心抽象。2021-06-15 的重做补齐了三个此前处理不准确的场景private protected归入有效内部、internal protected因其可跨程序集重写而归入有效公开、以及显式接口实现可见性继承自被实现接口。理解这三条规则不仅有助于读懂ExternalApi、Dispatch等库模块的实现也能帮助你在编写自定义安全查询时正确判断一个成员是否真正暴露在程序集外部从而减少误报、提升分析的准确性。赞分享静态分析SAST应用安全漏洞扫描代码质量【免费下载链接】codeqlCodeQL: the libraries and queries that power security researchers around the world, as well as code scanning in GitHub Advanced Security项目地址https://gitcode.com/gh_mirrors/co/codeql点击查看免费下载相关推荐CodeQL C 溢出分析库 SimpleRangeAnalysisexprMightOverflow* 谓词如何变得更可靠CodeQL C 溢出分析库 SimpleRangeAnalysisexprMightOverflow 谓词如何变得更可靠 本文以 CodeQL C静态分析SAST应用安全漏洞扫描代码质量CodeQL C 库 0.0.10 新增特性Variable::isStructuredBinding 谓词详解CodeQL C 库 0.0.10 新增特性 Variable::isStructuredBinding 谓词详解 CodeQL 的 C 查询库在版本静态分析SAST应用安全漏洞扫描代码质量CodeQL C/C 查询库通过 Function 新谓词精确分析 virtual、override 与 final 声明CodeQL C/C 查询库通过 Function 新谓词精确分析 virtual、override 与 final 声明 导读 在编写 C 安全查询静态分析SAST应用安全漏洞扫描代码质量上一篇BadPods项目深度挖掘can-they.sh脚本实现集群令牌自动化审计下一篇javascript-mini-projects深度剖析从贪吃蛇游戏看Canvas API的实战应用创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?