Skip to content

Commit 2aa4fd3

Browse files
authored
Merge branch 'main' into dependabot/github_actions/github/codeql-action-4.36.2
2 parents 871331f + c1701e4 commit 2aa4fd3

55 files changed

Lines changed: 3462 additions & 254 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitattributes

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
* text=auto
2+
.gitattributes text eol=lf
23
*.cpp text eol=lf
34
*.hpp text eol=lf
45
*.h text eol=lf
56
*.md text eol=lf
67
*.json text eol=lf
8+
*.toml text eol=lf
79
*.yml text eol=lf
810
*.yaml text eol=lf
911
*.txt text eol=lf
1012
*.csv text eol=lf
13+
*.log text eol=lf
1114
CMakeLists.txt text eol=lf
1215
CMakePresets.json text eol=lf
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Repo Sentinel
2+
3+
on:
4+
push:
5+
pull_request:
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: read
10+
11+
jobs:
12+
repo-sentinel:
13+
name: Repo Sentinel
14+
runs-on: ubuntu-latest
15+
16+
steps:
17+
- name: Checkout
18+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
19+
20+
- name: Set up Python
21+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
22+
with:
23+
python-version: "3.14"
24+
25+
- name: Install repo-sentinel-lite
26+
run: |
27+
python -m venv "$RUNNER_TEMP/repo-sentinel-venv"
28+
"$RUNNER_TEMP/repo-sentinel-venv/bin/python" -m pip install --upgrade pip
29+
"$RUNNER_TEMP/repo-sentinel-venv/bin/python" -m pip install repo-sentinel-lite
30+
31+
- name: Run repository hygiene gate
32+
run: |
33+
"$RUNNER_TEMP/repo-sentinel-venv/bin/repo-sentinel" scan \
34+
--fail-on-severity error \
35+
--format text \
36+
.

.reposentinel.toml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# LogLens uses repo-sentinel-lite as a narrow hygiene gate:
2+
# required repository files plus accidental sensitive filenames.
3+
#
4+
# High-entropy content scanning is intentionally disabled here so fixture logs
5+
# and C++ build outputs do not affect this gate.
6+
max_text_file_size = 0
7+
entropy_threshold = 999.0
8+
9+
ignore_globs = [
10+
"build/**",
11+
"build_manual*",
12+
"out/**",
13+
"report.md",
14+
"report.json",
15+
"*.exe",
16+
"CMakeFiles",
17+
"CMakeFiles/**",
18+
"CMakeCache.txt",
19+
"cmake_install.cmake",
20+
"compile_commands.json",
21+
"*.vcxproj.user",
22+
]

CHANGELOG.md

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@ All notable user-visible changes should be recorded here.
66

77
### Added
88

9-
- Added sanitized golden `report.md` / `report.json` regression fixtures to lock report contracts.
10-
- Expanded parser coverage for `Accepted publickey` and selected `pam_faillock` / `pam_sss` variants.
11-
- Added compact host-level summaries for multi-host reports.
12-
- Added optional CSV export for findings and warnings when explicitly requested.
9+
- None yet.
1310

1411
### Changed
1512

@@ -23,6 +20,47 @@ All notable user-visible changes should be recorded here.
2320

2421
- None yet.
2522

23+
## v0.5.0
24+
25+
### Added
26+
27+
- Stabilized the JSON report artifact contract as `loglens.report.v2` with
28+
`schema_version` set to `2`.
29+
- Added finding explainability fields to JSON findings, including `rule_id`,
30+
`subject_kind`, `subject`, `grouping_key`, `window_start`, `window_end`,
31+
`threshold`, `observed_count`, `evidence_event_ids`, and `verdict_boundary`.
32+
- Added sanitized golden `report.md`, `report.json`, `findings.csv`, and
33+
`warnings.csv` regression fixtures to lock report contracts.
34+
- Added a 150-line sanitized mixed auth corpus fixture covering Ubuntu /
35+
Debian-style `auth.log`, RHEL-family `secure`-style syslog, unknown lines,
36+
malformed source IPs, and blank-line handling.
37+
- Added a reviewer-facing parser coverage JSON artifact for the mixed auth
38+
corpus.
39+
40+
### Changed
41+
42+
- Made parser coverage telemetry and finding explainability part of the
43+
release-facing review path instead of internal-only implementation detail.
44+
45+
### Fixed
46+
47+
- None.
48+
49+
### Docs
50+
51+
- Added release notes for the v0.5 Evidence Explainability Release.
52+
- Added a release readiness checklist that maps v0.5 requirements to reviewer
53+
evidence and stopping points.
54+
- Added a one-page incident-style case that traces raw SSH evidence through
55+
normalized events and finding fields to a bounded conclusion.
56+
- Added a rule-by-rule false-positive taxonomy for NAT, bastion, internal scanner,
57+
lab replay, scheduled admin task, and shared-account contexts.
58+
- Added forensic-style case-study coverage for Linux auth brute-force evidence
59+
interpretation.
60+
- Expanded the parser conformance matrix with explicit Ubuntu / Debian
61+
`auth.log`, RHEL-family `secure`, `journalctl --output=short-full`, `sshd`,
62+
`sudo`, `pam_unix`, `pam_faillock`, and `pam_sss` style coverage.
63+
2664
## v0.4.0
2765

2866
### Added

README.md

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,34 @@ C++20 defensive log analysis CLI for Linux authentication logs, with parser cove
77

88
It parses `auth.log` / `secure`-style syslog input and `journalctl --output=short-full`-style input, normalizes authentication evidence, applies configurable rule-based detections, and emits deterministic Markdown and JSON reports, with optional CSV exports for findings and warnings.
99

10+
## Example Finding
11+
12+
A compact finding summary is a bounded triage signal, not a compromise verdict
13+
or attribution:
14+
15+
```json
16+
{
17+
"rule_id": "brute_force",
18+
"subject_kind": "source_ip",
19+
"subject": "203.0.113.10",
20+
"grouping_key": "source_ip",
21+
"window_start": "2026-03-10 08:11:22",
22+
"window_end": "2026-03-10 08:18:05",
23+
"threshold": 5,
24+
"observed_count": 5,
25+
"evidence_event_ids": ["line:1", "line:2", "line:3", "line:4", "line:5"],
26+
"verdict_boundary": "triage_signal_not_compromise_or_attribution"
27+
}
28+
```
29+
1030
## Project Status
1131

1232
LogLens is an MVP / early release. The repository is stable enough for public review, local experimentation, and extension, but the parser and detection coverage are intentionally narrow.
1333

14-
Reviewing the project quickly? Start with [`docs/reviewer-path.md`](./docs/reviewer-path.md) and [`docs/reviewer-brief.md`](./docs/reviewer-brief.md).
34+
Reviewing the project quickly? Start with [`docs/reviewer-path.md`](./docs/reviewer-path.md), [`docs/reviewer-brief.md`](./docs/reviewer-brief.md), and the [`v0.5 Evidence Explainability release note`](./docs/release-v0.5.0.md). The [`quality gates map`](./docs/quality-gates.md) links claims to tests and fixtures. For detection reasoning, follow the [`one-page incident-style case`](./docs/incident-style-case.md), then use the full [`Linux auth brute-force case study`](./docs/case-study-linux-auth-bruteforce.md), [`rule catalog`](./docs/rule-catalog.md), and [`false-positive taxonomy`](./docs/false-positive-taxonomy.md) for depth. For local scale expectations, see the [`performance envelope`](./docs/performance-envelope.md).
35+
36+
For a shorter external review entry point focused on uncertainty handling, read
37+
[How LogLens Treats Parser Uncertainty as Evidence](./docs/case-study-parser-uncertainty-as-evidence.md).
1538

1639
## Why This Project Exists
1740

@@ -38,7 +61,7 @@ LogLens includes two minimal GitHub Actions workflows:
3861
- `CI` builds and tests the project on `ubuntu-latest` and `windows-latest`
3962
- `CodeQL` runs GitHub code scanning for C/C++ on pushes, pull requests, and a weekly schedule
4063

41-
Both workflows are intended to stay stable enough to require on pull requests to `main`. Regression coverage is backed by sanitized parser fixture matrices plus golden report-contract fixtures for `report.md`, `report.json`, and optional CSV outputs. Release-facing documentation is split across [`CHANGELOG.md`](./CHANGELOG.md), [`docs/release-process.md`](./docs/release-process.md), [`docs/release-v0.1.0.md`](./docs/release-v0.1.0.md), [`docs/release-v0.3.0.md`](./docs/release-v0.3.0.md), and the repository's GitHub release notes. The repository hardening note is in [`docs/repo-hardening.md`](./docs/repo-hardening.md), and vulnerability reporting guidance is in [`SECURITY.md`](./SECURITY.md).
64+
Both workflows are intended to stay stable enough to require on pull requests to `main`. Regression coverage is backed by sanitized parser fixture matrices plus golden report-contract fixtures for `report.md`, `report.json`, and optional CSV outputs. Release-facing documentation is split across [`CHANGELOG.md`](./CHANGELOG.md), [`docs/release-process.md`](./docs/release-process.md), [`docs/release-v0.1.0.md`](./docs/release-v0.1.0.md), [`docs/release-v0.3.0.md`](./docs/release-v0.3.0.md), [`docs/release-v0.5.0.md`](./docs/release-v0.5.0.md), and the repository's GitHub release notes. The repository hardening note is in [`docs/repo-hardening.md`](./docs/repo-hardening.md), and vulnerability reporting guidance is in [`SECURITY.md`](./SECURITY.md).
4265

4366
## Threat Model
4467

