Skip to content

Wave 7: API fuzzing, committed-data check, offline Scorecard, CI liveness rule, audit-pr area budget - #2149

Merged
remigiusz-antczak merged 2 commits into
mainfrom
land/wave-1030w7
Oct 30, 2026
Merged

remigiusz-antczak merged 2 commits into
mainfrom
land/wave-1030w7

Conversation

@remigiusz-antczak

@remigiusz-antczak remigiusz-antczak commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

Wave 7: six independently reviewed lanes in 1dcc88a3a, plus 0dda58e0b, which rewraps one docstring line that tripped the CI mktemp gate.

What changes

  1. API fuzzing. app_pentest.sh --openapi SPEC runs schemathesis under the ZAP and nuclei target rails: GET and HEAD only unless --active, a proxy-based block on other hosts (residual documented), one lead per failure.
  2. Committed personal data. A new review_checks.sh step reports a file with 10 or more distinct email-shaped strings by path and count only, plus a repository-total row.
  3. Offline Scorecard for a git DIR. Nine offline-safe checks on a tracked-files export instead of SKIPPED; Vulnerabilities never runs offline.
  4. CI liveness rule. A review confirms workflows run before it claims CI coverage or recommends a CI-only fix.
  5. Audit PR-body budget per area. comms_lint --kind audit-pr budgets each area separately.
  6. Load-tolerant guard test. One 60 s ceiling, pinned by a test.

Verification

  • 59 of 59 affected suites pass on 39d5d4b40, whose tree is identical to 1dcc88a3a.
  • On 0dda58e0b, which changes only 2 docstring lines: the mktemp gate and the identity gate pass; CI's run on this head covers the rest.

🤖 Generated with Claude Code

remigiusz-antczak and others added 2 commits October 30, 2026 09:03
…mmitted-personal-data check, CI liveness rule, comms_lint audit-pr area budget

Review hub:
- New committed-data step in review_checks.sh (after invisible-chars):
  committed_personal_data.py counts the distinct email-shaped strings per
  tracked file, binary data included, and reports a file at or above 10 by
  path and count only, never an address. gitleaks, trufflehog and semgrep look
  for secrets, so a committed export of real people's addresses passed the hub
  clean. Changed files in diff mode, every tracked file under --full.
- A repository-total row (path ".", --repo-threshold, default 50) sums the
  addresses of files that stay below the file threshold, so a leak spread one
  address per file is not silent.
- Compressed and columnar files the scan cannot read (parquet, Arrow, ORC,
  zip, gzip, zstd, xz, 7z, lz4 frame, bzip2, Avro, PDF, zlib) get a
  not-checked row (path and format only) instead of a silent pass. Parquet,
  Arrow and ORC need their footer magic as well, and a bare magic is not a
  container.
- Reserved example and test names, asset-scale names such as icon@2x.png and
  scp-style git@ remotes are not counted. --max-bytes is range-checked.
  method-situational.md names the step and its rows.

Supply chain:
- supply_chain_check.sh scores a git DIR with OpenSSF Scorecard offline when
  --scorecard owner/repo is not given, instead of printing SKIPPED. It scans a
  git archive export of the repo root's HEAD (tracked files only, so an
  untracked node_modules cannot score Binary-Artifacts 0) and runs only the
  checks that work offline: Binary-Artifacts, Dangerous-Workflow,
  Dependency-Update-Tool, License, Packaging, Pinned-Dependencies, SAST,
  Security-Policy and Token-Permissions. Vulnerabilities is never run (it
  reported a false 10 while api.osv.dev was unreachable) and Fuzzing errors
  offline. Scores stay informational; the ok line says the view is partial
  and not comparable with a public score.
- The export is removed by an EXIT trap set right after mktemp, so SIGTERM and
  SIGHUP no longer leave it in $TMPDIR. git archive runs with
  GIT_NO_LAZY_FETCH=1, so a partial clone is SKIPPED instead of fetching blobs.
  A subdirectory DIR scores the whole repo root, and the output says so.

Communication structure:
- comms_lint --kind audit-pr: the 1200-word, 160-line budget counts everything
  outside "## Changes by area"; inside it each "### " area fails above 200
  words and the whole body fails above 3000 words. A body written to the
  required structure with many areas no longer fails for its area text.
  Eval audit-pr-multi-area-body-budget added.
- The placeholder rule no longer flags a mktemp template (3 or more uppercase X
  inside a single-backtick span on one line); TBD, TODO and a lone XXX in prose
  still fail, and <FILL>, <fill in> and <fill me> now fail.

Review method:
- domain-k.md: a workflow file is not CI coverage until it runs. Before
  claiming CI coverage or recommending a CI-only fix, a review confirms
  workflows fire (gh api repos/<owner>/<repo>/actions/permissions --jq
  .enabled, gh run list -L 5). If Actions is off or unknown it says so and
  aims the fix at the gate that does run, or flags re-enabling Actions as an
  owner decision. A real review recommended a CI step for a repo whose Actions
  was disabled, so the step would never have run. Eval
  ci-only-fix-where-actions-is-disabled-confirm-workflows-run added.

Delivery checks:
- test_destructive_guard_w21.py waits on the guard with one 60 s ceiling
  instead of 20 s (it failed once at a load average near 13). A new test pins
  the ceiling, that a hang still fails, and that the guard's own watchdog
  stays at most 20 s.

Live app testing:
- app_pentest.sh --openapi SPEC fuzzes the validated target's API with
  schemathesis under the same rails as ZAP and nuclei. SPEC is a local file
  or an http(s) URL; a URL must pass every target rule and is read once (no
  redirects, no env proxies, 10 s timeout, 10 MB cap), and schemathesis gets
  that copy. Passive mode sends only GET and HEAD; --active drops the method
  filter and runs only for a listed loopback or private host. --origin pins
  requests to the target, the coverage phase is off and an empty config file
  is pinned.
- Egress block: schemathesis runs with every proxy variable pointed at a
  closed loopback port and no_proxy set to the target host, so a remote $ref
  or externalValue that the early text check misses cannot be fetched from
  another host, target traffic goes direct, and the caller's own proxy cannot
  divert it. Residual: the same host on another port, its subdomains, and a
  fetcher that ignores proxy variables.
- An unreadable spec, one over 10 MB, or one with a remote $ref or
  externalValue in its text exits 2 before any tool starts; a spec
  schemathesis cannot load ends as error. The JSON adds openapi.tested and
  openapi.errored. Each failure is one lead per code and operation: medium
  for 5xx, 5xx on an undeclared Content-Type, unenforced authentication and a
  server that stopped answering; low otherwise.

Tests: 59/59 affected suites (run-ci-tests.sh --affected 6611ca8 on the
assembled tree 39d5d4b40); diff --check, fragments, tests-wired (485 tests,
473 run by CI, 12 allowlisted) and the size ratchet pass; test-ci-gates.sh is
left to CI.

size-budget-raise: .claude/skills/communication-structure/references/artifact-templates.md 9234→9443 the audit-pr paragraph states the budget scope and the two area and body caps
size-budget-raise: .claude/skills/deep-code-review/references/supply-chain-check.md 3421→3646 the scorecard table row states the offline git-DIR mode, its whole-repo scope and the partial offline view
size-budget-raise: .claude/skills/deep-code-review/references/method-situational.md 43864→44018 the analyzer list names the committed-data step and its rows
size-budget-raise: .claude/skills/deep-code-review/references/domain-k.md 5188→5674 the liveness rule (one checklist bullet plus one red-flag clause)
size-budget-raise: .claude/skills/deep-code-review/references/app-pentest.md 3033→6344 the --openapi safety rules, the egress block, the schemathesis flags with their reasons, the status semantics and the severity map

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CI's cheap job failed its "mktemp TMPDIR regression" step on PR head
1dcc88a. The BARE pattern in scripts/test-mktemp-tmpdir.sh matched line 8
of .claude/skills/communication-structure/scripts/comms_lint.py, a docstring
line that ended with the words "a mktemp": a line that ends in mktemp reads
as a bare call with no template.

Move the word "mktemp" to the start of the next docstring line. Same bytes,
same words, same line count; no code, SKILL.md, reference, index, checksum
or size-budget row is touched.

Checked locally with BASE_SHA=6611ca89b and HEAD_SHA=HEAD: the mktemp gate
passes, and so does every later step of the cheap job (steps 02 to 18 of
ci.yml, run one at a time; the regenerate-unlanded step skipped). Two caveats
on this host: python3 pointed at 3.12 to match CI, and two self-tests that
call ps ran against a small ps stand-in because the sandbox denies /bin/ps.

Tests: 17/17 cheap-job steps

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@remigiusz-antczak
remigiusz-antczak merged commit 3fae8b7 into main Oct 30, 2026
8 checks passed
@remigiusz-antczak
remigiusz-antczak deleted the land/wave-1030w7 branch October 30, 2026 09:03
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