Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,14 @@ updates:
- "dependencies"
commit-message:
prefix: "deps:"

# Python CLI tools (semgrep, ruff) live in
# `tools/setup/manifests/uv-tools`, installed via
# `common/python-tools.sh`. Dependabot does not support the
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The referenced script path looks incorrect: the repo path is tools/setup/common/python-tools.sh, but this comment refers to common/python-tools.sh without the tools/setup/ prefix. Please fix the path so readers can find the script and pointer-integrity audits don’t flag it.

Suggested change
# `common/python-tools.sh`. Dependabot does not support the
# `tools/setup/common/python-tools.sh`. Dependabot does not support the

Copilot uses AI. Check for mistakes.
# uv-tools format, so pin drift is caught by the periodic
# uv-tools drift scan (BACKLOG P1) rather than by this file.
# Three-way-parity per GOVERNANCE §24 takes precedence over
# Dependabot-trackability — one canonical manifest, installed
# the same way on dev laptop / CI / devcontainer, beats a
# parallel `requirements.txt` that exists only to satisfy
# Dependabot's ecosystem list.
166 changes: 166 additions & 0 deletions .github/workflows/resume-diff.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
# Zeta resume-claim diff reviewer-helper
#
# Runs on every PR that touches `docs/FACTORY-RESUME.md` or
# `docs/SHIPPED-VERIFICATION-CAPABILITIES.md` — the two files
# that form the factory's "job-interview honesty" surface per
# `memory/feedback_factory_resume_job_interview_honesty_only_direct_experience.md`.
Comment on lines +5 to +6
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The referenced memory file memory/feedback_factory_resume_job_interview_honesty_only_direct_experience.md does not appear to exist in the repo (no matching file under memory/). Either add the missing memory entry or update this reference to the correct existing path so the workflow header doesn’t point at a dead link.

Suggested change
# that form the factory's "job-interview honesty" surface per
# `memory/feedback_factory_resume_job_interview_honesty_only_direct_experience.md`.
# that form the factory's "job-interview honesty" surface.

Copilot uses AI. Check for mistakes.
#
# Purpose (BACKLOG row "Shipped-capabilities resume diff-based
# CI check (round 44 follow-up, H-risk row 24)"; H-risk flagged
# in `docs/research/imperfect-enforcement-hygiene-audit.md`):
# emit a structured claim-level diff as a PR comment so a
# reviewer can eyeball added / removed / modified claims for
# substantive drift. Tighter than round-cadence; NOT a gate —
# judgment stays with the reviewer and with Aaron (honesty-
# floor owner).
Comment on lines +14 to +15
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment uses a direct contributor name (“Aaron”), but repo guidance is to avoid name attribution in code/docs and use role references (e.g., “human maintainer”) except in explicitly exempt surfaces. Please rewrite this to use the role reference here.

Suggested change
# judgment stays with the reviewer and with Aaron (honesty-
# floor owner).
# judgment stays with the reviewer and with the human
# maintainer (honesty-floor owner).

Copilot uses AI. Check for mistakes.
#
# Security (reviewed 2026-04-22; complies with the pre-write
# checklist in `docs/security/GITHUB-ACTIONS-SAFE-PATTERNS.md`,
# which is in turn derived from the GitHub Security Lab guide at
# https://github.blog/security/vulnerability-research/how-to-catch-github-actions-workflow-injections-before-attackers-do/):
# - All `${{ github.event.* }}` values are consumed ONLY via
# `env:` blocks and referenced as shell variables in `run:`
# scripts. No inline `${{ ... }}` interpolation inside any
# `run:` command.
# - Inputs are limited to commit SHAs (40-hex, injection-proof)
# and the PR number (numeric). None of the risky inputs
# (issue/PR titles, commit messages, body text, head refs,
# branch names) appear anywhere in this workflow.
# - Third-party actions SHA-pinned (only actions/checkout is
# used). `gh pr comment` is pre-installed on GitHub-hosted
# runners; uses the default workflow token.
# - permissions: contents: read at the workflow level;
# pull-requests: write only at the single job that posts
# the comment.
# - concurrency: workflow-scoped; cancel-in-progress for PR
# events.
# - Runner digest-pinned (ubuntu-22.04).
# - Graceful no-change handling: if the diff has no claim-
# bearing lines, posts a clarifying message and passes.
# Does not fail the PR.

name: resume-diff

on:
pull_request:
types: [opened, reopened, synchronize, ready_for_review]
paths:
- 'docs/FACTORY-RESUME.md'
- 'docs/SHIPPED-VERIFICATION-CAPABILITIES.md'

permissions:
contents: read

concurrency:
group: resume-diff-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
resume-diff:
name: claim-level diff
runs-on: ubuntu-22.04
timeout-minutes: 5
permissions:
contents: read
pull-requests: write

Comment on lines +63 to +66
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On fork PRs, workflows triggered by pull_request commonly receive a read-only GITHUB_TOKEN, so gh pr comment can fail even if pull-requests: write is declared. To avoid noisy red runs, consider gating the comment step/job to same-repo PRs (or handling the failure explicitly), or document the required repo setting if write tokens for fork PRs are enabled intentionally.

Copilot uses AI. Check for mistakes.
steps:
- name: Checkout PR head with full history
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}

- name: Compute claim-level diff
id: diff
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
set -euo pipefail

FILES=(
"docs/FACTORY-RESUME.md"
"docs/SHIPPED-VERIFICATION-CAPABILITIES.md"
)

OUTPUT_FILE="$(mktemp)"
HAS_CHANGES=0

{
echo "### Resume claim-level diff — reviewer attention requested"
echo
echo "This PR touches one or both of the factory's"
echo "**job-interview honesty** docs. Per the honesty"
echo "floor (\`memory/feedback_factory_resume_job_interview_honesty_only_direct_experience.md\`),"
echo "every resume claim must be backed by in-repo evidence"
echo "a reader can verify. Confirm each added claim has"
echo "evidence, each removed claim is intentionally retired,"
echo "each modified line preserves the honesty floor."
echo
echo "Base SHA: \`${BASE_SHA}\`"
echo "Head SHA: \`${HEAD_SHA}\`"
} > "$OUTPUT_FILE"

for FILE in "${FILES[@]}"; do
if ! git diff --quiet "$BASE_SHA" "$HEAD_SHA" -- "$FILE"; then
HAS_CHANGES=1
{
echo
echo "#### \`$FILE\`"
echo

RAW_DIFF="$(git diff --no-color --unified=1 \
"$BASE_SHA" "$HEAD_SHA" -- "$FILE")"

CLAIM_LINES="$(printf '%s\n' "$RAW_DIFF" \
| grep -E '^[+-][^+-]' \
| grep -E '^[+-]\s*(- \*\*|\| |#{2,4} |.*\b(ships?|shipped|verified|proven|complete[ds]?|honest|already absorbed|implement(ed|s)?|in[- ]repo evidence)\b)' \
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

grep -E doesn’t support \s (whitespace) or \b (word boundary), so this claim-line filter won’t match what it intends on ubuntu-22.04 (GNU grep treats these as literal characters). Use POSIX character classes like [[:space:]] and a word-boundary alternative (or switch to grep -P / perl) so the detection is actually effective under set -euo pipefail.

Suggested change
| grep -E '^[+-]\s*(- \*\*|\| |#{2,4} |.*\b(ships?|shipped|verified|proven|complete[ds]?|honest|already absorbed|implement(ed|s)?|in[- ]repo evidence)\b)' \
| grep -E '^[+-][[:space:]]*(- \*\*|\| |#{2,4} |.*(^|[^[:alnum:]_])(ships?|shipped|verified|proven|complete[ds]?|honest|already absorbed|implement(ed|s)?|in[- ]repo evidence)([^[:alnum:]_]|$))' \

Copilot uses AI. Check for mistakes.
|| true)"

if [ -n "$CLAIM_LINES" ]; then
echo "**Claim-bearing lines** (bullets, table rows, headers, honesty-keyword hits):"
echo
echo '```diff'
printf '%s\n' "$CLAIM_LINES"
echo '```'
else
echo "_No claim-bearing lines detected in this file's diff_"
echo "_(changes may be formatting / punctuation / whitespace — still worth a reviewer glance)._"
fi

