The Semgrep patterns node is a YAML list (not dict), so the previous
implementation's .get() call on patterns would fail with AttributeError.
Fix: properly handle 'patterns' as a list of alternation groups, each
containing pattern-either -> patterns -> pattern-not entries. This
ensures the BDD assertion robustly finds bare raise pattern-nots in
the xml-no-suppressed-exception rule's nested structure.
Issues Closed: #9103
Document HAL 9000's contribution of the broad exception suppression
Semgrep guard (PR #9185, issue #9103) in CONTRIBUTORS.md per the
PR compliance checklist requirement.
Address blocking issues from PR review by HAL9001 (review #7080):
1. Add success_codes=[0, 1] to noxfile.py semgrep invocation so
the lint session runs in proper audit mode without failing CI on
the ~337 existing violations during phased rollout.
2. Strengthen BDD bare re-raise assertion: replace weak string search
for 'raise' with structured parsing of YAML pattern-not entries to
specifically verify bare raise patterns exist within the rule's
pattern-not configurations.
3. Add CHANGELOG.md entry under [Unreleased] documenting the Semgrep
guard implementation and its audit-mode migration strategy.
Issues Closed: #9103
Add 12 new Behave BDD scenarios to features/security_scan_hooks.feature
to automatically validate the Semgrep broad exception suppression rules
and their escape hatch behavior, as suggested by reviewer HAL9001.
New scenarios verify:
- python-no-suppressed-exception rule exists and targets src/
- python-no-suppress-exception rule exists and targets src/
- Both rules document the nosemgrep escape hatch in their messages
- Both rules document the error-propagation: allow annotation
- python-no-suppressed-exception has pattern-not for bare re-raise
- python-no-suppressed-exception has pattern-not for exception chaining
- Nox lint session integrates Semgrep and references .semgrep.yml
All 25 scenarios pass (13 original + 12 new).
ISSUES CLOSED: #9103
Fix broken escape hatch mechanism and address reviewer feedback:
- Replace non-functional comment-based pattern-not clauses with Semgrep's native # nosemgrep mechanism for the escape hatch. Semgrep strips comments from the AST so pattern-not clauses matching inline comments never fire; # nosemgrep is the only reliable per-line suppression mechanism.
- Require both # nosemgrep: <rule-id> AND # error-propagation: allow on the same line: the former is the actual suppression, the latter is the mandatory human-readable audit annotation.
- Add raise $EXC from $CAUSE pattern-not entries for both Exception and BaseException variants to prevent false positives on legitimate exception chaining (raise ServiceError from e).
- Switch nox -s lint Semgrep invocation to audit mode (no --error) for the phased rollout: the codebase has ~337 existing suppressions that must be triaged before enforcement mode is enabled. A comment in noxfile.py documents the migration path and references #9103.
- Update CONTRIBUTING.md examples and enforcement description to reflect the dual-comment requirement.
Fixed two critical issues with the Semgrep rules for broad exception suppression:
1. **Escape hatch mechanism**: Replaced the broken `# error-propagation: allow` comment-based escape hatch with Semgrep's native `# nosemgrep` comment support. Semgrep strips comments from the AST, so pattern-not clauses looking for inline comments never match. The native `# nosemgrep` comment is properly supported by Semgrep and provides a reliable override mechanism.
2. **Missing exception chaining pattern**: Added `raise $EXC from $CAUSE` pattern-not entries for both `Exception` and `BaseException` variants. This prevents false positives when legitimate exception chaining is used (e.g., `raise ServiceError("context") from e`), which is an allowed pattern per CONTRIBUTING.md.
Updated both `python-no-suppressed-exception` and `python-no-suppress-exception` rules with these fixes. The escape hatch now works reliably and exception chaining is properly recognized as an allowed pattern.
ISSUES CLOSED: #9103
Added two new Semgrep rules to enforce the CONTRIBUTING.md guideline against broad exception suppression:
- python-no-suppressed-exception: Detects except Exception/BaseException blocks without re-raising
- python-no-suppress-exception: Detects contextlib.suppress(Exception/BaseException) usage
Both rules support an escape hatch annotation '# error-propagation: allow' for documented recovery logic.
Integrated Semgrep into the nox lint session to run alongside Ruff checks.
Updated CONTRIBUTING.md to document the escape hatch policy and automated enforcement.
Pre-commit hook already configured to run these rules.
ISSUES CLOSED: #9103