Skip to content
Merged
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
16 changes: 16 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Normalize line endings: store LF in the repository and check out LF,
# so shell blocks in action.yml and CI stay valid on Linux runners
# regardless of the contributor's OS or core.autocrlf setting.
* text=auto eol=lf

# Keep Windows-native scripts as CRLF (none today, listed for clarity).
*.bat text eol=crlf
*.cmd text eol=crlf

# Treat binaries explicitly so git never touches their bytes.
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.ico binary
*.pdf binary
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ on:
push:
pull_request:

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest
Expand Down
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,13 @@ __marimo__/
*.sarif
pr-comment.md
secscore-result.json
secscore-report.html

# Generated at runtime by the M.A.R.I.A policy import (overwritten every run)
policy/policy-maria.yml

# Scratch / test artifacts
tmp-*

# Allow SARIF examples
!examples/*.sarif
Expand Down
53 changes: 53 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,59 @@ The format is based on semantic versioning and follows a simple chronological re

---

## v0.5.0 — 2026-07

### Added

* Console entry point for installed environments:
`secscore pr ...` can now be used instead of `python -m secscore.cli.main pr ...`.
* Optional HTML report output generated from the standard JSON result:
`--html-output true` and `--html-out secscore-report.html`.
* GitHub Action inputs `html_output` and `html_out` for publishing the visual report as a workflow artifact.
* HTML report polish: dark/light toggle, risk summary, linked findings and artifacts,
copy JSON path action, collapsible execution parameters, and report footer metadata.
* Optional **M.A.R.I.A policy import** with `--maria-import-policy` and `--maria-policy-url`,
allowing SecScore to sync repository risk policy before scoring.
* M.A.R.I.A risk score model support (`maria_riskscore_v1`) including risk weights,
application context, and risk profile multipliers.

### Changed

* Package version bumped to `0.5.0`.
* GitHub Action now documents the workflow permissions needed for checks, PR comments,
and labels.
* CI workflow now declares explicit least-privilege read access with `permissions: contents: read`.
* PR comment renderer now honors the policy `reporting` block
(`max_findings_in_comment`, `max_reasons`, `include_fields`) instead of always
falling back to fixed defaults.

### Fixed

* `include_fields` in the policy `reporting` block is now actually applied when
rendering finding lines (location and metadata fields), instead of being ignored.

### Security

* Hardened M.A.R.I.A outbound requests against server-side request forgery by validating
URL schemes, rejecting embedded credentials, and blocking local/private/reserved network
targets by default. Private/local URLs require explicit trusted opt-in with
`SECSCORE_ALLOW_PRIVATE_MARIA_URLS=true`.
* Hardened CLI and SARIF file handling against uncontrolled path access by resolving paths
and requiring them to stay inside the current workspace or approved CI roots.
* Hardened the GitHub composite action against code injection by moving input interpolation
into environment variables and passing CLI arguments through quoted Bash arrays.
* Hardened the PR comment against Markdown injection from untrusted scanner output by
escaping finding titles, paths and metadata, and percent-encoding link targets.

### Repository

* Added `.gitattributes` enforcing LF line endings so the composite action's Bash steps
stay valid on Linux runners regardless of contributor OS.
* Ignored generated artifacts (`secscore-report.html`, runtime `policy/policy-maria.yml`,
`tmp-*`) and stopped tracking `tmp-result.json`.

---

## v0.4.0 — 2026-04

### Added
Expand Down
1 change: 1 addition & 0 deletions CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @cassiodeveloper
72 changes: 63 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ Install dependencies:

```
pip install -r requirements.txt
pip install -e .
```

---
Expand All @@ -116,7 +117,7 @@ pip install -r requirements.txt
1. Run with SARIF and policy:

```bash
python -m secscore.cli.main pr \
secscore pr \
--sarif tests/fixtures/review.sarif \
--policy policy/policy-pr.yml \
--no-diff-aware
Expand All @@ -125,11 +126,12 @@ python -m secscore.cli.main pr \
2. Check outputs:
- `pr-comment.md` (PR-ready markdown summary)
- `secscore-result.json` (structured result)
- Optional: `secscore-report.html` (visual report generated when `--html-output true`)

3. Optional: submit result to M.A.R.I.A:

```bash
python -m secscore.cli.main pr \
SECSCORE_ALLOW_PRIVATE_MARIA_URLS=true secscore pr \
--sarif tests/fixtures/review.sarif \
--policy policy/policy-pr.yml \
--maria-url http://localhost:5213/api/secscore/submissions \
Expand All @@ -147,7 +149,7 @@ Use these commands to validate expected outcomes quickly:
### PASS

```bash
python -m secscore.cli.main pr \
secscore pr \
--sarif tests/fixtures/pass.sarif \
--policy policy/policy-pr.yml \
--no-diff-aware
Expand All @@ -158,7 +160,7 @@ Expected: `Decision: PASS`
### REVIEW

```bash
python -m secscore.cli.main pr \
secscore pr \
--sarif tests/fixtures/review.sarif \
--policy policy/policy-pr.yml \
--no-diff-aware
Expand All @@ -169,7 +171,7 @@ Expected: `Decision: REVIEW`
### FAIL

```bash
python -m secscore.cli.main pr \
secscore pr \
--sarif tests/fixtures/fail.sarif \
--policy policy/policy-pr.yml \
--no-diff-aware
Expand All @@ -194,7 +196,7 @@ Expected: `Decision: FAIL`
Single SARIF file:

```
python -m secscore.cli.main pr \
secscore pr \
--sarif examples/example-snyk.sarif \
--policy policy/policy-pr.yml \
--no-diff-aware
Expand All @@ -203,7 +205,7 @@ python -m secscore.cli.main pr \
Multiple SARIF files (v0.3.0+):

```
python -m secscore.cli.main pr \
secscore pr \
--sarif semgrep.sarif,trivy.sarif \
--policy policy/policy-pr.yml \
--no-diff-aware
Expand All @@ -212,7 +214,7 @@ python -m secscore.cli.main pr \
Send consolidated findings to M.A.R.I.A (token provided at invocation):

```bash
python -m secscore.cli.main pr \
secscore pr \
--sarif semgrep.sarif,trivy.sarif \
--policy policy/policy-pr.yml \
--maria-url https://demo.mariaappsec.com/api/secscore/submissions \
Expand All @@ -226,10 +228,18 @@ For `/api/secscore/submissions`, SecScore auto-fills required submission fields
You can override them with:
`--maria-submission-key`, `--maria-commit-sha`, `--maria-branch-name`, `--maria-pipeline-name`, `--maria-pipeline-run-id`, `--maria-pull-request-id`.

### M.A.R.I.A policy import behavior

- When M.A.R.I.A integration is configured (`--maria-url`, `--maria-repository-id`, `--token`/`--maria-token`),
SecScore imports policy from M.A.R.I.A by default.
- The imported policy is saved on every run to `policy/policy-maria.yml`.
- The execution then uses `policy/policy-maria.yml` as the effective policy.
- Use `--maria-import-policy false` to keep using the local policy file from `--policy`.

For local PR testing without opening a real PR:

```bash
SECSCORE_PULL_REQUEST_ID=local-pr-001 python -m secscore.cli.main pr \
SECSCORE_ALLOW_PRIVATE_MARIA_URLS=true SECSCORE_PULL_REQUEST_ID=local-pr-001 secscore pr \
--sarif semgrep.sarif \
--policy policy/policy-pr.yml \
--maria-url http://localhost:5213/api/secscore/submissions \
Expand All @@ -252,10 +262,36 @@ Score: 85 / 100
Decision: PASS
```

Generate a visual HTML report from the standard JSON output:

```bash
secscore pr \
--sarif tests/fixtures/review.sarif \
--policy policy/policy-pr.yml \
--no-diff-aware \
--html-output true
```

The JSON result is always generated. When HTML output is enabled, SecScore also writes
`secscore-report.html` by default. Use `--html-out custom-report.html` to choose another path.

---

## GitHub Action

Recommended workflow permissions:

```yaml
permissions:
contents: read
checks: write
pull-requests: write
issues: write
```

SecScore needs `contents: read` to access the repository, `checks: write` to create the status check,
and `issues: write`/`pull-requests: write` to upsert PR comments and manage the review label.

Minimal example:

```yaml
Expand All @@ -281,6 +317,24 @@ Multiple scanners (v0.3.0+):
maria-token: ${{ secrets.MARIA_TOKEN }}
```

Generate and publish the HTML report as a workflow artifact:

```yaml
- name: Run SecScore
uses: cassiodeveloper/secscore@v1
with:
sarif: results.sarif
html_output: "true"

- name: Upload SecScore report
uses: actions/upload-artifact@v4
with:
name: secscore-report
path: |
secscore-result.json
secscore-report.html
```

Disable diff-aware:

```yaml
Expand Down
Loading
Loading