@@ -66,7 +89,8 @@ LogLens currently parses and reports these additional auth patterns beyond the c
6689
- `Accepted keyboard-interactive/pam` SSH successes
6790
- `Failed publickey` SSH failures, which count toward SSH brute-force detection by default
6891
- `Failed keyboard-interactive/pam` and `maximum authentication attempts exceeded` SSH failures, which count toward SSH brute-force detection by default
69-
- `sshd`-owned `PAM: Authentication failure ...` lines, with invalid/illegal-user variants normalized to `ssh_invalid_user`
92+
- `input_userauth_request: invalid/illegal user ...` preauth SSH traces normalized to `ssh_invalid_user`
93+
- `sshd`-owned `PAM: Authentication failure ...` lines, including OpenSSH's optional leading `error:` marker, with invalid/illegal-user variants normalized to `ssh_invalid_user`
7094
- `sudo` command, password-failure, and sudoers policy-denial audit lines
7195
- `su` success and failure audit lines
7296
- `pam_unix(...:auth): authentication failure`
@@ -82,14 +106,19 @@ LogLens also tracks parser coverage telemetry for unsupported or malformed lines
82106
- `parsed_lines`
83107
- `unparsed_lines`
84108
- `parse_success_rate`
109+
- `failure_categories`
85110
- `top_unknown_patterns`
86111

87112
Common unsupported-pattern buckets include `sshd_connection_closed_preauth`,
88-
`sshd_timeout_or_disconnection`, `sshd_negotiation_failure`, and
89-
`pam_unix_session_closed`. These buckets keep non-finding evidence reviewable
90-
without counting it as detector evidence.
113+
`sshd_timeout_or_disconnection`, `sshd_negotiation_failure`,
114+
`pam_faillock_account_locked`, and `pam_unix_session_closed`. These buckets keep
115+
non-finding evidence reviewable without counting it as detector evidence.
116+
Failure categories group unsupported lines into reviewer-facing parser boundary
117+
classes: `unknown_timestamp`, `unknown_program`,
118+
`known_program_unknown_message`, `malformed_source_ip`, and
119+
`unsupported_pam_variant`.
91120

92-
For the parser behavior contract, supported modes, and fixture map, see [`docs/parser-contract.md`](./docs/parser-contract.md).
121+
For a compact raw-log-to-conclusion trace, see [`docs/incident-style-case.md`](./docs/incident-style-case.md). For rule-by-rule semantics and signal boundaries, see [`docs/rule-catalog.md`](./docs/rule-catalog.md). For benign-context hypotheses and the evidence needed to support them, see [`docs/false-positive-taxonomy.md`](./docs/false-positive-taxonomy.md). For a full forensic-style evidence walkthrough, see [`docs/case-study-linux-auth-bruteforce.md`](./docs/case-study-linux-auth-bruteforce.md). For the parser behavior contract, supported modes, and fixture map, see [`docs/parser-contract.md`](./docs/parser-contract.md). For the deliberately noisy parser-coverage sample, see [`docs/parser-coverage-notes.md`](./docs/parser-coverage-notes.md).
93122

94123
LogLens does not currently detect:
95124

@@ -107,6 +136,12 @@ cmake --build build
107136
ctest --test-dir build --output-on-failure
108137
```
109138

139+
For Visual Studio or other multi-config generators, pass the built configuration to CTest:
140+
141+
```bash
142+
ctest --test-dir build -C Debug --output-on-failure
143+
```
144+
110145
For fresh-machine setup and repeatable local presets, see [`docs/dev-setup.md`](./docs/dev-setup.md).
111146

112147
## Run
@@ -135,7 +170,7 @@ When you add `--csv`, LogLens also writes:
135170
The CSV schema is intentionally small and stable:
136171

137172
- `findings.csv`: `rule`, `subject_kind`, `subject`, `event_count`, `window_start`, `window_end`, `usernames`, `summary`
138-
- `warnings.csv`: `kind`, `line_number`, `message`
173+
- `warnings.csv`: `kind`, `line_number`, `category`, `message`
139174

140175
Without `--csv`, LogLens does not create, overwrite, or delete any existing CSV files in the output directory.
141176

@@ -212,6 +247,8 @@ The config file schema is intentionally small and strict:
212247

213248
This mapping lets LogLens normalize parsed events into detection signals before applying brute-force or multi-user rules. By default, `pam_auth_failure` is treated as lower-confidence attempt evidence and does not count as a terminal authentication failure unless the config explicitly upgrades it. The `ssh_failed_keyboard_interactive` and `ssh_max_auth_tries` mapping keys are optional in older configs and default to terminal failure evidence.
214249

250+
The checked-in [`assets/sample_config.json`](./assets/sample_config.json) is tested as a runnable default-equivalent config fixture. If default detector thresholds or signal mappings change, update that file and the related tests together.
251+
215252
Timestamp handling is now explicit:
216253

217254
- `--mode syslog`, `--mode syslog-legacy`, or `input_mode: syslog_legacy` requires `--year` or `timestamp.assume_year`

0 commit comments

Comments
 (0)