Skip to content

fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it - #209

Open
hyperpolymath wants to merge 1 commit into
mainfrom
fix/scan-and-report-sha-pins
Open

hyperpolymath wants to merge 1 commit into
mainfrom
fix/scan-and-report-sha-pins

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Why

hyperpolymath/echidna has sha_pinning_required: true. Its Security Scan calls this reusable and has ended in startup_failure since the pinning rule landed. The run page for echidna run 36185528155 says:

The actions actions/checkout@v4.3.1, dtolnay/rust-toolchain@v1, and swatinem/rust-cache@v2.8.2 are not allowed in hyperpolymath/echidna …

actions/checkout is GitHub-owned, and echidna has github_owned_allowed: true. So the allow-list is not the cause; the tag refs are.

A caller's own actions.lock does not cover a cross-repo callee's steps, so the callee has to carry commit SHAs itself.

Positive control: echidna's Scorecard and Secret Scanner succeed through standards/*-reusable.yml@571cc73, whose steps are written @<sha> # vX.

#201 had pinned these steps. #203's gh actions-lock rewrite turned them back into tags.

Change

  • Pins the three steps:
    • actions/checkout@3d3c42e5 (v7.0.1)
    • dtolnay/rust-toolchain@02cb101e (v1)
    • Swatinem/rust-cache@6323deb1 (v2.9.2)
  • Updates the actions.lock entry by hand to match, because gh actions-lock write mode de-pins the steps again.
  • Changes toolchain: v1 to stable. v1 is the action's tag, not a Rust toolchain.
  • Leaves one "managed by gh actions-lock" line after SPDX, instead of three.

Verification

gh actions-lock --no-fix --json:

  • This file: 0 errors, and 3 sha-as-ref warnings (the same advisory the standards reusables carry).
  • Repo total: 67 findings on main, 66 with this change, none new. The rest of the lock was already stale on main; that is out of scope here.

Follow-up

echidna's security-scan.yml has to bump its callee pin to this merge commit (echidna#310).

🤖 Generated with Claude Code

https://claude.ai/code/session_01SJGZgoR9ArMgxKcqG7ChW8

…rt it

Callers with `sha_pinning_required: true` (e.g. hyperpolymath/echidna) refuse
this reusable at startup because its steps used tag refs:

  The actions actions/checkout@v4.3.1, dtolnay/rust-toolchain@v1, and
  swatinem/rust-cache@v2.8.2 are not allowed in hyperpolymath/echidna ...

A caller's own actions.lock does not cover a cross-repo callee's steps, so the
callee must carry commit SHAs itself (same shape as the standards reusables,
which start fine under the same policy). #201 had pinned them; #203's
`gh actions-lock` rewrite turned them back into tags.

- checkout 3d3c42e5 (v7.0.1), rust-toolchain 02cb101e (v1),
  rust-cache 6323deb1 (v2.9.2); lock entry updated to match by hand
  (`gh actions-lock` write mode de-pins them again)
