LogLens treats parser behavior as reviewable output, not as a hidden implementation detail. A line is either recognized as a typed event, skipped as blank input, or surfaced as a warning with coverage telemetry.
The guiding rule is:
Parser observability > silent detection claims.
| Mode | Typical source | Timestamp behavior | Review anchor |
|---|---|---|---|
syslog_legacy |
auth.log / secure style lines such as Mar 10 08:11:22 example-host sshd[1234]: ... |
Requires an explicit four-digit year from --year or timestamp.assume_year |
assets/parser_fixture_matrix_syslog.log |
journalctl_short_full |
journalctl --output=short-full style lines such as Tue 2026-03-10 08:11:22 UTC example-host sshd[1234]: ... |
Uses the embedded year and supported timezone token | assets/parser_fixture_matrix_journalctl_short_full.log |
Supported timezone tokens for journalctl_short_full are intentionally narrow: UTC, GMT, Z, and numeric offsets such as +0000 or +00:00.
The parser currently recognizes common authentication evidence from:
sshdsudosupam_unix(...)- selected
pam_faillock(...)variants - selected
pam_sss(...)variants
Recognized SSH failure families include failed password, invalid user, illegal user, failed publickey, failed keyboard-interactive/pam, and maximum-authentication-attempts-exceeded lines. illegal user is treated as an OpenSSH wording variant of invalid user. Invalid or illegal-user variants of keyboard-interactive and maximum-authentication-attempts-exceeded lines are normalized into ssh_invalid_user events. Recognized SSH failures can become detection signals through the configured signal mapping.
Recognized success or audit families include accepted password, accepted publickey, accepted keyboard-interactive/pam, sudo command audit lines, sudo password failures, sudoers policy denials, su success/failure audit lines, and selected PAM session/auth lines.
| Input line outcome | Parser behavior | Report behavior |
|---|---|---|
| Recognized auth line | Emits a typed Event with timestamp, hostname, program, optional pid, message, source IP, username, event type, and line number |
Can contribute to summaries, reports, and configured detection signals |
| Blank line | Skips the line and increments skipped_blank_lines |
Does not become a warning or parsed event |
| Malformed header | Emits a parser warning with the original line number and structural reason | Counts toward unparsed_lines and top_unknown_patterns |
| Well-formed but unsupported auth pattern | Emits a parser warning with an unknown-pattern bucket | Stays visible as telemetry instead of being silently ignored |
This is the main trust boundary: unsupported input should remain inspectable, even when it does not produce a finding.
Parsing a line does not automatically mean it should drive a detector. LogLens keeps that boundary explicit through AuthSignalConfig.
Default terminal SSH failure evidence:
ssh_failed_passwordssh_invalid_userssh_failed_publickeyssh_failed_keyboard_interactivessh_max_auth_tries
Default lower-confidence attempt evidence:
pam_auth_failure, which is attempt evidence but not terminal failure evidence unless configured otherwise
Default sudo burst evidence:
sudo_command
Parsed successes and audit-only events remain reportable but do not count as brute-force or multi-user failure evidence by default.
| Artifact | What it proves |
|---|---|
tests/test_parser.cpp |
Unit-level parser expectations, malformed-line behavior, mode aliases, fixture-matrix counts, and unknown-pattern buckets |
tests/test_detector.cpp |
Detection signal mapping and default counting behavior after parsing |
assets/parser_fixture_matrix_syslog.log |
Syslog known/unknown parser matrix |
assets/parser_fixture_matrix_journalctl_short_full.log |
Journalctl short-full known/unknown parser matrix |
assets/parser_auth_families_syslog.log |
Syslog PAM/auth-family parser coverage |
assets/parser_auth_families_journalctl_short_full.log |
Journalctl PAM/auth-family parser coverage |
tests/test_report_contracts.cpp |
Stable report-shape expectations for generated artifacts |
The parser does not try to:
- infer missing syslog years
- support every Linux authentication log variant
- classify unsupported lines as findings
- correlate across files or hosts
- produce incident verdicts
Those boundaries are intentional for the MVP. The current priority is to keep parser coverage explicit and safely extensible.