Skip to content

Commit c56dbcb

Browse files
authored
Merge pull request #436 from igerber/dismiss-codeql-14
Dismiss CodeQL #14 (untrusted-checkout-toctou) with guard test
2 parents 91cdf34 + 711b943 commit c56dbcb

3 files changed

Lines changed: 1229 additions & 0 deletions

File tree

.github/workflows/ai_pr_review.yml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,66 @@ jobs:
5555
)
5656
5757
steps:
58+
# ─────────────────────────────────────────────────────────────────
59+
# CodeQL alert #14 (untrusted-checkout-toctou/critical) was
60+
# dismissed on 2026-05-14 as "won't fix" with the rationale
61+
# documented below. The dismissal is valid ONLY while ALL of
62+
# the following hold:
63+
# 1. The Codex action runs with sandbox: read-only (see the
64+
# Run Codex step below). No step EXECUTES PR-head FILE
65+
# BYTES — no `pip install -e .`, `pytest`, `npm install`,
66+
# `cargo run`, `make`, `./configure`, `maturin develop`,
67+
# or `python3 <pr-file>.py` against checked-out PR-head
68+
# files. Inline `python3 -c '...'` invocations operating
69+
# on sanitized environment variables (PR_TITLE, PR_BODY,
70+
# PREV_REVIEW) are SAFE — the script body comes from base,
71+
# not from PR head.
72+
# 2. The fork-skip gate (`is_fork == 'false'`) gates every
73+
# post-resolve step, including both actions/checkout
74+
# invocations.
75+
# 3. The author_association check on issue_comment /
76+
# review-comment events restricts triggers to
77+
# OWNER/MEMBER/COLLABORATOR.
78+
# 4. head_sha is API-pinned in this resolve-pr step before
79+
# checkout.
80+
#
81+
# If you are adding a step that VIOLATES any of these
82+
# invariants, this dismissal is invalid. Either remove the
83+
# offending step OR restructure the workflow to checkout
84+
# BASE_SHA only and use `git show` for PR-head reads (degrades
85+
# reviewer quality — see plan archive).
86+
#
87+
# Guard test: tests/test_openai_review.py
88+
# ::TestWorkflowDoesNotExecutePRHeadCode
89+
# Catches the common ACCIDENTAL-regression forms: pip / npm /
90+
# yarn / cargo / make / maturin / poetry / pdm / uv / tox /
91+
# setup.py install/run, python file execution against PR-head
92+
# paths, bash -c / sh -c (including compound flags -lc/-ec/-exc)
93+
# with python/cp inside, env-var prefixes (`VAR=1 python3 ...`),
94+
# wrapper commands (`env`, `nohup`, `exec`, `time`, `command`),
95+
# shell negation (`!`), backslash line continuations, single-line
96+
# `python3 -c` payloads (literal-allowlisted, currently empty),
97+
# subshell `(...)`, brace group `{ ...; }`, and write-overwrites
98+
# of allowlisted /tmp paths between staging and execution
99+
# (`>`, `>>`, `cp`, `mv`, `tee`, `ln`).
100+
#
101+
# NOT exhaustive against an adversarial maintainer. Known
102+
# unmodeled paths (any of these CAN execute PR-head bytes
103+
# without tripping CI; a maintainer reviewing this workflow
104+
# MUST refuse changes that introduce them):
105+
# - bash <script> / sh <script> / ./<script> / source <script>
106+
# / . <script> — direct shell-script execution
107+
# - multi-line `python3 -c` bodies (line-by-line shlex can't
108+
# reassemble across newlines; the workflow's existing 5
109+
# sanitizer bodies are therefore exempt by invisibility)
110+
# - variable expansion: `SCRIPT="$X"; python3 "$SCRIPT"`
111+
# - `eval`, `find -exec`, `xargs -I {}`
112+
# The dismissal's primary defense is THIS comment block plus
113+
# the `dismissed_comment` field on alert #14. The guard test
114+
# is belt-and-suspenders for accidental regressions, not a
115+
# complete adversarial parser.
116+
# See TODO.md for the long-term tracking of this gap.
117+
# ─────────────────────────────────────────────────────────────────
58118
- name: Resolve PR number + metadata
59119
id: pr
60120
uses: actions/github-script@v9

TODO.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ Deferred items from PR reviews that were not addressed before merge.
141141
| HonestDiD `test_m0_short_circuit` uses wall-clock `elapsed < 0.5s` as a proxy for "short-circuit path taken" instead of calling the full optimizer. Replace with a direct correctness signal (mock/spy the optimizer or check a state flag) so the test doesn't depend on CI timing. Not flaky today at 500ms, but load-bearing correctness on a timing proxy is brittle. | `tests/test_methodology_honest_did.py:246` || Low |
142142
| SyntheticDiD: rename internal `placebo_effects` variable to `variance_effects` (or `resampled_effects`). Misleading name across the placebo/bootstrap/jackknife dispatch paths — holds three different contents depending on variance method. Low-risk refactor; user-facing field rename should preserve `placebo_effects` as a deprecated alias for one release. | `synthetic_did.py`, `results.py` | follow-up | Medium |
143143
| AI review CI: pin workflow contract via test (uses `openai/codex-action@v1`, passes `prompt-file`, reads `steps.run_codex.outputs.final-message`, preserves diff-exclude paths and comment markers). Currently only the wrapper-tag and closing-tag-escape strings are asserted. | `tests/test_openai_review.py`, `.github/workflows/ai_pr_review.yml` | #416 | Low |
144+
| `TestWorkflowDoesNotExecutePRHeadCode` (CodeQL #14 dismissal guard) does not model: `bash <script>` / `sh <script>` / `./<script>` / `source <script>` / `. <script>` direct shell-script execution; multi-line `python3 -c` bodies (line-by-line shlex can't reassemble across newlines — the workflow's 5 sanitizer bodies are exempt by invisibility); shell-variable-expansion indirection (`SCRIPT="$X"; python3 "$SCRIPT"`); `eval`; `find -exec`; `xargs -I {}`. Each represents a path by which PR-head bytes COULD execute without the test failing. The guard catches accidental regressions of common forms (16 tests covering pip/npm/cargo/maturin/etc. installs, python file exec, bash -c indirection with compound flags, env-var prefixes, line continuations, subshells/brace groups, single-line python -c, write-overwrites of allowlisted /tmp paths). Closing the residuals would require multi-line shell parsing with command-substitution awareness + script-execution allowlists — significant work for diminishing return given the dismissal's primary defense is the documented threat model on the alert and in `.github/workflows/ai_pr_review.yml` comment block. | `tests/test_openai_review.py`, `.github/workflows/ai_pr_review.yml` | #436 | Low |
144145
| Render `docs/methodology/REPORTING.md` and `docs/methodology/REGISTRY.md` as in-site Sphinx pages so cross-references can use `:doc:` instead of off-site GitHub `blob/main` URLs. Current state (#410 fix-audit-r2) restores navigable links via `blob/main`, but stable-docs readers can land on a different revision than the package version they are reading. Two viable paths: (a) add `myst-parser` to `docs/conf.py` extensions + docs extras and link with `:doc:`, or (b) convert both files to `.rst`. | `docs/conf.py`, `docs/api/business_report.rst`, `docs/api/diagnostic_report.rst`, `docs/tutorials/18_geo_experiments.ipynb`, `docs/tutorials/19_dcdh_marketing_pulse.ipynb` | follow-up | Low |
145146

146147
---

0 commit comments

Comments
 (0)