|
| 1 | +--- |
| 2 | +title: Safe Update Specification |
| 3 | +description: Formal specification of safe update enforcement and manifest baselines in gh-aw compilation |
| 4 | +sidebar: |
| 5 | + order: 1366 |
| 6 | +--- |
| 7 | + |
| 8 | +# Safe Update Specification |
| 9 | + |
| 10 | +**Version**: 1.0.0 |
| 11 | +**Status**: Working Draft |
| 12 | +**Publication Date**: 2026-07-11 |
| 13 | +**Editor**: GitHub Agentic Workflows Team |
| 14 | +**This Version**: [safe-update-specification](/gh-aw/specs/safe-update-specification/) |
| 15 | +**Latest Published Version**: This document |
| 16 | + |
| 17 | +--- |
| 18 | + |
| 19 | +## Abstract |
| 20 | + |
| 21 | +This specification defines safe update behavior in GitHub Agentic Workflows (`gh-aw`) compilation. It standardizes when safe update enforcement is active, how baseline manifests are loaded and trusted, which secret/action/redirect/event changes require review, how warnings are surfaced, and how approval and strict-mode settings affect enforcement. |
| 22 | + |
| 23 | +## Status of This Document |
| 24 | + |
| 25 | +This is a working draft and may change. It describes behavior implemented in `pkg/workflow/` and exercised by `pkg/workflow/*safe_update*` and `pkg/cli/compile_safe_update_integration_test.go`. |
| 26 | + |
| 27 | +## Table of Contents |
| 28 | + |
| 29 | +1. [Introduction](#1-introduction) |
| 30 | +2. [Conformance](#2-conformance) |
| 31 | +3. [Safe Update Activation Model](#3-safe-update-activation-model) |
| 32 | +4. [Baseline Manifest Resolution and Trust](#4-baseline-manifest-resolution-and-trust) |
| 33 | +5. [Violation Detection Rules](#5-violation-detection-rules) |
| 34 | +6. [Compiler Output and Approval Flow](#6-compiler-output-and-approval-flow) |
| 35 | +7. [Manifest Format Requirements](#7-manifest-format-requirements) |
| 36 | +8. [Compliance Testing](#8-compliance-testing) |
| 37 | +9. [References](#9-references) |
| 38 | +10. [Change Log](#10-change-log) |
| 39 | + |
| 40 | +--- |
| 41 | + |
| 42 | +## 1. Introduction |
| 43 | + |
| 44 | +### 1.1 Purpose |
| 45 | + |
| 46 | +This document defines normative requirements for safe update enforcement during workflow compilation so that newly introduced security-sensitive changes are surfaced for review. |
| 47 | + |
| 48 | +### 1.2 Scope |
| 49 | + |
| 50 | +This specification covers: |
| 51 | + |
| 52 | +- safe update activation and disablement behavior |
| 53 | +- baseline manifest lookup precedence and trust guarantees |
| 54 | +- restricted secret and action change detection |
| 55 | +- redirect and event-trigger escalation detection |
| 56 | +- warning/prompt emission and approval workflow |
| 57 | +- `gh-aw-manifest` content used for future comparisons |
| 58 | + |
| 59 | +This specification does NOT cover runtime execution policy in GitHub Actions jobs. |
| 60 | + |
| 61 | +### 1.3 Design Goals |
| 62 | + |
| 63 | +Safe update enforcement is designed to preserve secure-by-default compilation while keeping compile output usable. The compiler SHALL produce actionable warnings and SHALL still generate lock files so subsequent compilations can compare against a baseline. |
| 64 | + |
| 65 | +--- |
| 66 | + |
| 67 | +## 2. Conformance |
| 68 | + |
| 69 | +### 2.1 Requirements Notation |
| 70 | + |
| 71 | +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt). |
| 72 | + |
| 73 | +### 2.2 Conformance Classes |
| 74 | + |
| 75 | +- **C1 (Compiler conformance)**: Correctly activates safe update mode, resolves trusted baseline manifests, detects violations, and emits required warnings. |
| 76 | +- **C2 (Manifest conformance)**: Emits parseable `gh-aw-manifest` metadata with deterministic normalization required for future safe update comparisons. |
| 77 | + |
| 78 | +--- |
| 79 | + |
| 80 | +## 3. Safe Update Activation Model |
| 81 | + |
| 82 | +### 3.1 Effective Safe Update Mode |
| 83 | + |
| 84 | +Safe update mode MUST be enabled whenever effective strict mode is enabled and approval is not granted. |
| 85 | + |
| 86 | +Effective strict mode MUST follow this precedence: |
| 87 | + |
| 88 | +1. CLI strict flag (enabled) |
| 89 | +2. Frontmatter `strict` boolean |
| 90 | +3. Default `true` when unspecified |
| 91 | + |
| 92 | +Safe update mode MUST be disabled when `--approve` is set, regardless of strict mode. |
| 93 | + |
| 94 | +### 3.2 Strict-Mode Coupling |
| 95 | + |
| 96 | +When frontmatter sets `strict: false`, safe update mode MUST be disabled and enforcement warnings MUST NOT be emitted. |
| 97 | + |
| 98 | +--- |
| 99 | + |
| 100 | +## 4. Baseline Manifest Resolution and Trust |
| 101 | + |
| 102 | +### 4.1 Resolution Order |
| 103 | + |
| 104 | +When safe update mode is enabled, baseline manifest lookup MUST use this precedence: |
| 105 | + |
| 106 | +1. Pre-cached prior manifest supplied by caller |
| 107 | +2. Existing lock file content from git `HEAD` |
| 108 | +3. Existing lock file content from filesystem |
| 109 | +4. Empty non-nil manifest when no lock file exists |
| 110 | + |
| 111 | +### 4.2 Legacy Lock Files |
| 112 | + |
| 113 | +If a lock file exists but has no `gh-aw-manifest`, enforcement MUST be skipped for that compilation and MUST NOT produce violation warnings from missing baseline data. |
| 114 | + |
| 115 | +### 4.3 Baseline Cache Stability |
| 116 | + |
| 117 | +When a non-nil baseline manifest is resolved, the compiler SHOULD retain that first trusted baseline for the current compiler instance and SHOULD NOT overwrite it with just-generated local results in subsequent compiles. |
| 118 | + |
| 119 | +--- |
| 120 | + |
| 121 | +## 5. Violation Detection Rules |
| 122 | + |
| 123 | +### 5.1 Secret Violations |
| 124 | + |
| 125 | +Secret names MUST be normalized by removing the `secrets.` prefix before comparison. |
| 126 | + |
| 127 | +The following secrets MUST always be allowed even when absent from prior manifest data: |
| 128 | + |
| 129 | +- `GITHUB_TOKEN` |
| 130 | +- `GH_AW_GITHUB_TOKEN` |
| 131 | +- `GH_AW_GITHUB_MCP_SERVER_TOKEN` |
| 132 | +- `GH_AW_AGENT_TOKEN` |
| 133 | +- `GH_AW_CI_TRIGGER_TOKEN` |
| 134 | +- `GH_AW_PROJECT_GITHUB_TOKEN` |
| 135 | +- `COPILOT_GITHUB_TOKEN` |
| 136 | + |
| 137 | +Any other normalized secret name not present in the baseline manifest MUST be reported as a violation. |
| 138 | + |
| 139 | +### 5.2 Action Violations |
| 140 | + |
| 141 | +Action comparison MUST use repository identity (owner/repo) as the key. Pin or version changes for an already approved repository MUST NOT be treated as violations. |
| 142 | + |
| 143 | +Compiler implementations MUST report: |
| 144 | + |
| 145 | +- added unapproved action repositories |
| 146 | +- removed previously approved action repositories |
| 147 | + |
| 148 | +The following repositories MUST be treated as trusted and MUST NOT generate add/remove violations: |
| 149 | + |
| 150 | +- `actions/*` |
| 151 | +- `github/gh-aw/actions/*` |
| 152 | +- `github/gh-aw-actions/*` |
| 153 | +- runtime-manager trusted repositories defined by compiler runtime mapping |
| 154 | + |
| 155 | +### 5.3 Redirect Violations |
| 156 | + |
| 157 | +Redirect values MUST be whitespace-trimmed before comparison. |
| 158 | + |
| 159 | +If redirect changes relative to baseline, the compiler MUST report: |
| 160 | + |
| 161 | +- newly added redirect |
| 162 | +- removed previously approved redirect |
| 163 | +- both signals when one redirect is replaced by another |
| 164 | + |
| 165 | +### 5.4 Event Escalation Violations |
| 166 | + |
| 167 | +The compiler MUST report a security escalation when baseline event presence indicates `pull_request` only, and current event presence indicates `pull_request_target` only. |
| 168 | + |
| 169 | +Adding `pull_request_target` while retaining `pull_request` MUST NOT be treated as an event escalation violation. |
| 170 | + |
| 171 | +--- |
| 172 | + |
| 173 | +## 6. Compiler Output and Approval Flow |
| 174 | + |
| 175 | +### 6.1 Warning-Only Enforcement |
| 176 | + |
| 177 | +Safe update violations MUST be emitted as warnings, not hard compilation failures. Compilation MUST continue, and lock output SHOULD still be written. |
| 178 | + |
| 179 | +### 6.2 Warning Content |
| 180 | + |
| 181 | +Violation output MUST include: |
| 182 | + |
| 183 | +- grouped violation details (secrets, added/removed actions, redirect changes, event escalation) |
| 184 | +- remediation guidance that includes approval and revert options |
| 185 | + |
| 186 | +A security-review prompt SHOULD instruct calling agents to review the flagged changes and include a review note in pull request descriptions. |
| 187 | + |
| 188 | +### 6.3 Approval Behavior |
| 189 | + |
| 190 | +When `--approve` is provided, safe update enforcement MUST be skipped for that compile invocation. |
| 191 | + |
| 192 | +### 6.4 First-Compile Baseline Establishment |
| 193 | + |
| 194 | +For workflows with no prior lock file, compilers MUST compare against an empty non-nil baseline, surface new restricted changes as warnings, and emit a lock file with `gh-aw-manifest` so future compiles have baseline state. |
| 195 | + |
| 196 | +--- |
| 197 | + |
| 198 | +## 7. Manifest Format Requirements |
| 199 | + |
| 200 | +### 7.1 Manifest Header |
| 201 | + |
| 202 | +Compiled lock files MUST embed a single-line JSON manifest comment in header form: |
| 203 | + |
| 204 | +- `# gh-aw-manifest: { ... }` |
| 205 | + |
| 206 | +### 7.2 Required and Optional Fields |
| 207 | + |
| 208 | +Manifest payloads MUST include `version`, `secrets`, and `actions`. Implementations MAY include additional fields such as skills, resolution failures, containers, redirect metadata, and pull request event presence flags. |
| 209 | + |
| 210 | +### 7.3 Normalization and Determinism |
| 211 | + |
| 212 | +Manifest generation MUST normalize and deduplicate secret/action data and SHOULD sort entries for deterministic output. |
| 213 | + |
| 214 | +### 7.4 Transitive Coverage |
| 215 | + |
| 216 | +Manifest content used by safe update comparisons SHOULD reflect secrets and actions contributed by imported and transitively imported workflow files. |
| 217 | + |
| 218 | +--- |
| 219 | + |
| 220 | +## 8. Compliance Testing |
| 221 | + |
| 222 | +### 8.1 Required Tests |
| 223 | + |
| 224 | +- **T-SU-001**: Safe update enabled when strict mode is effective and `--approve` is not set |
| 225 | +- **T-SU-002**: `strict: false` disables safe update warnings |
| 226 | +- **T-SU-003**: `--approve` disables safe update enforcement regardless of strict mode |
| 227 | +- **T-SU-004**: Baseline resolution order follows prior-manifest cache → HEAD lock → filesystem lock → empty baseline |
| 228 | +- **T-SU-005**: Legacy lock file without `gh-aw-manifest` skips enforcement |
| 229 | +- **T-SU-006**: New non-allowlisted secrets are reported; `GITHUB_TOKEN` and internal secrets are exempt |
| 230 | +- **T-SU-007**: Action add/remove detection is repo-based; pin changes do not violate |
| 231 | +- **T-SU-008**: Trusted action repos are exempt from add/remove violations |
| 232 | +- **T-SU-009**: Redirect add/remove/change violations are reported after trim normalization |
| 233 | +- **T-SU-010**: `pull_request` → `pull_request_target` conversion is reported as escalation |
| 234 | +- **T-SU-011**: Violations are emitted as warnings while compilation still succeeds |
| 235 | +- **T-SU-012**: First compile emits warning and writes baseline manifest |
| 236 | +- **T-SU-013**: Manifest includes data from imported/transitively imported workflow content |
| 237 | + |
| 238 | +### 8.2 Compliance Checklist |
| 239 | + |
| 240 | +| Requirement | Test ID | Level | Status | |
| 241 | +|---|---|---|---| |
| 242 | +| Safe update activation/deactivation rules | T-SU-001, T-SU-002, T-SU-003 | C1 | Required | |
| 243 | +| Baseline trust and legacy compatibility | T-SU-004, T-SU-005 | C1 | Required | |
| 244 | +| Secret and action violation detection | T-SU-006, T-SU-007, T-SU-008 | C1/C2 | Required | |
| 245 | +| Redirect and trigger escalation detection | T-SU-009, T-SU-010 | C1 | Required | |
| 246 | +| Warning-only enforcement and baseline creation | T-SU-011, T-SU-012 | C1 | Required | |
| 247 | +| Manifest completeness for imports | T-SU-013 | C2 | Required | |
| 248 | + |
| 249 | +--- |
| 250 | + |
| 251 | +## 9. References |
| 252 | + |
| 253 | +### Normative References |
| 254 | + |
| 255 | +- [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt) |
| 256 | +- `pkg/workflow/compiler.go` |
| 257 | +- `pkg/workflow/compiler_yaml.go` |
| 258 | +- `pkg/workflow/safe_update_enforcement.go` |
| 259 | +- `pkg/workflow/safe_update_manifest.go` |
| 260 | +- `pkg/workflow/compiler_types.go` |
| 261 | + |
| 262 | +### Informative References |
| 263 | + |
| 264 | +- `pkg/workflow/safe_update_enforcement_test.go` |
| 265 | +- `pkg/cli/compile_safe_update_integration_test.go` |
| 266 | +- `/gh-aw/setup/cli/` |
| 267 | + |
| 268 | +--- |
| 269 | + |
| 270 | +## 10. Change Log |
| 271 | + |
| 272 | +### Version 1.0.0 (Working Draft) |
| 273 | + |
| 274 | +- Initial safe update specification |
| 275 | +- Defined strict/approve activation semantics and baseline lookup precedence |
| 276 | +- Defined normative violation categories for secrets, actions, redirect changes, and trigger escalation |
| 277 | +- Defined warning-only compiler behavior and manifest conformance requirements |
0 commit comments