Tier 0: verdict integrity (HIGH tier, --exit-code, scanner fixes)#6
Merged
Conversation
Tier 0 (verdict integrity), scanner-correctness batch: - privacy: Required Reason stat()/statfs()/fstat() patterns now match real call sites with arguments (stat(path, &st)), not only the argument-less stat() form that almost never appears in source. Drop the broken \\.standard\\. UserDefaults clause (matched a literal backslash; UserDefaults already covers the real case). - codescan: hardcoded-ipv4 validates 0-255 octets so version/build strings like "2020.10.5.1" / "8.4.1.2" aren't misread as IPv4; widen the ignore to version/build/sdk/revision lines. - codescan: platform-reference no longer matches bare unquoted tokens (fired on virtually every React Native app via Platform.OS); only string/JSX literals, with ignores for Platform.*, imports, package names, and build config. - preflight: drain the previously-swallowed scanner error channel so a crashed sub-scanner surfaces as a WARN instead of a clean "no issues found". - verify: write the credential-bearing temp YAML at 0600, not 0644. - Tests covering each regex change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Tier 0 (verdict integrity), severity + CI-gating batch:
- codescan: new SeverityHigh tier between WARN and CRITICAL. The four
flow-dependent guidelines static analysis can only weakly assert -- missing
ATT (5.1.2), Sign in with Apple (4.8), Restore Purchases (3.1.1), account
deletion (5.1.1) -- move from WARN to HIGH. They are likely rejections, not
best-practice nits; labeling them WARN let rejectable apps read as GREENLIT.
- Severity now marshals to its NAME ("HIGH") instead of an integer ordinal, so
inserting a tier never shifts the JSON wire value for consumers.
- preflight + codescan: three-state headline -- NOT READY (critical) /
NEEDS REVIEW (high, no critical) / GREENLIT (neither). Summary gains a `high`
count. `passed` deliberately stays "no criticals" for backward compatibility
(README CI reads .summary.critical), so no existing behavior silently flips.
- preflight + verify: opt-in --exit-code flag for CI gating. preflight exits
non-zero on any CRITICAL/HIGH (or, with --verify, a failed flow); verify exits
non-zero on any failed/errored flow (it previously always exited 0, defeating
its purpose as a gate). Implemented via an ErrThreshold sentinel that main()
maps to a quiet exit 1; cobra error/usage printing moved to main().
- Tests: hard-rejection rules pinned at HIGH, summary High counting, name-based
JSON marshaling.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Closes the unit-test gap flagged in review (preflight had none): - computeSummary counts HIGH separately; Passed stays "no criticals". - dedup keeps the highest severity when scanners share a title. - preflightExit trips only with --exit-code, on critical/high or a failed flow. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- hardcoded-ipv4: drop build|sdk|revision from the ignore (unbounded substrings that swallowed real violations like `sdkEndpoint = "172.16.0.4"`). Octet validation already rejects version-shaped numbers; "version" still covers sdkVersion-style identifiers. - platform-reference: require the import `from '...'` ignore to match a module-path token (no spaces), so competitor copy like "Download from 'Google Play'" is no longer suppressed. - Tests pin both regressions. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A crashed sub-scanner is surfaced as a WARN ("Scanner did not complete"), but
preflightExit only failed on CRITICAL/HIGH, so `--exit-code` could pass in CI
even though a requested scanner (e.g. a malformed --ipa) never ran. Track it as
Result.Incomplete and fail the gate on it. Default behavior (no --exit-code) is
unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First of three PRs from a review of the scanner's correctness and CI story. This is Tier 0: the bugs that let a rejectable app read as GREENLIT, plus the CI gate.
Severity + verdict
passedis unchanged (still "no criticals"), so CI that reads.summary.criticalis unaffected.CI gating
--exit-codeon preflight and verify. preflight exits non-zero on any CRITICAL/HIGH (or, with --verify, a failed flow). verify exits non-zero on any failed/errored flow. verify previously always exited 0, which defeated its purpose as a gate.Scanner correctness
stat()/statfs()now match real call sites with args. The old patterns only matched the empty-paren form, so two categories never fired. Removed a broken\.standard\.clause.hardcoded-ipv4validates 0-255 octets so version strings like2020.10.5.1aren't flagged as IPs.platform-referenceno longer matches bare unquoted tokens, which fired on every React Native app viaPlatform.OS.--varvalues is written 0600, not 0644.Tests added for each change. build, vet, test green. Reviewed by a separate pass: no blocking issues.
Two calls for you
passed/GREENLIT or fail CI unless--exit-codeis passed. Say the word and I'll make HIGH block GREENLIT outright.--format jsonnow serializesseverityas a name ("HIGH") instead of an integer. Required so inserting a tier doesn't shift the wire value, and it matches preflight.Known follow-ups (not here)
--exit-code, not just WARN.