Skip to content

feat(scanner): structural analyzer for Actions poll bounds - #1133

Draft
seonghobae wants to merge 4 commits into
sentinel/detect-transport-only-poll-bound-1087from
feat/actions-poll-structural-analyzer-1087
Draft

feat(scanner): structural analyzer for Actions poll bounds#1133
seonghobae wants to merge 4 commits into
sentinel/detect-transport-only-poll-bound-1087from
feat/actions-poll-structural-analyzer-1087

Conversation

@seonghobae

Copy link
Copy Markdown
Contributor

Successor of #1088. This stacked G-06 slice adds a bounded structural GitHub Actions + shell control-flow analyzer without replacing the packaged regex family.

It preserves detector IDs github-actions-transport-only-poll-bound and github-actions-transport-failure-budget-poll-bound and all existing regex corpus as migration oracles.

This pull request does not Close #1087 or #1088. ADR-0009 Status is Proposed.

What this adds

  • classify_poll_loops(workflow_text) in appguardrail_core/actions_poll_analyzer.py
  • Loop-local causal safety: initialization must precede this loop; helper/sibling bounds cannot donate; forward -gt/-ge and statically positive owning-job timeout-minutes / ${{ N }} are total bounds; reversed, unreachable, zero/negative/dynamic, and quoted/comment text are not
  • Additive analyzer only: existing regex YAML rules are unchanged; this slice does not hook _scan_file

Verification

Focused tests: tests/test_actions_poll_structural_analyzer.py, tests/test_github_actions_poll_bound_control_flow_regression.py, tests/test_github_actions_poll_bounds.py.

Add failing regressions for a loop-local GitHub Actions + shell
control-flow analyzer so transport-only poll bounds cannot borrow
helper, sibling, reversed, or unreachable safety.
Classify conventional GitHub Actions while-polls by causal control
flow so a transport-failure budget cannot stand in for a total bound.
Record ADR-0009 as Proposed and add a changelog fragment. Regex
detector IDs stay migration oracles; this successor does not close
#1087 or #1088.
@coderabbitai

coderabbitai Bot commented Sep 7, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

seonghobae added a commit that referenced this pull request Sep 7, 2026
Summary:
- Snapshot 06:01 UTC records Draft #1133 `529ecb0` stacked on #1088.
- ADR-0009 remains Proposed; regex detector IDs stay migration oracles.

Rationale:
- #999 is the single writer of the product-technical gap baseline.
- Analyzer-only slice is not protected scanner emission.

Tests:
- documentation-only; analyzer evidence lives on #1133
Measure 100% statement and branch coverage of
appguardrail_core/actions_poll_analyzer.py on stacked PR heads.

Issues 1087 and 1088 stay open. The analyzer is not hooked into
_scan_file, and regex YAML is unchanged.

Copy link
Copy Markdown
Contributor Author

Added a dedicated exact-head coverage workflow at .github/workflows/actions-poll-analyzer-coverage.yml.

It checks out this stacked head and measures 100% statement and branch coverage of appguardrail_core/actions_poll_analyzer.py, running tests/test_actions_poll_structural_analyzer.py plus the existing issue 1088 poll regex tests.

Concurrency is actions-poll-analyzer-coverage-{repository}-{PR number} and fails closed when the PR number is missing.

Issues 1087 and 1088 stay open. This does not retarget off 1088, does not hook _scan_file, and does not rewrite regex YAML. Draft status is unchanged.

Copy link
Copy Markdown
Contributor Author

Follow-up evidence, not approval.

Exact head is now 5baeab93de2a940b024dd31463ce7417ae990e3a. Dedicated workflow .github/workflows/actions-poll-analyzer-coverage.yml uses concurrency actions-poll-analyzer-coverage-{repository}-{PR number} and fails closed without a PR number. Local 162 tests / 100% analyzer statement+branch coverage. Hosted exact-head coverage was queued on this head; predecessor 529ecb0 GREEN does not transfer.

Stay Draft. Do not Close #1087 or #1088. Do not hook _scan_file on this slice.

seonghobae added a commit that referenced this pull request Sep 7, 2026
Summary:
- Snapshot 06:16 UTC records #1133 `5baeab9` with
  actions-poll-analyzer-coverage and a queued exact-head job.
- Hosted coverage is queued, not claimed GREEN.

Rationale:
- Stacked PRs targeting #1088 do not inherit develop-only coverage
  workflows. The PR-number-bound job is the exact-head evidence path.

Tests:
- documentation-only; analyzer coverage evidence lives on #1133
seonghobae added a commit that referenced this pull request Sep 7, 2026
Summary:
- Snapshot 07:21 UTC records Draft #1134 `4404840` stacked on #1129.
- Inventory is evidence, not permission; undeclared executables fail
  admission. Hosted #1133 coverage remains queued, not GREEN.

Rationale:
- #999 is the single writer of the product-technical gap baseline.
- #1099 remaining surfaces stay on stacked successors, not Close.

Tests:
- documentation-only; detector evidence lives on #1134 (638/638)
seonghobae added a commit that referenced this pull request Sep 7, 2026
Summary:
- Snapshot 08:25 UTC records Draft #1135 `81e83f4` stacked on #1134.
- Archive path traversal and unadmitted submodules fail closed.
- #1134 restack head is `0cd4329`; #1133 coverage remains queued.

Rationale:
- #999 is the single writer of the product-technical gap baseline.
- #1099 remaining surfaces stay on stacked successors, not Close.

Tests:
- documentation-only; detector evidence lives on #1135 (997/997)
seonghobae added a commit that referenced this pull request Sep 7, 2026
Refresh the single-writer gap baseline from live exact-head evidence:
Draft #1150 on #1146, concurrent #1148 sentinel, and G-06 #1133
exact-head coverage SUCCESS. Relates to #1099.

seonghobae commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

Stacked successor Draft #1152 (feat/actions-poll-analyzer-emit-1087 @ 255cfd866efd971396e132992a474074487f1939) now hooks classify_poll_loops into production _scan_file without rewriting the regex YAML.

It preserves detector IDs github-actions-transport-only-poll-bound and github-actions-transport-failure-budget-poll-bound, merges regex plus analyzer hits by (rule_id, file) so the historical vulnerable fixture still emits count==1, and keeps the historical fixed fixture negative. Analyzer-only helper-loop / reversed / unreachable / split-do cases that regex adjacency misses can now be reported.

This does not Close #1087, #1088, or #1133.

seonghobae added a commit that referenced this pull request Sep 7, 2026
Summary:
- Snapshot 15:28 UTC records Draft #1151 `822ca12` on #1150 and
  Draft #1152 `255cfd8` on #1133.
- `_scan_file` emits poll analyzer findings once per (rule_id, file).
- Deceptive read-only descriptions fail closed when inventory shows
  write or egress.

Rationale:
- #999 is the single writer of the product-technical gap baseline.
- G-06 emission waited on #1133 exact-head coverage SUCCESS.

Tests:
- documentation-only; evidence lives on #1151 (1560/1560) and #1152
  (417/417 analyzer statements)
@seonghobae seonghobae added enhancement New feature or request priority: medium Normal-priority or P2 work labels Sep 8, 2026 — with ChatGPT Codex Connector
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request priority: medium Normal-priority or P2 work

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

1 participant