近期消费者报告和国家安全局的出版物在开发圈引发了关于“安全”及其益处的大量讨论。
- 安全与保障:安全是在威胁模型内有意义的概念,代码在给定威胁模型下是安全的,即攻击者无法利用代码实现不可接受的风险;安全(宽泛定义)是攻击者不能让代码做不该做的事。安全与编程中的规范相关,在规范内代码按其规范行为,通常规范可定义为程序员对代码的某种信念,如注释、文档等。安全与保障相关,但有全安全无保障的程序和全保障无安全的程序。实现完全安全的代码是编程语言社区和形式方法社区的长期目标,但尚未达成,不过在追求此目标过程中,给我们带来了很多有价值的工具,如强静态类型系统、类型推断、文档编程、模型检查、合约、沙盒执行模型、内存安全执行、内存模型、别名分析、证明携带代码、自动垃圾回收、依赖类型、线性类型和仿射类型、区域资源管理、多阶段编译、骨架并发、消息传递并发、单元测试、集成测试、模糊测试、混沌测试、调试、时间旅行/反向调试、可读语法、标记/关键字参数、代码审查等。在不完美的世界中,追求安全和保障是有意义的,因为知道不能 100%成功不是接受不良结果的借口。
- 编程语言:安全编程语言是有助于开发者编写安全代码(相对于规范/不变量)的语言,目前没有语言是绝对安全的,不同语言在不同规范和威胁模型下的安全性不同,如 C 语言容易破坏写安全、读安全和线程安全;C++在某些方面比 C 语言更难破坏写安全,但仍存在多种破坏方式;Python 容易破坏写安全,隔离写安全子集较难;JavaScript 有私域字段后破坏写安全较难,隔离写安全子集可行但需抛弃现有生态;TypeScript 与 JavaScript 情况类似;Ruby 情况与 JavaScript 相似;Java、Kotlin、C#等语言在写安全、读安全和线程安全方面有一定保障,但也存在破坏方式;Rust 提供了较好的写安全和读安全基线,隔离写安全和读安全子集相对容易,但仍需避免使用
unsafe代码,隔离线程安全子集可行但会限制并发能力。 - 分类安全:常见的安全类型有内存安全、类型安全、数据竞争安全和线程安全等,这些安全类型可简化为写安全和读安全,破坏读写安全意味着破坏不变量,可能引入错误或漏洞。不同语言在这些安全类型上表现不同,如 C 语言在各安全类型上都较易被破坏,Rust 在写安全和读安全方面有较好的保障。
- 统计数据:研究表明,超过 70%的微软、谷歌和苹果发现的安全漏洞是由于破坏写安全导致的,这些开发团队采取了大量预防措施仍频繁失败,这是安全和保障问题。Mozilla 已决定从 C++逐步转向 Rust,谷歌和微软也在投资 Rust 等语言,这表明这些公司认为在某些任务中 Rust 更优,但不能绝对地说 Rust 是最安全的语言。还有研究通过观察编程语言的 bug 修复提交与非 bug 修复提交比例来研究语言的安全性,不同语言在该研究中的表现不同,但结论难以确定。
总之,选择语言应根据目标、规范和威胁模型,各语言在安全方面各有特点,应共同努力提高代码的安全性。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。