- `toolchain: v1` -> `stable` (v1 is the action's tag, not a Rust toolchain)
- one "managed by gh actions-lock" line after SPDX instead of three

Verify (--no-fix) on this file: 0 errors, 3 sha-as-ref warnings; repo total
67 -> 66 findings, none new.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJGZgoR9ArMgxKcqG7ChW8
@coderabbitai

coderabbitai Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 40b02c65-5105-4caf-8c31-2e87d0756f3f

📥 Commits

Reviewing files that changed from the base of the PR and between 5e75753 and 153d3d2.

⛔ Files ignored due to path filters (1)
  • .github/workflows/actions.lock is excluded by !**/*.lock
📒 Files selected for processing (1)
  • .github/workflows/scan-and-report.yml

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

📜 Recent review details
⏰ Context from checks skipped due to timeout. (20)
  • GitHub Check: GitGuardian Security Checks
  • GitHub Check: governance / Exemption ratchet
  • GitHub Check: governance / Allowlist Preflight
  • GitHub Check: governance / Live Actions policy (credentialed advisory)
  • GitHub Check: governance / Well-Known (RFC 9116 + RSR)
  • GitHub Check: governance / Trusted-base reduction policy
  • GitHub Check: governance / Licence consistency
  • GitHub Check: governance / Workflow security linter
  • GitHub Check: governance / Security policy checks
  • GitHub Check: governance / Check Workflow Staleness
  • GitHub Check: governance / Actions lockfile verify
  • GitHub Check: governance / Code quality + docs
  • GitHub Check: governance / Debt ratchet
  • GitHub Check: governance / Guix packaging policy (Nix retired)
  • GitHub Check: governance / Language / package anti-pattern policy
  • GitHub Check: scan / gitleaks
  • GitHub Check: rust-ci / Detect Cargo.toml
  • GitHub Check: scan / shell-secrets
  • GitHub Check: hypatia / Hypatia Neurosymbolic Analysis
  • GitHub Check: semgrep-cloud-platform/scan
⚠️ CI failures not shown inline (24)

GitHub Actions: Secret Scanner / 0_scan _ gitleaks.txt: fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it

Conclusion: failure

View job details

##[group]Run set -euo pipefail
 �[36;1mset -euo pipefail�[0m
 �[36;1m�[0m
 �[36;1m# A repo-local baseline wins outright — it is expected to `[extend]`�[0m
 �[36;1m# the estate one, so "wins" still means "inherits". This mirrors what�[0m
 �[36;1m# the AsciiDoc pass below already did, which was inconsistent with�[0m
 �[36;1m# this step until now.�[0m
 �[36;1mCONFIG=".gitleaks-estate.toml"�[0m
 �[36;1mif [ -f .gitleaks.toml ]; then�[0m
 �[36;1m  CONFIG=".gitleaks.toml"�[0m
 �[36;1m  echo "Using repository .gitleaks.toml (extending the estate baseline)."�[0m
 �[36;1melse�[0m
 �[36;1m  echo "Using estate baseline allowlist."�[0m
 �[36;1mfi�[0m
 �[36;1m�[0m
 �[36;1m"$RUNNER_TEMP/gitleaks" detect \�[0m
 �[36;1m  --source . \�[0m
 �[36;1m  --no-git \�[0m
 �[36;1m  --redact \�[0m
 �[36;1m  --no-banner \�[0m
 �[36;1m  --verbose \�[0m
 �[36;1m  --config "$CONFIG" \�[0m
 �[36;1m  --exit-code 1�[0m
 shell: /usr/bin/bash -e {0}
 ##[endgroup]
 Using repository .gitleaks.toml (extending the estate baseline).
 Finding:     #   fixture   Key : �[1;3;mREDACTED�[0m;
 ***REDACTED_SECRET_ASSIGNMENT***
 RuleID:      generic-api-key
 Entropy:     3.932138
 File:        .gitleaks-estate.toml
 Line:        84
 Fingerprint: .gitleaks-estate.toml:generic-api-key:84
 Finding:     #   MATCH   = `Key : �[1;3;mREDACTED�[0m;`      ***REDACTED_SECRET_ASSIGNMENT***
 ***REDACTED_SECRET_ASSIGNMENT***
 RuleID:      generic-api-key
 Entropy:     3.932138
 File:        .gitleaks-estate.toml
 Line:        85
 Fingerprint: .gitleaks-estate.toml:generic-api-key:85
 Finding:     ...y : REDACTED;`      ***REDACTED_SECRET_ASSIGNMENT***
 ***REDACTED_SECRET_ASSIGNMENT***
 RuleID:      generic-api-key
 Entropy:     3.932138
 File:        .gitleaks-estate.toml
 Line:        85
 Fingerprint: .gitleaks-estate.toml:generic-api-key:85
 �[90m5:02PM�[0m �[32mINF�[0m scan completed in 361ms
 �[90m5:02PM�[0m �[31mWRN�[0m leaks found: 3
 ##[error]Process completed with exit code 1.

GitHub Actions: Secret Scanner / scan _ gitleaks: fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it

Conclusion: failure

View job details

##[group]Run set -euo pipefail
 �[36;1mset -euo pipefail�[0m
 �[36;1m�[0m
 �[36;1m# A repo-local baseline wins outright — it is expected to `[extend]`�[0m
 �[36;1m# the estate one, so "wins" still means "inherits". This mirrors what�[0m
 �[36;1m# the AsciiDoc pass below already did, which was inconsistent with�[0m
 �[36;1m# this step until now.�[0m
 �[36;1mCONFIG=".gitleaks-estate.toml"�[0m
 �[36;1mif [ -f .gitleaks.toml ]; then�[0m
 �[36;1m  CONFIG=".gitleaks.toml"�[0m
 �[36;1m  echo "Using repository .gitleaks.toml (extending the estate baseline)."�[0m
 �[36;1melse�[0m
 �[36;1m  echo "Using estate baseline allowlist."�[0m
 �[36;1mfi�[0m
 �[36;1m�[0m
 �[36;1m"$RUNNER_TEMP/gitleaks" detect \�[0m
 �[36;1m  --source . \�[0m
 �[36;1m  --no-git \�[0m
 �[36;1m  --redact \�[0m
 �[36;1m  --no-banner \�[0m
 �[36;1m  --verbose \�[0m
 �[36;1m  --config "$CONFIG" \�[0m
 �[36;1m  --exit-code 1�[0m
 shell: /usr/bin/bash -e {0}
 ##[endgroup]
 Using repository .gitleaks.toml (extending the estate baseline).
 Finding:     #   fixture   Key : �[1;3;mREDACTED�[0m;
 ***REDACTED_SECRET_ASSIGNMENT***
 RuleID:      generic-api-key
 Entropy:     3.932138
 File:        .gitleaks-estate.toml
 Line:        84
 Fingerprint: .gitleaks-estate.toml:generic-api-key:84
 Finding:     #   MATCH   = `Key : �[1;3;mREDACTED�[0m;`      ***REDACTED_SECRET_ASSIGNMENT***
 ***REDACTED_SECRET_ASSIGNMENT***
 RuleID:      generic-api-key
 Entropy:     3.932138
 File:        .gitleaks-estate.toml
 Line:        85
 Fingerprint: .gitleaks-estate.toml:generic-api-key:85
 Finding:     ...y : REDACTED;`      ***REDACTED_SECRET_ASSIGNMENT***
 ***REDACTED_SECRET_ASSIGNMENT***
 RuleID:      generic-api-key
 Entropy:     3.932138
 File:        .gitleaks-estate.toml
 Line:        85
 Fingerprint: .gitleaks-estate.toml:generic-api-key:85
 �[90m5:02PM�[0m �[32mINF�[0m scan completed in 361ms
 �[90m5:02PM�[0m �[31mWRN�[0m leaks found: 3
 ##[error]Process completed with exit code 1.

GitHub Actions: Secret Scanner / 1_scan _ shell-secrets.txt: fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it

Conclusion: failure

View job details

##[group]Run # Patterns: an `export FOO=` or `FOO=` with a quoted literal of meaningful length.
 �[36;1m# Patterns: an `export FOO=` or `FOO=` with a quoted literal of meaningful length.�[0m
 �[36;1m# Restricted to *_TOKEN / *_KEY / *_SECRET / PASSWORD to keep false-positives low.�[0m
 �[36;1mPATTERNS=(�[0m
 �[36;1m  '(export[[:space:]]+)?[A-Z_]*TOKEN[A-Z_]*=["'"'"'][A-Za-z0-9_./+=-]{20,}["'"'"']'�[0m
 �[36;1m  '(export[[:space:]]+)?[A-Z_]*API_KEY[A-Z_]*=["'"'"'][A-Za-z0-9_./+=-]{20,}["'"'"']'�[0m
 �[36;1m  '(export[[:space:]]+)?[A-Z_]*SECRET[A-Z_]*=["'"'"'][A-Za-z0-9_./+=-]{16,}["'"'"']'�[0m
 �[36;1m  '(export[[:space:]]+)?***"'"'"'][^"'"'"']{6,}["'"'"']'�[0m
 �[36;1m)�[0m
 �[36;1m�[0m
 �[36;1m# Inline pragma patterns — suppress a hit when found on the same or�[0m
 �[36;1m# immediately preceding line.�[0m
 �[36;1mPRAGMA_RE='(scanner-allow:[[:space:]]*shell-secrets|hypatia:[[:space:]]*allow[[:space:]]+security_errors/secret_detected)'�[0m
 �[36;1m�[0m
 �[36;1m# Param-expansion RHS pattern — assignments whose value is a variable�[0m
 �[36;1m# reference rather than a literal are never real secrets.�[0m
 �[36;1m# Matches: ="$VAR"  ="${VAR}"  ="${VAR:-…}"  ="${VAR:?…}"  ='${VAR}'  =$VAR�[0m
 �[36;1mPARAM_EXPANSION_RE='=['"'"'"'"'"']?\$\{?[A-Za-z_][A-Za-z0-9_]*(:[?-][^}]*)?\}?['"'"'"'"'"']?[[:space:]]*(#.*)?$'�[0m
 �[36;1m�[0m
 �[36;1m# Load per-repo ignore globs from .shell-secrets-ignore if present.�[0m
 �[36;1mIGNORE_GLOBS=()�[0m
 �[36;1mif [[ -f .shell-secrets-ignore ]]; then�[0m
 �[36;1m  while IFS= read -r line || [[ -n "$line" ]]; do�[0m
 �[36;1m    # Skip blank lines and comments�[0m
 �[36;1m    [[ -z "$line" || "$line" == \#* ]] && continue�[0m
 �[36;1m    IGNORE_GLOBS+=("$line")�[0m
 �[36;1m  done < .shell-secrets-ignore�[0m
 �[36;1mfi�[0m
 �[36;1m�[0m
 �[36;1m# is_ignored <filepath> — returns 0 (true) if path matches any ignore glob.�[0m
 �[36;1mis_ignored() {�[0m
 �[36;1m  local path="$1"�[0m
 �[36;1m  for glob in "${IGNORE_GLOBS[@]}"; do�[0m
 �[36;1m    #...

GitHub Actions: Secret Scanner / scan _ shell-secrets: fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it

Conclusion: failure

View job details

##[group]Run # Patterns: an `export FOO=` or `FOO=` with a quoted literal of meaningful length.
 �[36;1m# Patterns: an `export FOO=` or `FOO=` with a quoted literal of meaningful length.�[0m
 �[36;1m# Restricted to *_TOKEN / *_KEY / *_SECRET / PASSWORD to keep false-positives low.�[0m
 �[36;1mPATTERNS=(�[0m
 �[36;1m  '(export[[:space:]]+)?[A-Z_]*TOKEN[A-Z_]*=["'"'"'][A-Za-z0-9_./+=-]{20,}["'"'"']'�[0m
 �[36;1m  '(export[[:space:]]+)?[A-Z_]*API_KEY[A-Z_]*=["'"'"'][A-Za-z0-9_./+=-]{20,}["'"'"']'�[0m
 �[36;1m  '(export[[:space:]]+)?[A-Z_]*SECRET[A-Z_]*=["'"'"'][A-Za-z0-9_./+=-]{16,}["'"'"']'�[0m
 �[36;1m  '(export[[:space:]]+)?***"'"'"'][^"'"'"']{6,}["'"'"']'�[0m
 �[36;1m)�[0m
 �[36;1m�[0m
 �[36;1m# Inline pragma patterns — suppress a hit when found on the same or�[0m
 �[36;1m# immediately preceding line.�[0m
 �[36;1mPRAGMA_RE='(scanner-allow:[[:space:]]*shell-secrets|hypatia:[[:space:]]*allow[[:space:]]+security_errors/secret_detected)'�[0m
 �[36;1m�[0m
 �[36;1m# Param-expansion RHS pattern — assignments whose value is a variable�[0m
 �[36;1m# reference rather than a literal are never real secrets.�[0m
 �[36;1m# Matches: ="$VAR"  ="${VAR}"  ="${VAR:-…}"  ="${VAR:?…}"  ='${VAR}'  =$VAR�[0m
 �[36;1mPARAM_EXPANSION_RE='=['"'"'"'"'"']?\$\{?[A-Za-z_][A-Za-z0-9_]*(:[?-][^}]*)?\}?['"'"'"'"'"']?[[:space:]]*(#.*)?$'�[0m
 �[36;1m�[0m
 �[36;1m# Load per-repo ignore globs from .shell-secrets-ignore if present.�[0m
 �[36;1mIGNORE_GLOBS=()�[0m
 �[36;1mif [[ -f .shell-secrets-ignore ]]; then�[0m
 �[36;1m  while IFS= read -r line || [[ -n "$line" ]]; do�[0m
 �[36;1m    # Skip blank lines and comments�[0m
 �[36;1m    [[ -z "$line" || "$line" == \#* ]] && continue�[0m
 �[36;1m    IGNORE_GLOBS+=("$line")�[0m
 �[36;1m  done < .shell-secrets-ignore�[0m
 �[36;1mfi�[0m
 �[36;1m�[0m
 �[36;1m# is_ignored <filepath> — returns 0 (true) if path matches any ignore glob.�[0m
 �[36;1mis_ignored() {�[0m
 �[36;1m  local path="$1"�[0m
 �[36;1m  for glob in "${IGNORE_GLOBS[@]}"; do�[0m
 �[36;1m    #...

GitHub Actions: Secret Scanner / 2_scan _ rust-secrets.txt: fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it

Conclusion: failure

View job details

##[group]Run TODAY="${RUST_TODAY:-$(date -u +%Y-%m-%d)}"
 �[36;1mTODAY="${RUST_TODAY:-$(date -u +%Y-%m-%d)}"�[0m
 �[36;1m�[0m
 �[36;1m# An unparseable cutoff would pick the warn branch forever, silently�[0m
 �[36;1m# disarming the widened scan. Refuse to run instead.�[0m
 �[36;1mrequire_date() {�[0m
 �[36;1m  case "$2" in�[0m
 �[36;1m    [0-9][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9]) : ;;�[0m
 �[36;1m    *) echo "::error::rust-secrets: $1='$2' is not YYYY-MM-DD."�[0m

GitHub Actions: Secret Scanner / scan _ rust-secrets: fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it

Conclusion: failure

View job details

##[group]Run TODAY="${RUST_TODAY:-$(date -u +%Y-%m-%d)}"
 �[36;1mTODAY="${RUST_TODAY:-$(date -u +%Y-%m-%d)}"�[0m
 �[36;1m�[0m
 �[36;1m# An unparseable cutoff would pick the warn branch forever, silently�[0m
 �[36;1m# disarming the widened scan. Refuse to run instead.�[0m
 �[36;1mrequire_date() {�[0m
 �[36;1m  case "$2" in�[0m
 �[36;1m    [0-9][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9]) : ;;�[0m
 �[36;1m    *) echo "::error::rust-secrets: $1='$2' is not YYYY-MM-DD."�[0m

GitHub Actions: Rust CI / 1_rust-ci _ Cargo check + clippy + fmt.txt: fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it

Conclusion: failure

View job details

::strip_should_panic_items_rs(
 -            &Self::strip_cfg_test_modules_rs(&without_comments),
 -        );
 +        let code_only =
 +            Self::strip_should_panic_items_rs(&Self::strip_cfg_test_modules_rs(&without_comments));
          stats.unsafe_blocks += code_only.matches("unsafe {").count();
          stats.unsafe_blocks += code_only.matches("unsafe fn").count();
 Diff in /home/runner/work/panic-attack/panic-attack/src/assail/analyzer.rs:1903:
                          ),
                          recommended_attack: vec![AttackAxis::Network],
                          suppressed: false,
 -                test_context: None,
 +                        test_context: None,
                      });
                      break;
                  }
 Diff in /home/runner/work/panic-attack/panic-attack/src/assail/analyzer.rs:1926:
                          ),
                          recommended_attack: vec![AttackAxis::Network],
                          suppressed: false,
 -                test_context: None,
 +                        test_context: None,
                      });
                      break;
                  }
 Diff in /home/runner/work/panic-attack/panic-attack/src/assail/analyzer.rs:2089:
                          ),
                          recommended_attack: vec![AttackAxis::Network],
                          suppressed: false,
 -                test_context: None,
 +                        test_context: None,
                      });
                      break;
                  }
 Diff in /home/runner/work/panic-attack/panic-attack/src/assail/analyzer.rs:2111:
                          ),
                          recommended_attack: vec![AttackAxis::Network],
                          suppressed: false,
 -                test_context: None,
 +                        test_context: None,
                      });
                      break;
                  }
 Diff in /home/runner/work/panic-attack/panic-attack/src/assa...

GitHub Actions: Rust CI / rust-ci _ Cargo check + clippy + fmt: fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it

Conclusion: failure

View job details

::strip_should_panic_items_rs(
 -            &Self::strip_cfg_test_modules_rs(&without_comments),
 -        );
 +        let code_only =
 +            Self::strip_should_panic_items_rs(&Self::strip_cfg_test_modules_rs(&without_comments));
          stats.unsafe_blocks += code_only.matches("unsafe {").count();
          stats.unsafe_blocks += code_only.matches("unsafe fn").count();
 Diff in /home/runner/work/panic-attack/panic-attack/src/assail/analyzer.rs:1903:
                          ),
                          recommended_attack: vec![AttackAxis::Network],
                          suppressed: false,
 -                test_context: None,
 +                        test_context: None,
                      });
                      break;
                  }
 Diff in /home/runner/work/panic-attack/panic-attack/src/assail/analyzer.rs:1926:
                          ),
                          recommended_attack: vec![AttackAxis::Network],
                          suppressed: false,
 -                test_context: None,
 +                        test_context: None,
                      });
                      break;
                  }
 Diff in /home/runner/work/panic-attack/panic-attack/src/assail/analyzer.rs:2089:
                          ),
                          recommended_attack: vec![AttackAxis::Network],
                          suppressed: false,
 -                test_context: None,
 +                        test_context: None,
                      });
                      break;
                  }
 Diff in /home/runner/work/panic-attack/panic-attack/src/assail/analyzer.rs:2111:
                          ),
                          recommended_attack: vec![AttackAxis::Network],
                          suppressed: false,
 -                test_context: None,
 +                        test_context: None,
                      });
                      break;
                  }
 Diff in /home/runner/work/panic-attack/panic-attack/src/assa...

GitHub Actions: Governance / 2_governance _ Well-Known (RFC 9116 + RSR).txt: fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it

Conclusion: failure

View job details

##[group]Run SECTXT=""
 �[36;1mSECTXT=""�[0m
 �[36;1m[ -f ".well-known/security.txt" ] && SECTXT=".well-known/security.txt"�[0m
 �[36;1m[ -f "security.txt" ] && SECTXT="security.txt"�[0m
 �[36;1mif [ -z "$SECTXT" ]; then�[0m
 �[36;1m  echo "::warning::No security.txt found."�[0m
 �[36;1m  exit 0�[0m
 �[36;1mfi�[0m
 �[36;1mgrep -q "^Contact:" "$SECTXT" || { echo "::error::Missing Contact field"; exit 1; }�[0m

GitHub Actions: Governance / governance _ Well-Known (RFC 9116 + RSR): fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it

Conclusion: failure

View job details

##[group]Run SECTXT=""
 �[36;1mSECTXT=""�[0m
 �[36;1m[ -f ".well-known/security.txt" ] && SECTXT=".well-known/security.txt"�[0m
 �[36;1m[ -f "security.txt" ] && SECTXT="security.txt"�[0m
 �[36;1mif [ -z "$SECTXT" ]; then�[0m
 �[36;1m  echo "::warning::No security.txt found."�[0m
 �[36;1m  exit 0�[0m
 �[36;1mfi�[0m
 �[36;1mgrep -q "^Contact:" "$SECTXT" || { echo "::error::Missing Contact field"; exit 1; }�[0m

GitHub Actions: Governance / governance _ Well-Known (RFC 9116 + RSR): fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it

Conclusion: failure

View job details

##[group]Run MIXED=$(grep -rE 'src="http://|href="http://' --include="*.html" --include="*.htm" . 2>/dev/null | grep -vE 'localhost|127\.0\.0\.1|example\.com|lol/|node_modules/|third-party/|vendor/' | head -5 || true)
 �[36;1mMIXED=$(grep -rE 'src="http://|href="http://' --include="*.html" --include="*.htm" . 2>/dev/null | grep -vE 'localhost|127\.0\.0\.1|example\.com|lol/|node_modules/|third-party/|vendor/' | head -5 || true)�[0m
 �[36;1mif [ -n "$MIXED" ]; then�[0m
 �[36;1m  echo "::error::Mixed content (HTTP in HTML)"�[0m

GitHub Actions: Governance / 4_governance _ Security policy checks.txt: fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it

Conclusion: failure

View job details

##[group]Run FAILED=false
 �[36;1mFAILED=false�[0m
 �[36;1mWEAK_CRYPTO=$(grep -rE 'md5\(|sha1\(' --include="*.py" --include="*.rb" --include="*.js" --include="*.ts" --include="*.go" --include="*.rs" . 2>/dev/null | grep -v 'checksum\|cache\|test\|spec' | head -5 || true)�[0m
 �[36;1mif [ -n "$WEAK_CRYPTO" ]; then�[0m
 �[36;1m  echo "::warning::Weak crypto (MD5/SHA1) detected — ADVISORY, does not fail this job. Use SHA256+:"�[0m
 �[36;1m  echo "$WEAK_CRYPTO"�[0m
 �[36;1mfi�[0m
 �[36;1mHTTP_URLS=$(grep -rE 'http://[^l][^o][^c]' --include="*.py" --include="*.js" --include="*.ts" --include="*.go" --include="*.rs" --include="*.yaml" --include="*.yml" . 2>/dev/null | grep -v 'localhost\|127.0.0.1\|example\|test\|spec' | head -5 || true)�[0m
 �[36;1mif [ -n "$HTTP_URLS" ]; then�[0m
 �[36;1m  echo "::warning::HTTP URLs found — ADVISORY, does not fail this job. Use HTTPS:"�[0m
 �[36;1m  echo "$HTTP_URLS"�[0m
 �[36;1mfi�[0m
 �[36;1mSECRETS=$(grep -rEi '(api_key|apikey|secret_key|password)\s*[=:]\s*["\x27][A-Za-z0-9+/=]{20,}' --include="*.py" --include="*.js" --include="*.ts" --include="*.go" --include="*.rs" --include="*.env" . 2>/dev/null | grep -v 'example\|sample\|test\|mock\|placeholder' | head -3 || true)�[0m
 �[36;1mif [ -n "$SECRETS" ]; then�[0m
 �[36;1m  echo "::error::Potential hardcoded secrets detected — this FAILS the job:"�[0m

GitHub Actions: Governance / governance _ Security policy checks: fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it

Conclusion: failure

View job details

##[group]Run FAILED=false
 �[36;1mFAILED=false�[0m
 �[36;1mWEAK_CRYPTO=$(grep -rE 'md5\(|sha1\(' --include="*.py" --include="*.rb" --include="*.js" --include="*.ts" --include="*.go" --include="*.rs" . 2>/dev/null | grep -v 'checksum\|cache\|test\|spec' | head -5 || true)�[0m
 �[36;1mif [ -n "$WEAK_CRYPTO" ]; then�[0m
 �[36;1m  echo "::warning::Weak crypto (MD5/SHA1) detected — ADVISORY, does not fail this job. Use SHA256+:"�[0m
 �[36;1m  echo "$WEAK_CRYPTO"�[0m
 �[36;1mfi�[0m
 �[36;1mHTTP_URLS=$(grep -rE 'http://[^l][^o][^c]' --include="*.py" --include="*.js" --include="*.ts" --include="*.go" --include="*.rs" --include="*.yaml" --include="*.yml" . 2>/dev/null | grep -v 'localhost\|127.0.0.1\|example\|test\|spec' | head -5 || true)�[0m
 �[36;1mif [ -n "$HTTP_URLS" ]; then�[0m
 �[36;1m  echo "::warning::HTTP URLs found — ADVISORY, does not fail this job. Use HTTPS:"�[0m
 �[36;1m  echo "$HTTP_URLS"�[0m
 �[36;1mfi�[0m
 �[36;1mSECRETS=$(grep -rEi '(api_key|apikey|secret_key|password)\s*[=:]\s*["\x27][A-Za-z0-9+/=]{20,}' --include="*.py" --include="*.js" --include="*.ts" --include="*.go" --include="*.rs" --include="*.env" . 2>/dev/null | grep -v 'example\|sample\|test\|mock\|placeholder' | head -3 || true)�[0m
 �[36;1mif [ -n "$SECRETS" ]; then�[0m
 �[36;1m  echo "::error::Potential hardcoded secrets detected — this FAILS the job:"�[0m

GitHub Actions: Governance / governance _ Security policy checks: fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it

Conclusion: failure

View job details

##[group]Run set -uo pipefail
 �[36;1mset -uo pipefail�[0m
 �[36;1mDIR=.github/canonical-references�[0m
 �[36;1mif [ ! -d "$DIR" ]; then�[0m
 �[36;1m  echo "ℹ️  [R5] no $DIR/ — skipped (repo has not opted in)"�[0m
 �[36;1m  exit 0�[0m
 �[36;1mfi�[0m
 �[36;1mif ! command -v python3 >/dev/null 2>&1; then�[0m
 �[36;1m  echo "❌ [R5] python3 missing on runner — required for YAML rule parsing"�[0m
 �[36;1m  exit 2�[0m
 �[36;1mfi�[0m
 �[36;1mpython3 - <<'PY'�[0m
 �[36;1mimport os, sys, glob, subprocess�[0m
 �[36;1mtry:�[0m
 �[36;1m    import yaml�[0m
 �[36;1mexcept ImportError:�[0m
 �[36;1m    sys.exit("❌ [R5] PyYAML not installed on runner; install python3-yaml")�[0m
 �[36;1m�[0m
 �[36;1mdir_ = ".github/canonical-references"�[0m
 �[36;1mfiles = sorted(glob.glob(f"{dir_}/*.yml") + glob.glob(f"{dir_}/*.yaml"))�[0m
 �[36;1mif not files:�[0m
 �[36;1m    print(f"ℹ️  [R5] {dir_}/ has no .yml/.yaml rules — skipped")�[0m
 �[36;1m    sys.exit(0)�[0m
 �[36;1m�[0m
 �[36;1mtotal = 0�[0m
 �[36;1mfor rf in files:�[0m
 �[36;1m    with open(rf, encoding="utf-8") as fh:�[0m
 �[36;1m        cfg = yaml.safe_load(fh)�[0m
 �[36;1m    if not isinstance(cfg, dict):�[0m
 �[36;1m        print(f"❌ [R5] {rf}: top-level must be a mapping"); total += 1; continue�[0m
 �[36;1m    rid  = cfg.get("id", os.path.basename(rf))�[0m
 �[36;1m    desc = cfg.get("description", "")�[0m
 �[36;1m    pats = cfg.get("patterns") or []�[0m
 �[36;1m    canon = cfg.get("canonical_pointer", "")�[0m
 �[36;1m    scope = (cfg.get("scope") or {})�[0m
 �[36;1m    includes = scope.get("include") or []�[0m
 �[36;1m    if not pats or not includes:�[0m
 �[36;1m        print(f"❌ [R5:{rid}] missing patterns or scope.include in {rf}")�[0m
 �[36;1m        total += 1; continue�[0m
 �[36;1m    # exclude self-references�[0m
 �[36;1m    skip = set(["CHANGELOG.md", "CHANGELOG.adoc", rf])�[0m
 �[36;1m    if canon: skip.add(canon)�[0m
 �[36;1m    rule_hits = 0�[0m
 �[36;1m    for f_ in includes:�[0m
 �[36;1m        if f_ in skip or not os...

GitHub Actions: Governance / 8_governance _ Actions lockfile verify.txt: fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it

Conclusion: failure

View job details

##[group]Run set -uo pipefail
 �[36;1mset -uo pipefail�[0m
 �[36;1mif [ "$GITHUB_REPOSITORY" = hyperpolymath/standards ]; then�[0m
 �[36;1m  SRC=scripts�[0m
 �[36;1m  echo "Using this repository's own gate + verifier (standards self-lint)."�[0m
 �[36;1melse�[0m
 �[36;1m  SRC=.standards-lock/scripts�[0m
 �[36;1mfi�[0m
 �[36;1mfor f in check-actions-lock-gate.sh update-actions-lock.sh; do�[0m
 �[36;1m  if [ ! -f "$SRC/$f" ]; then�[0m
 �[36;1m    echo "::error::actions-lock gate: $f not found in $SRC (standards checkout at job.workflow_sha failed?)"�[0m

GitHub Actions: Governance / governance _ Actions lockfile verify: fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it

Conclusion: failure

View job details

##[group]Run set -uo pipefail
 �[36;1mset -uo pipefail�[0m
 �[36;1mif [ "$GITHUB_REPOSITORY" = hyperpolymath/standards ]; then�[0m
 �[36;1m  SRC=scripts�[0m
 �[36;1m  echo "Using this repository's own gate + verifier (standards self-lint)."�[0m
 �[36;1melse�[0m
 �[36;1m  SRC=.standards-lock/scripts�[0m
 �[36;1mfi�[0m
 �[36;1mfor f in check-actions-lock-gate.sh update-actions-lock.sh; do�[0m
 �[36;1m  if [ ! -f "$SRC/$f" ]; then�[0m
 �[36;1m    echo "::error::actions-lock gate: $f not found in $SRC (standards checkout at job.workflow_sha failed?)"�[0m

GitHub Actions: Governance / 10_governance _ Workflow security linter.txt: fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it

Conclusion: failure

View job details

##[group]Run if [ "$GITHUB_REPOSITORY" = hyperpolymath/standards ]; then
 �[36;1mif [ "$GITHUB_REPOSITORY" = hyperpolymath/standards ]; then�[0m
 �[36;1m  SCRIPT="tools/policy/check-workflows-parse.sh"�[0m
 �[36;1m  echo "Using this repository's own copy (standards self-lint)."�[0m
 �[36;1melse�[0m
 �[36;1m  SCRIPT=".standards-dupkey/tools/policy/check-workflows-parse.sh"�[0m
 �[36;1mfi�[0m
 �[36;1mif [ ! -f "$SCRIPT" ]; then�[0m
 �[36;1m  echo "::error::workflow parser gate not found in the pinned Standards revision or locally"�[0m

GitHub Actions: Governance / governance _ Workflow security linter: fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it

Conclusion: failure

View job details

##[group]Run if [ "$GITHUB_REPOSITORY" = hyperpolymath/standards ]; then
 �[36;1mif [ "$GITHUB_REPOSITORY" = hyperpolymath/standards ]; then�[0m
 �[36;1m  SCRIPT="tools/policy/check-workflows-parse.sh"�[0m
 �[36;1m  echo "Using this repository's own copy (standards self-lint)."�[0m
 �[36;1melse�[0m
 �[36;1m  SCRIPT=".standards-dupkey/tools/policy/check-workflows-parse.sh"�[0m
 �[36;1mfi�[0m
 �[36;1mif [ ! -f "$SCRIPT" ]; then�[0m
 �[36;1m  echo "::error::workflow parser gate not found in the pinned Standards revision or locally"�[0m

GitHub Actions: Governance / governance _ Workflow security linter: fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it

Conclusion: failure

View job details

##[group]Run # GitHub Actions REJECTS a workflow with duplicate keys: the run is
 �[36;1m# GitHub Actions REJECTS a workflow with duplicate keys: the run is�[0m
 �[36;1m# `failure` with no jobs, no log and no check run. Nothing else here�[0m
 �[36;1m# can see it, because yaml.safe_load silently keeps the LAST�[0m
 �[36;1m# duplicate and reports success — so the file "parses" and every�[0m
 �[36;1m# other lint passes. Measured 2026-08-05: nine workflows in hypatia�[0m
 �[36;1m# were dead this way, including a CodeQL workflow with zero�[0m
 �[36;1m# successful runs in its entire lifetime.�[0m
 �[36;1mset -euo pipefail�[0m
 �[36;1m# Standards exercises its pull-request scripts; every consumer uses�[0m
 �[36;1m# the canonical scripts fetched from this workflow's immutable�[0m
 �[36;1m# Standards revision.�[0m
 �[36;1mif [ "$GITHUB_REPOSITORY" = hyperpolymath/standards ]; then�[0m
 �[36;1m  SCRIPT="scripts/check-workflow-duplicate-keys.sh"�[0m
 �[36;1m  echo "Using this repository's own copy (standards self-lint)."�[0m
 �[36;1melse�[0m
 �[36;1m  SCRIPT=".standards-dupkey/scripts/check-workflow-duplicate-keys.sh"�[0m
 �[36;1mfi�[0m
 �[36;1mif [ ! -f "$SCRIPT" ]; then�[0m
 �[36;1m  echo "::error::duplicate-key checker not found — neither fetched from" \�[0m

GitHub Actions: Governance / 11_governance _ Code quality + docs.txt: fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it

Conclusion: failure

View job details

##[group]Run editorconfig-checker/action-editorconfig-checker@840e866d93b8e032123c23bac69dece044d4d84c
 with:
   github-***REDACTED_SECRET_ASSIGNMENT***
   version: latest
 ##[endgroup]
 Find 'latest' release
 ##[error]Error: The binary 'ec-linux-amd64*' not found

GitHub Actions: Governance / governance _ Code quality + docs: fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it

Conclusion: failure

View job details

##[group]Run editorconfig-checker/action-editorconfig-checker@840e866d93b8e032123c23bac69dece044d4d84c
 with:
   github-***REDACTED_SECRET_ASSIGNMENT***
   version: latest
 ##[endgroup]
 Find 'latest' release
 ##[error]Error: The binary 'ec-linux-amd64*' not found

GitHub Actions: Governance / 14_governance _ Language _ package anti-pattern policy.txt: fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it

Conclusion: failure

View job details

##[group]Run SCRIPT=".standards-checkout/scripts/check-ts-allowlist.sh"
 �[36;1mSCRIPT=".standards-checkout/scripts/check-ts-allowlist.sh"�[0m
 �[36;1mif [ ! -f "$SCRIPT" ] && [ "$GITHUB_REPOSITORY" = "hyperpolymath/standards" ] \�[0m
 �[36;1m   && [ -f scripts/check-ts-allowlist.sh ]; then�[0m
 �[36;1m  SCRIPT="scripts/check-ts-allowlist.sh"�[0m
 �[36;1m  echo "Using this repository's own copy (standards self-check)."�[0m
 �[36;1mfi�[0m
 �[36;1mif [ ! -f "$SCRIPT" ]; then�[0m
 �[36;1m  echo "::error::check-ts-allowlist gate not found in standards@main or locally"�[0m

GitHub Actions: Governance / governance _ Language _ package anti-pattern policy: fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it

Conclusion: failure

View job details

##[group]Run SCRIPT=".standards-checkout/scripts/check-ts-allowlist.sh"
 �[36;1mSCRIPT=".standards-checkout/scripts/check-ts-allowlist.sh"�[0m
 �[36;1mif [ ! -f "$SCRIPT" ] && [ "$GITHUB_REPOSITORY" = "hyperpolymath/standards" ] \�[0m
 �[36;1m   && [ -f scripts/check-ts-allowlist.sh ]; then�[0m
 �[36;1m  SCRIPT="scripts/check-ts-allowlist.sh"�[0m
 �[36;1m  echo "Using this repository's own copy (standards self-check)."�[0m
 �[36;1mfi�[0m
 �[36;1mif [ ! -f "$SCRIPT" ]; then�[0m
 �[36;1m  echo "::error::check-ts-allowlist gate not found in standards@main or locally"�[0m

GitHub Actions: Governance / governance _ Language _ package anti-pattern policy: fix(ci): SHA-pin scan-and-report steps so sha_pinning callers can start it

Conclusion: failure

View job details

##[group]Run SCRIPT=".standards-checkout/tools/policy/check-language-policy.sh"
 �[36;1mSCRIPT=".standards-checkout/tools/policy/check-language-policy.sh"�[0m
 �[36;1mif [ ! -f "$SCRIPT" ] && [ -f tools/policy/check-language-policy.sh ]; then�[0m
 �[36;1m  SCRIPT="tools/policy/check-language-policy.sh"�[0m
 �[36;1m  echo "Using this repository's own copy (standards self-check)."�[0m
 �[36;1mfi�[0m
 �[36;1mif [ ! -f "$SCRIPT" ]; then�[0m
 �[36;1m  echo "::error::language-policy gate not found in standards@main or locally"�[0m
🔇 Additional comments (1)
.github/workflows/scan-and-report.yml (1)

1-2: LGTM!

Also applies to: 39-39, 42-42, 44-44, 47-47


📝 Summary

Summary by CodeRabbit

  • Chores
    • Updated the automated workflow to reference fixed revisions of its checkout, Rust toolchain, and cache actions. The Rust toolchain continues to use the stable release.
    • Added licensing and workflow-management metadata to the workflow configuration. These changes affect automation setup rather than app features or user-facing behaviour.

Walkthrough

The workflow header now includes an SPDX identifier and a gh actions-lock management comment. The checkout, Rust toolchain, and Rust cache actions now use pinned commit SHAs with version comments.

Changes

Workflow action pinning

Layer / File(s) Summary
Update workflow header and action pins
.github/workflows/scan-and-report.yml
The workflow header now includes an SPDX identifier and a gh actions-lock management comment. The checkout, Rust toolchain, and Rust cache actions now use pinned commit SHAs with version comments. The Rust toolchain remains set to stable.

Priority: ➖ Normal

Estimated code review effort: 1 (Trivial) | ~4 minutes

Change: Bug fix

Suggested reviewers: metadatastician

Merge Risk: ⚪ Minimal · up to 153d3

No actionable merge-blocking risk remains from the reviewed changes.

Architecture Summary

Architecture risk: 🔵 Low · up to 153d3

The changed surface does not map to a changed system, dependency edge, entrypoint, or external dependency.

Changed systems: None identified.

Architecture concerns
No architecture-level concerns identified.

Review details

Before / after behavior

  • observed — Modified behavior in .github/workflows/scan-and-report.yml: The workflow header now places the SPDX identifier before the gh actions-lock management comment, replacing the previous repeated management comments.
  • observed — Modified behavior in .github/workflows/scan-and-report.yml: The checkout, Rust toolchain, and Rust cache action references now use pinned commit SHAs with version comments instead of version tags; the Rust toolchain input remains stable.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarises the main change: SHA-pinning the reusable scan-and-report workflow steps so callers with SHA-pinning requirements can start it.
Description check ✅ Passed The description is directly related to the changeset. It explains the startup failure, the three SHA pins, the toolchain correction, verification results, and the required follow-up.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

A rabbit checks each action pin,
Then nibbles clover in the sun.
The toolchain stays on stable ground,
Three SHA pins are safely found.
The workflow header gets its mark,
And bunnies bound off through the park.

Comment @coderabbitai help to get the list of available commands.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant