Skip to content

test: a sixth fuzz target for the cron parsers, and tailnet address coverage - #73

Merged
FMSMITH91 merged 3 commits into
mainfrom
test/cron-fuzz-and-tailnet
Aug 9, 2026
Merged

test: a sixth fuzz target for the cron parsers, and tailnet address coverage#73
FMSMITH91 merged 3 commits into
mainfrom
test/cron-fuzz-and-tailnet

Conversation

@FMSMITH91

Copy link
Copy Markdown
Owner

Fuzzing: the cron parsers

Everything these read comes off a remote host — the game user's crontab, which anyone with shell access edits by hand, and the base64-framed status blob the panel's own wrapper writes, carrying whatever a LinuxGSM command printed to stderr (for an update, text fetched off the internet).

That path has already produced one real bug this way: a tr that missed \r truncated every record at the transport, so errors silently read as empty. The Scheduled Tasks page renders all of it, and a raise here takes out the page rather than one row.

Six parsers under test — _split_cron_line, _unwrap_cron_command, _cron_role, _cron_line_managed, _cron_log_text, _clean_cron_error — with 11 seeds covering a wrapped line, @reboot, name-form fields, valid and broken base64, and an ANSI-laden error. Property-checked over 200,000 random inputs before committing; nothing raised.

Fuzz matrix is now [game_status, firewall, config, fail2ban, console, cron].

Tailnet address recognition

is_tailscale_ip decides whether the panel treats a host as being on the tailnet, which changes how it connects and what it exempts from fail2ban and UFW — so a false positive exempts a public address from the security rules. Nine near-misses asserted alongside the six hits, including example.ts.net.evil.com and 1.100.0.1.

get_magic_url too: 80 and 443 are left off, any other port appended, and a node with no MagicDNS name yields None rather than https://None.

unit 867 → 889 · smoke 307 · manage 21 · template_actions 7 · lint clean.

🤖 Generated with Claude Code

FMSMITH91 and others added 2 commits August 9, 2026 10:14
…d test

The rest of notifications.py's zero-coverage functions. The one that matters:

save_settings treats a None secret as "keep what is stored", because the
settings form never round-trips a real token back to the server. If that ever
broke, every unrelated checkbox change would silently wipe the bot token and
alerts would just stop — no error, nothing on screen. Asserted in both
directions: None keeps the stored value, a real value replaces it AND is
written encrypted (the plaintext must not appear in the config, and it must
decrypt back).

Also: thresholds clamp to their bounds rather than storing whatever was
posted, and junk in a numeric field is ignored instead of overwriting a good
value; the Telegram poller returns None for a malformed or empty token
without building a URL; and Send test explains what is missing — five cases,
each naming the field — rather than failing mute.

update_config is stubbed throughout, so the real data/config.json is never
written by these. Verified: the file's bytes are unchanged across a run. (Its
mtime does move, but that predates this change — the suite already rewrote it
byte-identically at HEAD.)

Mutation-verified: making a None token overwrite fails 1, storing the secret
in the clear fails 1, dropping the threshold clamp fails 1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…overage

── fuzz: cron ────────────────────────────────────────────────────────────────
Everything the cron parsers read comes off a remote host — the game user's
crontab, which anyone with shell access edits by hand, and the base64-framed
status blob the panel's own wrapper writes, which carries whatever a LinuxGSM
command printed to stderr (for an update, text fetched off the internet).

That path has already produced one real bug this way: a `tr` that missed \r
truncated every record at the transport, so errors silently read as empty. The
Scheduled Tasks page renders all of it, and a raise here takes out the page
rather than one row.

Six parsers under test — _split_cron_line, _unwrap_cron_command, _cron_role,
_cron_line_managed, _cron_log_text, _clean_cron_error — with 11 seeds covering
a wrapped line, @reboot, name-form fields, a valid and a broken base64 blob,
and an ANSI-laden error. Property-checked over 200k random inputs before
committing: nothing raised.

── tailnet address recognition ───────────────────────────────────────────────
is_tailscale_ip decides whether the panel treats a host as being ON the
tailnet, which changes how it connects and what it exempts from fail2ban and
UFW — so a false positive exempts a PUBLIC address from the security rules.
Nine near-misses are asserted alongside the six hits, including
"example.ts.net.evil.com" and "1.100.0.1".

get_magic_url too: 80 and 443 are left off, any other port is appended, and a
node with no MagicDNS name yields None rather than "https://None".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@codacy-production

codacy-production Bot commented Aug 9, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Coverage ∅ diff coverage · +0.03% coverage variation

Metric Results
Coverage variation +0.03% coverage variation (-1.00%)
Diff coverage diff coverage

View coverage diff in Codacy

Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (74d11e8) 11965 5873 49.08%
Head commit (24378ae) 11965 (+0) 5876 (+3) 49.11% (+0.03%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#73) 0 0 ∅ (not applicable)

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

…o both

sides carried that block. Kept one copy; both test sets present, 889 checks.
@FMSMITH91
FMSMITH91 merged commit 4f7b255 into main Aug 9, 2026
27 checks passed
@FMSMITH91
FMSMITH91 deleted the test/cron-fuzz-and-tailnet branch August 9, 2026 15:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant