Security review
4 min read

Closing an intake's outbound trust-boundary gap

A scoped review found outbound reachability across an intended boundary. The recorded repair blocked the tested path and preserved the required service traffic.

Date
26 September 2026
Outcome
Remediated
Focus
Owner-operated infrastructure · scoped network review

An intake guest accepted new outbound connections despite restrictive ingress. Known protected destinations accepted TCP connections from it in the historical validation. The repair blocked a previously reachable listener while the health endpoint and approved reverse-proxy connection still worked.

Why the ingress rules missed the problem

The intake had service sandboxing and restricted ingress. Useful Linux sandbox controls include NoNewPrivileges, ProtectSystem, ProtectHome and RestrictNamespaces; none defines an outbound destination allowlist.

Those settings address different authorities: NoNewPrivileges limits privilege gains through executable transitions, filesystem protection constrains visible/writable paths, and namespace restrictions limit namespace operations. They do not specify an outbound destination allowlist. That distinction explains why an apparently hardened service still needed a separate network-path review. Upstream systemd execution manual source.

Those controls did not establish network isolation. Restrictive ingress did not constrain new outbound connections. Routing and accepting forwarding rules along the path supplied reachability to a protected destination. The review followed that complete route rather than treating the container's input policy as a verdict.

The change

This reusable nftables example illustrates the repair pattern using a generic chain layout. Adapt it to the application's dependencies and existing rules; it is not a deployment configuration.

 chain output {
-    type filter hook output priority filter; policy accept;
+    type filter hook output priority filter; policy drop;
+    ct state invalid drop
+    ct state established,related accept
+    oifname "lo" accept
 }

The distinction is between new outbound connections and replies to admitted inbound connections. The nftables manual assigns packets generated by local processes to the output hook; a base-chain policy supplies the verdict when processing reaches its end. Changing the input chain would not close this guest-initiated path. Connection-state matching retained established/related traffic, and the recorded postchecks confirmed that the exercised health and reverse-proxy replies still worked. Loopback preserved local communication. Official nftables manual: hooks, chains and connection tracking.

Dependency inspection found no required application-initiated remote connection in the inspected paths. Inbound requests and their replies could therefore be preserved without a permanent new-connection exception. A reusable review should distinguish local jobs from outbound HTTP, SMTP, DNS, subprocess and remote-backup dependencies. Package updates were a separate maintenance requirement, not a reason for permanent Internet access.

Evidence and what it establishes

Recorded observationConclusion
A new outbound connection crossed the intended protected boundaryRestrictive ingress did not contain guest-initiated traffic
TCP connections to already-known protected listeners completed before the repairA transport path existed; no application request or authentication was needed to establish it
Native nft -c -f /etc/nftables.conf check passed before reload; effective output policy then showed the intended rulesThe approved configuration parsed and was loaded
Existing health GET returned status: ok; the approved proxy still completed a TCP connectionThe exercised inbound dependencies survived the change
A new connection to the previously reachable protected listener timed out after reloadThe tested outbound path was blocked
Affected service and timer states retained their expected operationThe observed service and scheduling state was retained

The conditional impact was a network pivot if the public-facing intake were compromised. The finding was reachability, not a recorded compromise.

Apply the review to your own lab

This is a reusable procedure for infrastructure you are authorized to review, separate from the recorded evidence above.

  1. Inspect the guest's effective input, forward and output chains. Read routes and the enforcement rules at each routed hop; an input allowlist does not restrict outbound initiation.
  2. Inspect application and scheduled-job dependencies. Separate local jobs, inbound requests and their replies from connections the guest initiates. Check time synchronization, name resolution and maintenance needs for your own guest.
  3. Select one known, approved destination for a baseline TCP-only connection. Record the intended health and ingress checks too; avoid substituting a port scan for a boundary test.
  4. Save the exact current ruleset and prepare restoration before applying the smallest justified change. Validate the candidate with nft -c -f /etc/nftables.conf, then load it through the existing firewall service during the authorized change.
  5. Inspect the loaded chain. Repeat the same destination check, health check and proxy connection; inspect affected services and timers. A firewall syntax pass alone does not prove the required paths still work.

A default-deny rule is useful only with the right dependency model. This intake needed replies and loopback; another application may legitimately need narrowly scoped outbound destinations.

Validation coverage

Validation covered effective rules and routes, preserved health and ingress, and one previously reachable TCP destination. It did not cover every protocol or a comprehensive IPv6 matrix. The repair used the guest firewall; the proposed host layer was not applied.

← All researchNext article