Commit fbcf3d0
committed
fix(groom): enforce path scope after the verifier + close four scoping holes (BE-4757)
Cursor-review panel follow-ups on the `path` input, in severity order.
- The scope filter ran only on the FINDER's output, but a `DOWNGRADE` verdict
explicitly reshapes a finding — so a cross-boundary candidate that legitimately
passed that filter could be narrowed onto its OUT-of-scope half and filed under
a directory it no longer belongs to. `verifier.md` now emits `sites`, and
`scope.py verify` re-applies the same ANY-in-scope rule to what the verifier
confirmed. A finding with no LOCATABLE site is KEPT there (the opposite of the
finder-side rule): `sites` is advisory on that schema, so dropping on it would
discard every survivor and read as an honest "nothing survived verification".
- `canonicalize_signature` forces the dedup key's scope component back to the
literal the brief handed out, so signature scope-independence no longer rests
on an untrusted model obeying `{{SIG_SCOPE}}`. Left alone when `scope_label`
itself contains a colon — component boundaries are ambiguous there, and
corrupting a working dedup key is worse than the double-filing it guards.
- `normalize_site` no longer relativizes an absolute path that is NOT under the
clone; it returns "" (unlocatable). Stripping the leading slash silently
reinterpreted `/services/api/x.go` as repo-relative, so an out-of-tree site
could satisfy a matching scope.
- `resolve_within` rejects a SYMLINKED scope even when it points inside the
repo. Verified against git: `git ls-files -- <link>` returns the link entry
alone, so groom.yml's non-empty guard passed while the finder audited nothing
and reported clean. The error names the fix (pass the real directory).
- `list_files` reads bytes and decodes with surrogateescape: one non-UTF-8
tracked filename previously raised UnicodeDecodeError and killed the scoped
audit before the finder ran. `printable_path` drops surrogates too, and the
omitted count is now WARNED rather than silently shortening the list.
- `run_audited` compares the `(scoped: <path>)` marker case-SENSITIVELY, so
`services/api` and `services/API` keep separate cadence clocks instead of one
silently suppressing the other's due tick.
- Every caller-controlled value reaches argparse as `--flag=value`: a directory
named `-foo` is valid per the charset and the bare form reads it as an option.1 parent f297fcc commit fbcf3d0
7 files changed
Lines changed: 572 additions & 30 deletions
File tree
- .github
- groom
- tests
- workflows
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
39 | 39 | | |
40 | 40 | | |
41 | 41 | | |
42 | | - | |
| 42 | + | |
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
46 | 46 | | |
47 | 47 | | |
48 | 48 | | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
49 | 53 | | |
50 | 54 | | |
51 | 55 | | |
52 | | - | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
53 | 60 | | |
54 | 61 | | |
55 | 62 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
243 | 243 | | |
244 | 244 | | |
245 | 245 | | |
246 | | - | |
| 246 | + | |
247 | 247 | | |
248 | | - | |
| 248 | + | |
| 249 | + | |
249 | 250 | | |
250 | 251 | | |
251 | 252 | | |
252 | 253 | | |
253 | 254 | | |
254 | | - | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
255 | 265 | | |
256 | 266 | | |
257 | 267 | | |
| |||
0 commit comments