Skip to content

Harden findings parsing, fix 4 input-handling bugs, 4x tests + demos#6

Open
cognis-digital wants to merge 3 commits into
mainfrom
feat/harden-parsing-and-4x-depth
Open

Harden findings parsing, fix 4 input-handling bugs, 4x tests + demos#6
cognis-digital wants to merge 3 commits into
mainfrom
feat/harden-parsing-and-4x-depth

Conversation

@cognis-digital

Copy link
Copy Markdown
Owner

Summary

Deepens stigsentry across error handling, tests, and demos while keeping the
public API (scan, emit_poam, parse_findings_file, STIG_CONTROLS) stable.

Real bugs fixed

Each of these was reproduced before fixing:

  1. Malformed JSON silently swallowed. parse_findings_file used a bare
    except: return [], so a half-written/corrupt findings file scanned as zero
    findings — a false "all clear" on a compliance scan. Now raises
    FindingsParseError naming the offending path.
  2. Case-sensitive suffixes. .JSON / .CSV / .TSV (any non-lowercase
    case) were silently ignored. Now matched case-insensitively.
  3. Wrapper-object JSON crashed scan(). A {"findings": [...]} /
    {"results": [...]} / single-object payload — the shape most OpenSCAP/SCC
    exporters emit — raised AttributeError: 'str' object has no attribute 'get'.
    A new _coerce_findings normalizes all these shapes.
  4. Missing target path read as clean. scan("/no/such/path") reported
    items_scanned=1 with no findings instead of erroring. Now raises
    FileNotFoundError.

Also: emit_poam now writes UTF-8 explicitly and creates parent dirs;
normalize_control_id handles combined enhancements (AC-6(2)(a)) and a space
before the paren (AC-6 (2)).

New error-handling surface

  • scan(..., strict=True) re-raises parse errors (fail the build in CI).
  • Lenient mode (default) surfaces an unparseable file as a tracked MODERATE
    SS-PARSE-ERROR finding and continues scanning the rest of the directory.

Tests: 34 → 189

New suites: test_parse_errors, test_crosswalk, test_resolver_edges,
test_output_formats, test_cli, test_cognis_mil. Cover malformed configs,
missing/unknown STIG IDs, RMF mapping gaps, POA&M/OSCAL/SARIF output edges, the
air-gap snapshot export/import round-trip, and audit-log tamper detection. The
whole suite stays fully offline (network hard-blocked in conftest).

Demos: 5 → 20

Fifteen new runnable scenarios (each exits 0 under PYTHONUTF8=1), with
demos/run_all.py and docs/DEMOS.md updated. New scenarios cover malformed
input handling, exporter JSON shapes, the RMF mapping gap, control-ID
normalization, air-gap sneakernet, CI gate exit codes, the tamper-evident audit
trail, classification banners, severity rollup, CSV/TSV ingest, multi-format
export, POA&M→GRC mapping, OSCAL diffing, per-host triage, and a full end-to-end
pipeline.

Verification

  • python -m pytest -q189 passed, fully offline.
  • PYTHONUTF8=1 python demos/run_all.py → exit 0; each demo also exits 0 standalone.

Error handling / real bug fixes (public API unchanged):
- parse_findings_file: malformed JSON now raises FindingsParseError with the
  offending path instead of a bare `except` returning [] (which masked findings
  and produced a false "all clear" on a compliance scan).
- Case-insensitive file suffixes: .JSON / .CSV / .TSV are now ingested (were
  silently ignored by the case-sensitive .suffix comparison).
- Wrapper-object JSON: {"findings":[...]} / {"results":[...]} / single-object
  shapes (the common SCAP/SCC exporter shapes) no longer crash scan() with an
  AttributeError; _coerce_findings normalizes them.
- scan() on a missing target path now raises FileNotFoundError instead of
  reporting items_scanned=1 with zero findings.
- scan(strict=True) re-raises parse errors for CI; lenient mode (default)
  surfaces an unparseable file as a tracked MODERATE SS-PARSE-ERROR finding.
- emit_poam writes UTF-8 explicitly and creates parent dirs.
- normalize_control_id handles combined enhancements AC-6(2)(a) and "AC-6 (2)".

Tests: 34 -> 189 (test_parse_errors, test_crosswalk, test_resolver_edges,
test_output_formats, test_cli, test_cognis_mil). Edge cases + error paths:
malformed configs, missing/unknown STIG IDs, RMF mapping gaps, POA&M/OSCAL/SARIF
output, air-gap snapshot round-trip, audit-log tamper detection.

Demos: 5 -> 20 runnable scenarios (each exits 0, PYTHONUTF8=1), run_all.py and
docs/DEMOS.md updated.
The config used the v4 flat list form, which v5 rejects ('found unexpected type
for label docs'). Migrate to the v5 changed-files / any-glob-to-any-file shape so
the label workflow stops failing on every PR.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant