Skip to content

🔒 安全审计

对项目依赖执行安全审计,检测已知漏洞(CVE)与已放弃维护(abandoned)的包。

Composer Skills 把 composer audit 及其周边能力封装为一组方法,覆盖从「拿一份原始输出」到「结构化解析」再到「按严重性筛选高危漏洞」的完整链路。所有结构化方法都基于 composer audit --format=json,并自动处理审计发现漏洞时返回的非零退出码。

何时使用

  • 📦 CI/CD 流水线里在 composer install 之后跑一次审计,发现漏洞即阻断构建。
  • 🛠️ 运维巡检:定期扫描 composer.lock,确认生产依赖没有被披露新的 CVE。
  • 🧩 依赖治理:找出已放弃维护(abandoned)的包,提前规划替换。
  • ⚡ 应急响应:某 CVE 爆发后,快速判断当前项目是否受影响、受影响包的版本与严重性。

🔍 审计数据流

结构化返回类型

AuditResult

AuditWithJSON 返回,对应 composer audit --format=json 的顶层结构。

go
type AuditResult struct {
    Vulnerabilities []Vulnerability `json:"vulnerabilities"`
    Found           int             `json:"found"`
    Advisory        string          `json:"advisory,omitempty"`
    WithoutDev      bool            `json:"without-dev,omitempty"`
}
字段类型说明
Vulnerabilities[]Vulnerability发现的漏洞列表
Foundint漏洞总数
Advisorystring公告标识(可空)
WithoutDevbool是否排除了开发依赖

Vulnerability

单个漏洞条目,Abandoned=true 时表示该条目是「已放弃维护的包」而非传统 CVE。

go
type Vulnerability struct {
    Package     string   `json:"package"`
    Version     string   `json:"version"`
    Title       string   `json:"title"`
    Link        string   `json:"link"`
    CVE         []string `json:"cve,omitempty"`
    Advisory    string   `json:"advisory"`
    Abandoned   bool     `json:"abandoned,omitempty"`
    Severity    string   `json:"severity,omitempty"`
    Source      string   `json:"source,omitempty"`
    Affectedver string   `json:"affectedver,omitempty"`
}
字段类型说明
Packagestring受影响的包名
Versionstring当前安装版本
Titlestring漏洞标题
Linkstring详情链接
CVE[]string关联的 CVE 编号列表
Advisorystring公告标识
Abandonedbool是否为已放弃维护的包
Severitystring严重性:critical/high/medium/low
Sourcestring数据来源
Affectedverstring受影响版本范围

AuditInfoResult

GetAuditInfo / GetAuditInfoWithOptions 返回,提供更细粒度的公告信息。

go
type AuditAdvisoryInfo struct {
    PackageName string `json:"package"`
    Version     string `json:"version"`
    Title       string `json:"title"`
    Severity    string `json:"severity"` // "critical", "high", "medium", "low"
    CVE         string `json:"cve,omitempty"`
    Link        string `json:"link,omitempty"`
    ReportedAt  string `json:"reportedAt,omitempty"`
}

type AuditInfoResult struct {
    Advisories []AuditAdvisoryInfo `json:"advisories"`
    Count      int                 `json:"count,omitempty"`
}

两种结构化结果的区别

AuditResult(来自 AuditWithJSON)直接映射 Composer 的原始 JSON,含 abandoned 标记;AuditInfoResult(来自 GetAuditInfo)是 SDK 层做的归一化封装,字段名更规整(如 PackageName),并在解析时自动填充 Count。需要判断「是否含已放弃包」用前者,需要遍历公告做告警分发用后者。


Audit

🔒 执行安全审计,返回原始文本输出。

签名

go
func (c *Composer) Audit() (string, error)

参数

无。

返回值

类型说明
输出stringcomposer audit 的标准输出
错误error执行失败时返回;发现漏洞时 Composer 返回非零退出码也会以 error 形式返回

示例

go
package main

import (
    "fmt"
    "log"

    "github.com/scagogogo/composer-skills/pkg/composer"
)

func main() {
    comp, err := composer.New(composer.DefaultOptions())
    if err != nil {
        log.Fatalf("初始化失败: %v", err)
    }

    output, err := comp.Audit()
    if err != nil {
        log.Fatalf("执行安全审计失败: %v", err)
    }
    fmt.Println("安全审计结果:", output)
}

AuditWithJSON

🔒 执行安全审计并返回结构化 JSON 结果。

签名

go
func (c *Composer) AuditWithJSON() (*AuditResult, error)

参数

无。

返回值

类型说明
结果*AuditResult解析后的审计结果,含漏洞列表与计数
错误error执行或 JSON 解析失败时返回

示例

go
result, err := comp.AuditWithJSON()
if err != nil {
    log.Fatalf("执行安全审计失败: %v", err)
}
fmt.Printf("发现 %d 个漏洞\n", result.Found)
for _, vuln := range result.Vulnerabilities {
    fmt.Printf("漏洞: %s %s\n", vuln.Package, vuln.Title)
    fmt.Printf("严重性: %s\n", vuln.Severity)
    fmt.Printf("详情: %s\n\n", vuln.Link)
}

AuditWithoutDev

🔒 仅审计生产依赖,排除开发依赖(require-dev)。

签名

go
func (c *Composer) AuditWithoutDev() (string, error)

参数

无。

返回值

类型说明
输出stringcomposer audit --no-dev 的输出
错误error执行失败时返回

示例

go
output, err := comp.AuditWithoutDev()
if err != nil {
    log.Fatalf("执行安全审计失败: %v", err)
}
fmt.Println("生产环境依赖安全审计结果:", output)

等价命令

composer audit --no-dev。生产环境通常不部署开发依赖,审计生产依赖即可反映真实风险面。


AuditWithFormat

🔒 以指定格式输出审计结果。

签名

go
func (c *Composer) AuditWithFormat(format string) (string, error)

参数

参数类型说明
formatstring输出格式,例如 jsontableplain

返回值

类型说明
输出stringcomposer audit --format=FORMAT 的输出
错误error执行失败时返回

示例

go
// 以表格形式输出
output, err := comp.AuditWithFormat("table")
if err != nil {
    log.Fatalf("执行安全审计失败: %v", err)
}
fmt.Println(output)

// 以纯文本形式输出
output, err = comp.AuditWithFormat("plain")
if err != nil {
    log.Fatalf("执行安全审计失败: %v", err)
}
fmt.Println(output)

HasVulnerabilities

🔒 快速判断项目是否存在任何安全漏洞。

签名

go
func (c *Composer) HasVulnerabilities() (bool, error)

参数

无。

返回值

类型说明
是否有漏洞booltrue 表示存在漏洞
错误error检查过程发生非预期错误时返回

实现说明

内部调用 AuditWithJSON,并依据 result.Found > 0 判断。当 Composer 因发现漏洞返回非零退出码时,会检查错误信息是否包含 Foundvulnerabilities 关键字,若是则同样认定为「有漏洞」而不向上抛错。

示例

go
hasVulns, err := comp.HasVulnerabilities()
if err != nil {
    log.Fatalf("检查漏洞失败: %v", err)
}
if hasVulns {
    fmt.Println("警告: 项目中存在安全漏洞!")
} else {
    fmt.Println("项目中未发现安全漏洞。")
}

GetHighSeverityVulnerabilities

🔒 筛选出严重性为 highcritical 的高危漏洞,便于优先修复。

签名

go
func (c *Composer) GetHighSeverityVulnerabilities() ([]Vulnerability, error)

参数

无。

返回值

类型说明
高危漏洞[]VulnerabilitySeverityhighcritical 的漏洞列表,无则为空切片
错误error审计或解析失败时返回

示例

go
highVulns, err := comp.GetHighSeverityVulnerabilities()
if err != nil {
    log.Fatalf("获取高危漏洞失败: %v", err)
}
if len(highVulns) > 0 {
    fmt.Printf("发现 %d 个高危漏洞:\n", len(highVulns))
    for _, vuln := range highVulns {
        fmt.Printf("包: %s 版本: %s\n", vuln.Package, vuln.Version)
        fmt.Printf("漏洞: %s\n", vuln.Title)
        fmt.Printf("详情: %s\n\n", vuln.Link)
    }
} else {
    fmt.Println("未发现高危漏洞。")
}

AuditLock

🔒 审计指定的 composer.lock 文件,可用于尚未安装依赖的项目。

签名

go
func (c *Composer) AuditLock(lockFilePath string) (string, error)

参数

参数类型说明
lockFilePathstringcomposer.lock 文件路径;传空字符串则审计当前目录的 lock 文件

返回值

类型说明
输出string审计输出
错误error执行失败时返回

示例

go
// 审计当前项目的 lock 文件
output, err := comp.AuditLock("")
if err != nil {
    log.Fatalf("审计 lock 文件失败: %v", err)
}
fmt.Println(output)

// 审计其他项目的 lock 文件
output, err = comp.AuditLock("/path/to/other/project/composer.lock")
if err != nil {
    log.Fatalf("审计 lock 文件失败: %v", err)
}
fmt.Println(output)

路径参数

lockFilePath 非空时,路径会作为位置参数直接传给 composer audit <path>,请确保路径正确且文件存在。


GetAbandonedPackages

🔒 获取已被标记为「已放弃维护」(abandoned)的包列表。

签名

go
func (c *Composer) GetAbandonedPackages() ([]Vulnerability, error)

参数

无。

返回值

类型说明
已放弃包[]VulnerabilityAbandoned=true 的条目列表,无则为空切片
错误error审计或解析失败时返回

示例

go
abandoned, err := comp.GetAbandonedPackages()
if err != nil {
    log.Fatalf("获取已放弃的包失败: %v", err)
}
if len(abandoned) > 0 {
    fmt.Printf("发现 %d 个已放弃维护的包:\n", len(abandoned))
    for _, pkg := range abandoned {
        fmt.Printf("包: %s 版本: %s\n", pkg.Package, pkg.Version)
        fmt.Printf("详情: %s\n\n", pkg.Link)
    }
    fmt.Println("建议替换这些包以避免潜在的安全风险。")
} else {
    fmt.Println("未发现已放弃维护的包。")
}

复用 Vulnerability 类型

已放弃的包并非传统漏洞,但 SDK 复用 Vulnerability 结构承载,通过 Abandoned 字段区分。遍历时如需分别处理,先判断该字段。


进阶

AuditWithOptions

需要组合多个审计标志时使用,提供最大灵活性。

go
func (c *Composer) AuditWithOptions(options map[string]string) (string, error)
参数类型说明
optionsmap[string]string选项映射,键为选项名,值为选项值(无值标志传空字符串)
go
options := map[string]string{
    "no-dev":  "",
    "format":  "json",
    "locked":  "",
}
output, err := comp.AuditWithOptions(options)
if err != nil {
    log.Fatalf("执行安全审计失败: %v", err)
}
fmt.Println(output)

GetAuditInfo / GetAuditInfoWithOptions

返回归一化的 AuditInfoResult,适合需要逐条公告做分发的场景(如向监控系统推送告警)。

go
func (c *Composer) GetAuditInfo() (*AuditInfoResult, error)
func (c *Composer) GetAuditInfoWithOptions(options map[string]string) (*AuditInfoResult, error)
go
result, err := comp.GetAuditInfo()
if err != nil {
    log.Fatalf("安全审计失败: %v", err)
}
for _, adv := range result.Advisories {
    fmt.Printf("漏洞: %s (%s) - %s\n", adv.PackageName, adv.Severity, adv.Title)
}

RunAudit

dependencies.go 中还提供了 RunAudit(),等价于 Audit(),可在依赖管理流程中成对调用。

🔍 相关方法

基于 MIT 许可证发布