echo
echo "<details><summary>Full unified diff</summary>"
echo
echo '```diff'
printf '%s\n' "$RAW_DIFF"
echo '```'
echo
echo "</details>"
} >> "$OUTPUT_FILE"
fi
done

if [ "$HAS_CHANGES" -eq 0 ]; then
{
echo
echo "_No changes detected in either resume file at claim level._"
echo "_(The \`paths\` filter matched one of the two files but"
echo "the diff resolved to zero lines — likely a rename or a"
echo "whitespace-only change.)_"
} >> "$OUTPUT_FILE"
fi

{
echo "diff_file=$OUTPUT_FILE"
echo "has_changes=$HAS_CHANGES"
} >> "$GITHUB_OUTPUT"

- name: Post PR comment
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ github.event.pull_request.number }}
DIFF_FILE: ${{ steps.diff.outputs.diff_file }}
run: |
set -euo pipefail
gh pr comment "$PR_NUMBER" --body-file "$DIFF_FILE"
Comment on lines +159 to +166
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gh pr comment will fail on fork PRs when the workflow is triggered via pull_request, because GITHUB_TOKEN is read-only for forks and cannot write PR comments. Since this step runs under set -euo pipefail, the whole workflow will go red for forked contributions. Make comment posting conditional on same-repo PRs, or switch to a hardened pull_request_target design (while ensuring you never execute PR-provided code) so the workflow behaves reliably.

Copilot uses AI. Check for mistakes.
89 changes: 89 additions & 0 deletions .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# OpenSSF Scorecard — weekly project-health audit.
#
# Scorecard runs ~20 heuristic checks that score the repo on
# security-relevant posture: branch protection, signed releases,
# dangerous workflows, pinned dependencies, CII best practices,
# dependency-update tools, SAST coverage, token permissions,
# maintained-ness, and so on. Results upload to GitHub
# Security -> Code scanning as SARIF.
#
# Lane: factory. Orthogonal to the CVE scanners (Dependabot +
# `dotnet list --vulnerable`) - Scorecard audits *configuration*,
# not advisories. See `docs/research/vuln-and-dep-scanner-
# landscape-2026-04-22.md` adopt-now item #3 for the rationale.
Comment on lines +12 to +13
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment hard-wraps the referenced doc path across lines (docs/research/vuln-and-dep-scanner- + landscape-...), which breaks copy/paste and makes pointer-integrity checking harder. Keep repository paths unbroken on a single line.

Suggested change
# not advisories. See `docs/research/vuln-and-dep-scanner-
# landscape-2026-04-22.md` adopt-now item #3 for the rationale.
# not advisories. See `docs/research/vuln-and-dep-scanner-landscape-2026-04-22.md`
# adopt-now item #3 for the rationale.

Copilot uses AI. Check for mistakes.
#
# SECURITY NOTE on expressions
# ----------------------------
# No attacker-controlled fields are interpolated into any `run:`
# block or action input in this workflow. The only `${{ ... }}`
# expansions are `github.workflow` and `github.ref` (trusted
# contexts) in the concurrency group. Scorecard action inputs
# (`results_format`, `results_file`, `publish_results`) are
# static literals. `publish_results: true` opts in to the
# OpenSSF public Scorecard dashboard - outbound publish of our
# score; no inbound attack surface. Pre-write checklist:
# `docs/security/GITHUB-ACTIONS-SAFE-PATTERNS.md`.
#
# Action-pin content-review (per `docs/security/SUPPLY-CHAIN-
# SAFE-PATTERNS.md`): ossf/scorecard-action v2.4.3 tagged
# 2025-09-30 by sschrock@google.com (OpenSSF maintainer),
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This header comment includes an individual’s email address (ss...@google.com). Beyond name-attribution guidance, embedding personal identifiers in workflow comments tends to age badly and can be unnecessary PII in-repo. Consider replacing it with an organization/role reference (e.g., “OpenSSF maintainer”) and/or a link to the tagged release/verification evidence instead of a specific email.

Suggested change
# 2025-09-30 by sschrock@google.com (OpenSSF maintainer),
# 2025-09-30 by an OpenSSF maintainer,

Copilot uses AI. Check for mistakes.
# SSH-signed, GitHub API reports verified=true reason=valid.
# Owner org `ossf` is the OpenSSF foundation's GitHub org.
# Commit SHA `4eaacf0543bb3f2c246792bd56e8cdeffafb205a` locks
# the reviewed release.

name: scorecard

on:
schedule:
- cron: '0 7 * * 1'
push:
branches: [main]
branch_protection_rule:
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false

jobs:
analysis:
name: scorecard analysis
runs-on: ubuntu-22.04
timeout-minutes: 10

permissions:
id-token: write
security-events: write
contents: read
actions: read

steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Run Scorecard analysis
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
with:
results_file: results.sarif
results_format: sarif
publish_results: true

- name: Upload SARIF as workflow artifact
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: scorecard-sarif
path: results.sarif
retention-days: 7

- name: Upload SARIF to GitHub code scanning
# Same pin as `.github/workflows/codeql.yml` - one
# codeql-action version across the repo, bumped together.
uses: github/codeql-action/upload-sarif@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2
with:
sarif_file: results.sarif
30 changes: 30 additions & 0 deletions .semgrep.yml
Original file line number Diff line number Diff line change
Expand Up @@ -340,3 +340,33 @@ rules:
# "file lacks any of these headings"; a bespoke diff-level lint
# (which round-30 spec calls the "safety-clause-diff lint") is
# the stronger signal. Tracked in docs/DEBT.md; target round-31.

# ────────────────────────────────────────────────────────────────
# Rule 17 — GitHub Actions workflow-injection: inline untrusted
# context on a `run:` line. The primary workflow-injection vector
# per https://github.blog/security/vulnerability-research/how-to-
# catch-github-actions-workflow-injections-before-attackers-do/.
# Matches single-line `run: ... ${{ github.<unsafe-path> }} ...`
# forms for the attacker-controlled contexts enumerated in
# docs/security/GITHUB-ACTIONS-SAFE-PATTERNS.md. Multi-line `run:
# |` blocks are covered by actionlint's YAML-aware parser.
# Fix: bind the value to an `env:` entry on the step and read it
# as `"$VAR"` in the shell. See the safe-patterns doc.
# ────────────────────────────────────────────────────────────────
- id: gha-untrusted-in-run-line
patterns:
- pattern-regex: '(?m)^\s*-?\s*run:.*\$\{\{\s*github\.(head_ref|event\.(issue\.(title|body)|pull_request\.(title|body|head_ref|head\.ref|head\.label)|comment\.body|review\.body|head_commit\.message|commits))'
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pattern-regex matches prefixes like github.event.commits without requiring a following .message or a boundary, so it can false-positive on safe fields such as github.event.commits_url (and similarly for other paths where the unsafe name is a prefix). Since this is severity: ERROR, please tighten the regex to match only the intended unsafe properties (e.g., commits\[[^\]]+\]\.message) and/or add a proper boundary so benign keys don’t get blocked.

Suggested change
- pattern-regex: '(?m)^\s*-?\s*run:.*\$\{\{\s*github\.(head_ref|event\.(issue\.(title|body)|pull_request\.(title|body|head_ref|head\.ref|head\.label)|comment\.body|review\.body|head_commit\.message|commits))'
- pattern-regex: '(?m)^\s*-?\s*run:.*\$\{\{\s*github\.((?:head_ref\b)|(?:event\.(?:issue\.(?:title|body)\b|pull_request\.(?:title|body|head_ref|head\.ref|head\.label)\b|comment\.body\b|review\.body\b|head_commit\.message\b|commits\[[^\]]+\]\.message\b)))'

Copilot uses AI. Check for mistakes.
paths:
include:
- ".github/workflows/*.yml"
- ".github/workflows/*.yaml"
message: >-
Attacker-controlled `github.event.*` / `github.head_ref` value
expanded directly into a `run:` shell command — classic GitHub
Actions workflow-injection sink. A PR title / issue body /
branch name containing shell metacharacters will execute on
the runner. Bind the value to the step's `env:` block and
reference it as `"$VAR"` in the shell instead. See
`docs/security/GITHUB-ACTIONS-SAFE-PATTERNS.md` §Do / don't.
languages: [generic]
severity: ERROR
Loading
Loading