Skip to content

Suppression with line_start but no line_end is matched as open-ended, but lint message claims it defaults to line_start #347

Description

@rafaelpereyra

Summary

There is an inconsistency between what ash config lint tells the user about a suppression with only line_start set, and what _line_range_matches actually does at scan time.

  • Lint message (config_linter.py::_check_suppression_issues):

    "Suppression has 'line_start' (N) but missing 'line_end' — will default to line_start value"

  • Matcher (suppression_matcher.py::_line_range_matches) treats line_end=None as open-ended ("from line_start to end of file"), not as line_end=line_start.

The matcher and the suppression-id generator also disagree with each other:

  • _line_range_matches (matching) treats missing line_end as +∞.
  • _get_suppression_id (in both sarif_utils.py and unused_suppressions_reporter.py) substitutes line_start for missing line_end when building the dedupe key.

Why it matters

  • A user sets line_start: 42 expecting "only line 42", but every finding on line ≥ 42 in that file matches. This silently over-suppresses.
  • The lint warning gives users false confidence about the runtime semantics.

Reproduction

global_settings:
  suppressions:
    - path: "src/foo.py"
      rule_id: "B201"
      line_start: 42
      reason: "False positive"

A finding at src/foo.py:99 with rule_id=B201 is suppressed, even though the user only specified line 42.

Relevant code

  • automated_security_helper/utils/suppression_matcher.py::_line_range_matches — branch if suppression.line_start is not None and suppression.line_end is None: returns true for finding_end >= suppression.line_start.
  • automated_security_helper/config/config_linter.py::_check_suppression_issues — emits the misleading "will default to line_start value" message.
  • automated_security_helper/utils/sarif_utils.py::_get_suppression_id and automated_security_helper/plugin_modules/ash_builtin/reporters/unused_suppressions_reporter.py::_get_suppression_id — substitute line_start for missing line_end in the ID.
  • automated_security_helper/models/core.py::AshSuppressionline_end description is just (Optional) Ending line number; doesn't document missing-value semantics.

Proposed fix (pick one and align everything)

Option A — make missing line_end mean "single line" (matches lint message, matches user intuition, matches _get_suppression_id):

  • Change _line_range_matches to default line_end = line_start when missing.
  • Update AshSuppression.line_end docstring to say so.
  • Keep current lint message and _get_suppression_id behavior.

Option B — keep open-ended semantics (current matcher behavior):

  • Update _line_range_matches docstring to document open-ended behavior.
  • Update lint message in _check_suppression_issues to:

    "Suppression has 'line_start' (N) but missing 'line_end' — will match all findings from line N to end of file. Set line_end explicitly."

  • Update _get_suppression_id in both sarif_utils.py and unused_suppressions_reporter.py to use a sentinel like * (or EOF) instead of line_start for missing line_end, so unused-suppression dedupe matches the actual semantics.
  • Update AshSuppression.line_end docstring.

Option A is the lower-risk choice; Option B is a behavior change for anyone relying on the current open-ended behavior.

Acceptance criteria

  • ash config lint message and the runtime matcher behavior agree.
  • _get_suppression_id is consistent across sarif_utils.py and unused_suppressions_reporter.py and reflects the chosen semantics.
  • AshSuppression.line_end docstring documents the semantics of the missing case.
  • Tests in tests/unit/utils/test_suppression_matcher_extended.py cover the missing-line_end case explicitly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions