Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/actions.lock
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ workflows:
- 'dependabot/fetch-metadata@v3.1.0'
'.github/workflows/dogfood-gate.yml':
- 'actions/checkout@v7.0.1'
- 'hyperpolymath/a2ml-ecosystem@main'
- 'hyperpolymath/deed-ecosystem@main'
- 'hyperpolymath/k9-ecosystem@main'
'.github/workflows/estate-rescan.yml':
- 'actions/cache@v6.1.0'
Expand Down Expand Up @@ -294,14 +294,14 @@ dependencies:
commit: 'sha1-6037f33647c3f17758a2356c80fc4a53d7e0685d'
owner_id: 75048950
repo_id: 623796603
'hyperpolymath/a2ml-ecosystem@main':
'hyperpolymath/deed-ecosystem@main':
ref: 'main'
commit: 'sha1-c992d2882ee1e62bf5c78b5f9a1893a6a16730e4'
commit: 'sha1-f7a40a4d5cc82b2e73f861119baa6818d77a448d'
owner_id: 6759885
repo_id: 1275649586
'hyperpolymath/k9-ecosystem@main':
ref: 'main'
commit: 'sha1-3f250fba42e432c7ff47b48f59525bec3357136b'
commit: 'sha1-2155aa26a21758f2ba119f61bc7e0e1981c106fb'
owner_id: 6759885
repo_id: 1275650185
'ruby/setup-ruby@v1.321.0':
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/dogfood-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:

- name: Validate A2ML manifests
if: steps.detect.outputs.count > 0
uses: hyperpolymath/a2ml-ecosystem/validate-action@main
uses: hyperpolymath/deed-ecosystem/validate-action@main
with:
path: '.'
strict: 'false'
Expand Down
64 changes: 54 additions & 10 deletions lib/hypatia/cli.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ defmodule Hypatia.CLI do
cicd_rules,code_safety,migration_rules,scorecard,
green_web,git_state,dependabot_alerts,
secret_scanning_alerts,code_scanning_alerts,
structural_drift,implementation_inside_canon
structural_drift,implementation_inside_canon,
content_patterns
--format <fmt> Output format: json (default), text, github, sarif
--severity <lvl> Minimum severity to report: critical, high, medium (default), low, info
--path <dir> Path to scan (alternative to positional argument)
Expand All @@ -54,7 +55,8 @@ defmodule Hypatia.CLI do
:secret_scanning_alerts,
:code_scanning_alerts,
:structural_drift,
:implementation_inside_canon
:implementation_inside_canon,
:content_patterns
Comment thread
coderabbitai[bot] marked this conversation as resolved.
]

@severity_order %{
Expand Down Expand Up @@ -299,13 +301,17 @@ defmodule Hypatia.CLI do
# ─── Finding collection across rule modules ──────────────────────────

@doc """
Run the named rule modules against `repo_path` and return normalized findings
(`%{rule_module, type, severity, file, reason, action}`). Public so the RSR
conformance oracle can delegate content-scan criteria to the live scanners
rather than reimplement per-file detection. `rules` is a list of module atoms
(e.g. `[:cicd_rules, :structural_drift]`); GitHub-API modules
(`:dependabot_alerts`, `:secret_scanning_alerts`, `:code_scanning_alerts`,
`:scorecard`) require network + token and return nothing offline.
Run the named rule modules against `repo_path` and return unsuppressed findings
normalised as `%{rule_module, type, severity, file, reason, action}` maps.
Content-pattern findings also include their one-based source `line`. Public so
the RSR conformance oracle can delegate content-scan criteria to the live
scanners rather than reimplement per-file detection.

`rules` is a list of module atoms (for example, `[:content_patterns,
:structural_drift]`). GitHub alert modules (`:dependabot_alerts`,
`:secret_scanning_alerts`, and `:code_scanning_alerts`) require network access
and credentials; when unavailable, they write a warning to standard error and
contribute no findings.
"""
def collect_findings(repo_path, rules) do
results = []
Expand Down Expand Up @@ -818,6 +824,43 @@ defmodule Hypatia.CLI do
results
end

# ─── Content-pattern rules ───────────────────────────────────────────
#
# `CicdRules.scan_content_patterns/1` is a glob+regex, per-line content
# engine over the `@blocked_patterns` table. It shipped complete but
# unwired: until now nothing in `lib/` called it, so every table entry
# carrying `:pattern` + `:applies_to` was dormant and only its unit test
# ever exercised it. Wiring it here makes rule authoring a matter of
# adding a table row rather than writing a module.
#
# This is the only branch that emits a real `:line`. Everything else
# normalizes without one, which is why SARIF's `startLine` was uniformly
# 1 before this landed. Suppression is NOT applied here -- the uniform
# pass below funnels every finding through ScannerSuppression exactly
# once, and doing it twice would be both redundant and a second place
# for exemptions to silently diverge.
results =
if :content_patterns in rules do
normalized =
repo_path
|> Hypatia.Rules.CicdRules.scan_content_patterns()
|> Enum.map(fn f ->
%{
rule_module: "content_patterns",
severity: to_string(Map.get(f, :severity, "medium")),
type: to_string(f.rule),
file: f.file,
line: f.line,
reason: f.reason,
action: "flag"
}
end)

results ++ normalized
else
results
end

# ─── Uniform suppression pass ──────────────────────────────────────
#
# Several rule paths above (structural_drift, code_scanning_alerts,
Expand Down Expand Up @@ -1301,7 +1344,8 @@ defmodule Hypatia.CLI do
migration_rules,scorecard,green_web,
git_state,dependabot_alerts,
secret_scanning_alerts,code_scanning_alerts,
structural_drift,implementation_inside_canon
structural_drift,implementation_inside_canon,
content_patterns
--format, -f <fmt> Output format: json (default), text, github, sarif, sarif
--severity, -s <lvl> Minimum severity: critical, high, medium (default), low
--path, -p <dir> Path to scan (alternative to positional arg)
Expand Down
Loading
Loading