gog drive audit 实战:用只读命令审计 Google Drive 共享与权限风险
gog drive audit 实战用只读命令审计 Google Drive 共享与权限风险【免费下载链接】gogcliGoogle Workspace in your terminal.项目地址: https://gitcode.com/GitHub_Trending/gogcl/gogcli导读gog drive audit是 gog CLI 内置的一组只读审计命令用于在终端中对 Google Drive 的共享与权限进行安全盘点发现公开链接anyone-with-link、外部域授权、越权授予等风险项同时保证不产生任何变更。本文基于仓库中的 Agent 技能文档 .agents/skills/gog-drive-audit/SKILL.md结合internal/cmd/drive_audit.go源码、生成的命令文档与安全配置文件完整讲解 audit 命令的参数、分类逻辑、输出格式以及审计不改权限、修复走 dry-run的安全实践。读完你将能够为任意账号执行有界、可复现的 Drive 共享审计并把审计结果接入自动化脚本或 Agent 工作流。审计的前提先读基础技能与安全规则gog drive audit属于 gog 的 Drive 命令族使用前建议先阅读两份前置技能文档.agents/skills/gog/SKILL.md共享的认证、输出、安全、写入规则与 .agents/skills/gog-drive/SKILL.mdDrive 命令总览。其中与审计直接相关的核心规则如下显式选择账号所有 API 操作都通过--account userexample.com显式指定账号不依赖隐式默认只读边界任务不应修改 Google 数据时一律加--readonly该标志会在运行时阻止所有 mutating API 请求非交互自动化场景加--no-input让认证或 keyring 提示直接失败而非挂起等待机器可读输出读取 Google 内容优先使用--json --wrap-untrusted把获取的文本字段包进外部不可信内容标记便于 Agent 安全解析人类提示与进度信息走 stderrstdout 只输出数据退出码稳定schema与--help暴露命令语法、稳定退出码与生效的安全状态自动化前可先用gog schema drive --json校验命令契约。安全配置层面仓库的 safety-profiles/readonly.yaml 在drive:段明确将permissions: true读取允许而share: false、unshare: false、delete: false、move: false等写入类操作全部禁止——这正是审计命令可以放心运行的环境前提审计本身只读而改权限永远被安全档位拦在门外。两条审计命令sharing 与 user从命令入口 internal/cmd/drive_audit.go 可以看到gog drive audit下挂两个子命令type DriveAuditCmd struct { Sharing DriveAuditSharingCmd cmd: name:sharing aliases:permissions,perms,public,external help:Find public or external Drive permissions User DriveAuditUserCmd cmd: name:user help:Find Drive permissions granted to a user }gog drive audit sharing别名permissions、perms、public、external扫描目录树找出公开或外部权限gog drive audit user user扫描目录树找出授予指定用户的权限。两个命令都会遍历文件树、逐一读取权限列表但只做查询与输出不产生任何修改。命令一audit sharing——发现公开与外部共享技能文档给出的三条核心审计命令gog --account userexample.com --readonly drive audit sharing --max 200 --json --wrap-untrusted gog --account userexample.com --readonly drive audit sharing --internal-domain example.com \ --max 200 --json --wrap-untrusted gog --account userexample.com --readonly drive audit user personexample.com --max 200 \ --json --wrap-untrustedaudit sharing的完整参数见生成的命令文档 docs/commands/gog-drive-audit-sharing.md与源码DriveAuditSharingCmd字段一一对应参数类型默认值说明--file/--file-idstring—只审计单个文件 ID替代目录树扫描--parentstring根目录指定要扫描的文件夹 ID--depthint2最大文件夹深度0表示不限制--maxint500最多扫描的文件/文件夹数量0表示不限制--internal-domain[]string账号邮箱域名视为内部域的域名可重复传入也支持逗号分隔--public-onlyboolfalse只报告 anyone-with-link / 公开权限--external-onlyboolfalse只报告外部 user/group/domain 权限--all-drivesbooltrue是否包含共享云端硬盘用--no-all-drives只查 My Drive--fail-foundboolfalse存在发现项时以退出码 3 结束几点值得注意--public-only与--external-only互斥源码Run中会显式校验并报错--public-only cannot be combined with --external-only--depth与--max都有边界校验validateDriveScanBounds要求均大于等于 0对应的测试用例在 internal/cmd/drive_validation_more_test.go如audit sharing max、audit sharing depth、audit user max、audit user depth默认--depth 2、--max 500是为了让扫描有界——技能文档强调运行有界、只读的盘点命令bounded, read-only inventory避免在大型网盘上产生失控的 API 调用。内部域判定与外部权限识别--internal-domain决定哪些域算内部。源码normalizeInternalDomains的逻辑是若未显式传入则默认取--account邮箱的后缀域名例如userexample.com→example.com并对所有域做小写、去首尾空格与点号的归一化。真正的分类逻辑在driveSharingFinding与isExternalDrivePermissioninternal/cmd/drive_audit.gofunc driveSharingFinding(item driveTreeItem, perm *drive.Permission, internalDomains map[string]struct{}) (driveSharingAuditFinding, bool) { reasons : make([]string, 0, 2) if perm.Type driveShareToAnyone { // anyone reasons append(reasons, public) } if isExternalDrivePermission(perm, internalDomains) { reasons append(reasons, external) } ... }权限类型为anyone公开链接→ 归为publicuser/group类型取授权对象的邮箱域名若不在内部域列表内 → 归为externaldomain类型取权限上的domain字段若不在内部域列表内 → 归为external两者都不命中则不构成发现项直接跳过。也就是说一条权限可以同时命中 public 与 external 两个原因例如公开链接且域为外部域reasons数组会同时记录输出阶段对public与external的分类过滤正是基于hasReason判断。权限本身的读取通过Permissions.List完成listDrivePermissionsForAudit每页 100 条并跟随nextPageToken翻页请求字段包含id,type,role,emailAddress,domain,displayName,allowFileDiscovery,deleted,expirationTime,permissionDetails(permissionType,role,inherited,inheritedFrom)其中permissionDetails用于记录权限是否继承自父文件夹inherited以及继承来源inheritedFrom这对后续识别陈旧直授stale-looking direct grants很有价值。命令二audit user——排查某个用户拿到的一切权限gog drive audit user personexample.com用于回答这个人对我网盘里的哪些文件有权限。参数见 docs/commands/gog-drive-audit-user.md与源码DriveAuditUserCmd对应user为必选位置参数其余--file/--parent/--depth/--max/--all-drives/--fail-found与 sharing 命令一致。实现上DriveAuditUserCmd.Run它对目标邮箱做小写与去空白归一化遍历扫描到的每个文件读取权限列表后只保留emailAddress与目标一致的权限原因标记为[user]。因此该命令不受内部/外部域概念影响——不管授予者是本域还是外域只要授权对象是personexample.com就会被列出。输出TSV 表格与 JSON 两种形态表格输出非 JSON 模式下--json未开启sharing 审计输出 TSV 表格表头为PATH REASONS TYPE ROLE TARGET PERMISSION_IDPATH文件在目录树中的路径无路径时回退为文件名REASONSpublic/external逗号分隔TYPE权限类型user/group/domain/anyoneROLE权限角色。结合 internal/cmd/drive_sharing.go 中的常量Drive 权限角色为reader查看、writer编辑、commenter查看评论TARGET优先展示邮箱其次域名、显示名都没有则显示-PERMISSION_ID权限 ID可用于后续精确的权限变更操作。结果按PATH排序同路径下按PERMISSION_ID排序sortDriveSharingFindings。没有发现项时人类可读模式输出No public or external permissions found若扫描因--max限制被截断会提示Results truncated; increase --max to scan more.。JSON 输出配合--jsonsharing 审计输出结构化结果{ findings: [ { fileId: …, fileName: …, path: …, mimeType: …, webViewLink: …, ownerEmails: […], permissionId: …, permissionType: user, role: writer, email: personexample.com, domain: …, displayName: …, allowFileDiscovery: false, deleted: false, expirationTime: …, reasons: [external], inherited: true, permissionDetails: {permissionType: …, role: …, inheritedFrom: …} } ], findingCount: 1, scannedFileCount: 500, internalDomains: [example.com], truncated: false }user 审计的 JSON 结构类似区别在于固定返回user: 目标邮箱而不是internalDomains。字段定义见源码中的driveSharingAuditFinding结构体internal/cmd/drive_audit.go包含文件 ID、名称、路径、MIME 类型、Web 查看链接、所有者邮箱、权限 ID/类型/角色、授权对象邮箱/域/显示名、allowFileDiscovery是否允许在搜索中发现、deleted授权对象是否已删除、expirationTime权限过期时间以及reasons分类原因。findingCount、scannedFileCount、truncated三个字段让脚本可以快速判断扫描是否完整truncated、覆盖面多大scannedFileCount、风险项多少findingCount。--fail-found把审计接入 CI 的退出码--fail-found让命令在存在发现项时以退出码3结束。实现在 internal/cmd/paging.goconst emptyResultsExitCode 3 func failEmptyExit(failEmpty bool) error { if !failEmpty { return nil } return ExitError{Code: emptyResultsExitCode, Err: nil} }这意味着你可以把审计命令直接作为 CI 或定时任务的检查步骤--fail-found下无风险项 退出 0发现风险项 退出 3无需再手工解析输出即可触发告警或修复流程。gog schema提供机器可读的命令契约可用于在自动化之前确认这类语义。如何分类与呈现审计发现技能文档要求对审计结果按以下类别分别归类并在输出中包含文件 ID、名称、所有者、权限与证据evidence公开链接public linksreasons含public的 anyone 权限外部域授权external-domain grantsreasons含external且类型为 user/group/domain 的授权广泛的域授权broad domain grants类型为domain、授予整个内部域或外部域的权限——注意即使是内部域授权如果授予面过宽比如整个example.com都能访问某机密文件也应在报告中单独标注疑似陈旧的直接授权stale-looking direct grants结合deleted授权对象已删除、expirationTime无过期时间或已过期、inherited/inheritedFrom权限继承关系等字段判断deleted: true或长期无expirationTime的直接授权是典型清理对象所有权异常ownership anomaliesownerEmails中出现的非预期所有者例如个人文件出现在团队网盘、所有者邮箱与账号域不符等。对于 Agent 或脚本消费--json输出天然支持这些分类reasons字段区分 public/externalpermissionType/role/email/domain提供授权对象细节permissionDetails.inheritedFrom与deleted、expirationTime则支撑陈旧授权与继承关系分析。人读场景下--plainTSV 稳定输出也足够干净、可解析。审计铁律不改权限修复必须 dry-run技能文档明确了两条纪律这也是安全配置与实现共同保证的审计过程中绝不修改权限。audit命令从设计上就是只读的只调用Files.Get与Permissions.List没有任何写路径配合--readonly标志运行时层面也会拦截 mutating 请求。这也是 safety-profiles/readonly.yaml 中drive.share: false、drive.unshare: false的原因——只读档位下连改权限的入口都不存在。修复需要独立、可复核的计划且任何写操作先走--dry-run。即审计报告与修复动作必须分离先产出审计结果再单独提出修复方案对每一个被批准的变更先执行 dry-run 预览确认无误后才真正写入。gog 的 Drive 权限相关写命令同样支持这一工作流均位于gog drive命令族.agents/skills/gog-drive/SKILL.mdgog drive share fileId --to user|domain|anyone --role reader|writer|commenter共享写gog drive unshare fileId ...移除某条权限gog drive bulk remove-public批量移除 anyone 公开权限internal/cmd/drive_bulk.go内部先经过dryRunExit输出预期的动作gog drive bulk update-role批量调整权限角色同样支持 dry-rungog drive permissions列出单文件权限。典型的安全修复流程可以组织为# 1. 审计只读产出报告 gog --account userexample.com --readonly drive audit sharing --internal-domain example.com \ --max 200 --json --wrap-untrusted audit.json # 2. 针对报告逐项评估形成修复清单如移除 3 个公开权限 # 3. 对每个修复动作先 dry-run 预览 gog --account userexample.com drive unshare fileId --permission-id permissionId --dry-run # 4. 用户批准后去掉 --dry-run 执行真实写入 gog --account userexample.com drive unshare fileId --permission-id permissionId注意任何写命令都不应在未获用户明确批准时执行同时确保写操作保留在用户授权的账号与对象范围内这正是 .agents/skills/gog/SKILL.md 中Identify the account, object id, and exact mutation原则的体现。把审计接入 Agent 与自动化gog drive audit是仓库 Agent 技能体系中的一环专为只读审计场景设计。在 Agent 或脚本中使用时推荐组合gog --account userexample.com --readonly --no-input drive audit sharing \ --internal-domain example.com --max 200 --json --wrap-untrusted --fail-found--readonly强制只读边界即使误发写请求也会被拦截--no-input认证/keyring 问题直接失败不会卡住无人值守任务--json --wrap-untrusted机器可读且对外部内容做不可信标记避免注入式误导--fail-found有发现即退出码 3可被调度器捕获。更严格的场景可直接使用按 docs/safety-profiles.md 构建的只读二进制例如readonly安全档位构建的gog-readonly从二进制层面确保审计脚本只能读取、不能写入。需要更多命令级安全约束时还可以通过--enable-commands/--disable-commands把 CLI 限定到drive.audit等白名单范围见 .agents/skills/gog/SKILL.md 中的运行时命令守卫示例。关键源码与文档速查Agent 技能文档.agents/skills/gog-drive-audit/SKILL.md本文主题文档审计实现internal/cmd/drive_audit.go命令结构、分类逻辑、JSON 输出字段权限角色与共享参数internal/cmd/drive_sharing.go扫描边界校验与退出码internal/cmd/drive_reporting.go、internal/cmd/paging.go参数校验测试internal/cmd/drive_validation_more_test.go生成命令文档docs/commands/gog-drive-audit.md、docs/commands/gog-drive-audit-sharing.md、docs/commands/gog-drive-audit-user.md只读安全档位safety-profiles/readonly.yaml批量权限修复入口internal/cmd/drive_bulk.go小结gog drive audit把 Google Drive 共享审计收敛为两条只读命令sharing负责公共与外部风险的全网盘扫描user负责单用户的权限追溯二者都支持有界的--depth/--max扫描、TSV/JSON 双形态输出、--internal-domain内部域判定与--fail-found的 CI 退出码。审计本身绝不改权限修复动作则以独立计划 --dry-run预览的方式与审计严格分离。这套设计让安全审计既可以由运维在终端手工执行也可以被 Agent 和自动化流水线可靠地调度——这正是它作为 Agent 技能被沉淀进仓库的原因。【免费下载链接】gogcliGoogle Workspace in your terminal.项目地址: https://gitcode.com/GitHub_Trending/gogcl/gogcli创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考