From 8717a1132772391ffd08b28de17eeed323d4bca3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 16 May 2026 03:33:31 +0000 Subject: [PATCH] spec: add CTR-017 Secret Leakage via Env Vars and CTR-018 Version Integrity Bypass Two implemented security validation rules were missing from the compiler threat detection specification: - CTR-017 Secret Leakage via Environment Variables: covers strict_mode_env_validation.go (validateEnvSecrets) and strict_mode_steps_validation.go (validateStepsSecrets), which detect secrets expressions in env:, engine.env, and uncontrolled step fields that would expose secrets to the agent container. - CTR-018 Version Integrity Bypass: covers update_check_validation.go (validateUpdateCheck), which warns/rejects when check-for-updates: false disables the compile-agentic version update check. Also adds T-CTR-017 and T-CTR-018 test ID entries in Section 7.1, extends the Section 6.1 implementation mapping table, updates the mapping audit note, bumps spec version to 1.0.8, and adds change-log entries for 1.0.7 and 1.0.8. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- specs/compiler-threat-detection-spec.md | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/specs/compiler-threat-detection-spec.md b/specs/compiler-threat-detection-spec.md index 7cf727722c4..d4f36152950 100644 --- a/specs/compiler-threat-detection-spec.md +++ b/specs/compiler-threat-detection-spec.md @@ -7,7 +7,7 @@ sidebar: # GitHub Actions Compiler Threat Detection Specification -**Version**: 1.0.6 +**Version**: 1.0.8 **Status**: Candidate Recommendation **Latest Version**: https://github.com/github/gh-aw/blob/main/specs/compiler-threat-detection-spec.md **Editors**: GitHub Next (GitHub, Inc.) @@ -24,7 +24,7 @@ This specification is the source of truth for detection rule coverage, implement This is a Candidate Recommendation specification. It may be revised based on operational evidence, threat-model updates, and conformance results. -**Publication Date**: May 15, 2026 +**Publication Date**: May 16, 2026 **Governance**: This specification is maintained by the gh-aw maintainers and governed by gh-aw security review processes. ## Table of Contents @@ -124,6 +124,8 @@ A conforming implementation MUST include detection coverage for at least the fol - **CTR-014 Supply Chain Attack via Install Scripts**: Detect when `run-install-scripts: true` is configured in workflow frontmatter (globally or per-runtime); warn in non-strict mode and reject in strict mode to protect against malicious npm pre/post install hooks that can exfiltrate secrets or corrupt the runner environment. - **CTR-015 Allowed Label Glob Scope**: Detect bare `*` wildcard patterns in `safe-outputs.*.allowed-labels` fields (`create-issue`, `create-discussion`, `update-discussion`, `create-pull-request`, `merge-pull-request`); reject compilation when such a pattern is present because it renders the label restriction ineffective and may allow the agent to apply labels that trigger unintended label-driven automation in the repository. - **CTR-016 Compile-Time Manifest Drift**: Detect when recompilation of an existing workflow would introduce new secrets or unapproved action references beyond what was previously approved in the lock file manifest; reject compilation when new restricted secrets or previously-absent action references appear, preventing adversarial workflow sources or prompt-injection from silently expanding the workflow's trust surface during routine updates. +- **CTR-017 Secret Leakage via Environment Variables**: Detect secrets expressions (`${{ secrets.* }}`) in the top-level `env:` section, in `engine.env` (excluding allowed engine-required vars), and in custom step fields (`pre-steps`, `steps`, `pre-agent-steps`, `post-steps`) outside controlled `env:` bindings and `with:` inputs for `uses:` action steps; these placements expose secrets to the agent container environment. Warn in non-strict mode; reject in strict mode. +- **CTR-018 Version Integrity Bypass**: Detect `check-for-updates: false` in workflow frontmatter, which disables the compile-agentic version update check that ensures the workflow was compiled with a supported version of gh-aw. Warn in non-strict mode; reject in strict mode. ### 4.2 Compiler Response Requirements @@ -213,6 +215,8 @@ Implementations MUST maintain a clear mapping from each active `CTR-*` rule to c | CTR-014 Supply Chain Attack via Install Scripts | `pkg/workflow/run_install_scripts_validation.go` (`validateRunInstallScripts`, `resolveRunInstallScripts`) | `pkg/workflow/run_install_scripts_validation_test.go` | | CTR-015 Allowed Label Glob Scope | `pkg/workflow/safe_outputs_allowed_labels_validation.go` (`validateSafeOutputsAllowedLabelsGlobScope`) | `pkg/workflow/safe_outputs_allowed_labels_validation_test.go` | | CTR-016 Compile-Time Manifest Drift | `pkg/workflow/safe_update_enforcement.go` (`EnforceSafeUpdate`, `collectSecretViolations`, `collectActionViolations`, `collectRedirectViolations`), called from `pkg/workflow/compiler.go` | `pkg/workflow/safe_update_enforcement_test.go` | +| CTR-017 Secret Leakage via Environment Variables | `pkg/workflow/strict_mode_env_validation.go` (`validateEnvSecrets`, `validateEnvSecretsSection`), `pkg/workflow/strict_mode_steps_validation.go` (`validateStepsSecrets`, `validateStepsSectionSecrets`) | `pkg/workflow/env_secrets_validation_test.go`, `pkg/workflow/jobs_secrets_validation_test.go` | +| CTR-018 Version Integrity Bypass | `pkg/workflow/update_check_validation.go` (`validateUpdateCheck`) | `pkg/workflow/update_check_validation_test.go` | The mappings above are pattern-based references and MUST be validated against concrete file paths whenever this specification is updated. @@ -220,7 +224,7 @@ When mappings change, this table MUST be updated in the same change set as the i ### 6.2 Mapping Audit (2026-05-15) -Audit result: ✅ all listed `CTR-001` through `CTR-016` rows currently include non-empty implementation references and non-empty test coverage targets; no `TODO` placeholders were found in the mapping table. +Audit result: ✅ all listed `CTR-001` through `CTR-018` rows currently include non-empty implementation references and non-empty test coverage targets; no `TODO` placeholders were found in the mapping table. Implementation note: entries that use glob patterns (for example, `pkg/workflow/*permissions*validation*.go`) SHOULD continue to be verified against concrete files during each rule update to prevent silent drift. @@ -259,6 +263,8 @@ The following test IDs map one-to-one to the CTR rules in Section 4.1. Each test | **T-CTR-014** | CTR-014 Supply Chain Attack via Install Scripts | A workflow frontmatter sets `run-install-scripts: true` (globally or under `runtimes.node`) | Compilation warning in non-strict mode identifying the supply chain risk and advising removal of `run-install-scripts: true`; compilation failure in strict mode | `CTR-014` | | **T-CTR-015** | CTR-015 Allowed Label Glob Scope | A workflow frontmatter sets `safe-outputs.*.allowed-labels` to `["*"]` (bare wildcard) for any safe-output type that supports the field (`create-issue`, `create-discussion`, `update-discussion`, `create-pull-request`, `merge-pull-request`) | Compilation failure with error identifying the field name, explaining that `"*"` disables label restrictions and may permit unintended label-driven automation, and recommending specific names or narrower patterns | `CTR-015` | | **T-CTR-016** | CTR-016 Compile-Time Manifest Drift | An existing workflow lock file has a `gh-aw-manifest` section recording approved secrets and action references; when recompiled, the new workflow body introduces a secret not in the approved manifest (e.g., `MY_NEW_SECRET`) or a new action reference not previously recorded | Compilation failure with error identifying each new restricted secret and each added or removed action reference beyond the previously approved manifest baseline, preventing silent trust-surface expansion | `CTR-016` | +| **T-CTR-017** | CTR-017 Secret Leakage via Environment Variables | A workflow frontmatter declares a secrets expression (e.g., `${{ secrets.MY_SECRET }}`) in the top-level `env:` section, in `engine.env` for a non-engine var, or in a custom step's `run:` field | Compilation warning in non-strict mode identifying the secrets expression and the section where it appears; compilation failure in strict mode | `CTR-017` | +| **T-CTR-018** | CTR-018 Version Integrity Bypass | A workflow frontmatter sets `check-for-updates: false` | Compilation warning in non-strict mode identifying the disabled version check and advising removal; compilation failure in strict mode | `CTR-018` | ### 7.2 Test Coverage Requirements @@ -280,6 +286,19 @@ The following test IDs map one-to-one to the CTR rules in Section 4.1. Each test ## 9. Change Log +### 1.0.8 (2026-05-16) + +- Added CTR-018 Version Integrity Bypass (warn/reject when `check-for-updates: false` disables the compile-agentic version update check; implemented in `update_check_validation.go`) +- Added T-CTR-018 test ID entry in Section 7.1 +- Extended Section 6.1 baseline rule mapping table with CTR-018 implementation references (`update_check_validation.go`) + +### 1.0.7 (2026-05-16) + +- Added CTR-017 Secret Leakage via Environment Variables (warn/reject when secrets expressions appear in top-level `env:`, `engine.env`, or in uncontrolled custom step fields; implemented in `strict_mode_env_validation.go` and `strict_mode_steps_validation.go`) +- Added T-CTR-017 test ID entry in Section 7.1 +- Extended Section 6.1 baseline rule mapping table with CTR-017 implementation references (`strict_mode_env_validation.go`, `strict_mode_steps_validation.go`) +- Updated mapping audit note to cover CTR-001 through CTR-018 + ### 1.0.6 (2026-05-15) - Added CTR-016 Compile-Time Manifest Drift (compilation rejection when recompilation of an existing workflow would introduce new restricted secrets or unapproved action references beyond the previously approved lock file manifest baseline; detected by `EnforceSafeUpdate` in `safe_update_enforcement.go`, called from `compiler.go`)