Repository navigation
Description
ADR-0016
decided that the NAS on CasaBonita (40) is scraped, never pushed — metrics
come out over 99→40:9100, and nothing on that segment initiates anywhere. Loki
has no pull. Metrics survive that reversal; logs do not.
So the NAS will be the one host in the estate whose compromise is invisible.
Prometheus will show it alive, loaded and busy, and nothing will show what it
did. Jellyfin is a large codebase with a network-facing indexer, sitting on the
segment whose stated assumption is that everything on it is already
compromised — which is exactly the host you would want logs from.
Important
The trigger has fired. This issue said "Nothing to do until the hardware
lands" and "record it as a residual when it lands". It landed:
smaug — the host this issue filed as zion, renamed by
ADR-0038
— has held 10.0.40.30 since 2026-09-16, runs TrueNAS
(ADR-0040),
and its four inbound passes are created and verified in position. It runs no
Alloy agent and ships no logs, exactly as decided. The three boxes below are
now writable, and none of them waits on the ZFS pool, which is why this
moved to Wave 0. #102 is closed; the build is
#413.
Why the obvious fix is worse than the gap
A 40→99:3100 rule would collect the logs. It would also:
- Be the first upward path in the estate — the property ADR-0008 claims to
keep ("nothing untrusted ever initiates upward") and ADR-0016 went out of its
way to preserve. All four passes that exist today reach in, and
CasaBonita's Reaches column is unchanged for exactly this reason. - Let anything that reaches the NAS write to the log store the rest of the
estate is judged by. Loki's ingest is unauthenticated by design
(ADR-0012,
#182), so this does not just
move logs — it hands a low-trust host the ability to inject and delete them. - Make a sentence in
SECURITY.mdfalse. The residual row for the ingest ports
currently reads "Firewall default-deny is the whole control: only Hicks (50)
and Winterfell (99) can reach the host at all, and never an untrusted
segment." That last clause survives ADR-0016 only because the direction was
reversed. This rule would retire it.
Trading a blind spot on one host for a write path into every host's logs is the
wrong way round, which is why ADR-0016 chose the blind spot. But it chose it —
it is not an oversight, and it should not be discovered later as one.
What this issue is for
Not to close the gap. To record it where residuals are recorded:
- A row in
SECURITY.md's Known exposure table, in the same
"Accepted residual, not a fix in progress" form as the ingest-port and
unencrypted-disk rows. - A line in
docs/security.md, near the tripwire paragraph — the tripwire
is the control that still watches this segment, and it is worth saying
that it is the only one. That paragraph moved on 2026-09-16 when the
rules were created and the prose had to stop saying CasaBonita has "no
path to anything else"; this line belongs beside the wording that
replaced it. - Decide whether
TerminalSegmentReachedInternalNetworkis enough on its
own for this host, or whether the absence of logs deserves something of
its own. Note the trap: a rule that alerts on "no logs fromsmaug"
cannot exist, because there were never any logs to stop arriving. This is
theSuricataStoppedreasoning insecurity.rules.yaml:241-250again —
absence of a signal is indistinguishable from absence of the service —
and it is why the answer here is probably "the tripwire, and honesty in
the docs", not a new alert.
One thing to state while writing it, because it is newly true. smaug runs
no Alloy, so it has no logs and no SMART collection and no patch state — every
one of those rides the push this host does not make. The blind spot is wider
than the logs this issue was filed about, and the rest of it is its own issue
rather than a fourth box here.
Found writing ADR-0016 for #95.
Activity
Gerrrt commentedon Sep 8, 2026
Nothing to add to
SECURITY.mdyet — every row in that table is an observedfinding about a host that exists, and
zionis still not bought(
network.mdsays so; ADR-0016's three rules are written down and notcreated). But the third checkbox is answerable now, and answering it removes
the only thinking left in this issue.
Is
TerminalSegmentReachedInternalNetworkenough on its own?It is a positional check, not a compromise detector, and it should be
described as the former. Three facts from the repository:
zioninitiating toward 30, 50 or 99, which ADR-0016 sayswill never happen. Return traffic for a session Winterfell opened is carried
by state and never consults the ruleset, so a scrape works and the rule stays
silent — as designed.
ziondoes inside VLAN 40 — to thetelevisions, on the same broadcast domain — never reaches
morpheus, andADR-0016 already says the TVs need no rule for exactly that reason.
filterlog, so it watches the segmentation aroundthe NAS, not the NAS.
So it is the control that watches the segment, and it is the only one. The
absence-of-logs alert this issue warns about cannot exist, for the reason the
file records — not at
security.rules.yaml:241-250, which isKernelOomKill,but in the block headed NO LOG-BASED "SuricataStopped" RULE, DELIBERATELY
(now around line 560): absence of a signal is indistinguishable from absence
of the service, and there was never a signal here. The answer is the
tripwire and honesty in the docs. No new alert.
Ready to paste on the day
SECURITY.md, known-exposure table, after the Loki size-ceiling row:docs/security.md, after the tripwire paragraph:Both are drafts against the design; check them against the box when it exists
— in particular that the address is
10.0.40.30and that the99 → 40:9100pass is the only rule that names it.
Still blocked on #102's hardware; nothing else to do here until then.
🤖 Generated with Claude Code
[-]The NAS will have no logs, and that is a decision — record it as a residual when it lands[/-][+]smaug has no logs, and that is a decision — record it as a residual[/+]Gerrrt commentedon Sep 17, 2026
The trigger has fired, and this moved to Wave 0.
smaugexists, isaddressed, runs no Alloy and ships no logs — exactly as ADR-0016 decided. The
three residual rows can be written now; none of them waits on the pool. See
the build comment on #413.
The blind spot turned out to be wider than the logs this issue was filed about:
SMART and patch state ride the same push, and this host makes none. That is
#483 rather than a fourth
checkbox here, but the residual rows should describe the whole of the gap and
not just its logging half.
Merge pull request #493 from Gerrrt/gerrrt/smaug-logging-gap-residual…