Skip to content

Commit bb02953

Browse files
committed
add more firejail protections, including network restrictions
1 parent f27987e commit bb02953

File tree

1 file changed

+59
-1
lines changed

1 file changed

+59
-1
lines changed

airbyte_cdk/cli/source_declarative_manifest/_sandboxed_run.py

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,22 @@
3939
"""
4040

4141

42+
def _get_default_gateway() -> str | None:
43+
"""Returns the system's default gateway IP, or None if not found."""
44+
try:
45+
result = subprocess.run(
46+
["ip", "route"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True
47+
)
48+
for line in result.stdout.split("\n"):
49+
if line.startswith("default via"):
50+
return line.split()[2] # Extract the gateway IP
51+
52+
except Exception as e:
53+
print(f"❌ Error detecting gateway: {e}")
54+
55+
return None
56+
57+
4258
def _wrap_in_sandbox(cmd: list[str]) -> list[str]:
4359
"""Wrap the given command in Firejail.
4460
This function modifies the command to include Firejail options
@@ -66,8 +82,50 @@ def _wrap_in_sandbox(cmd: list[str]) -> list[str]:
6682
return cmd
6783

6884
# Firejail is available
85+
gateway_ip: str | None = _get_default_gateway()
86+
if not gateway_ip:
87+
print("❌ No gateway detected. Blocking all egress traffic.")
88+
netfilter_rules = [
89+
"--netfilter=reject 0.0.0.0/0" # Block all traffic if no gateway is detected
90+
]
91+
else:
92+
print(f"🔥 Allowing egress only via gateway: {gateway_ip}")
93+
netfilter_rules = [
94+
# Allow traffic only via the detected gateway:
95+
f"--netfilter=accept {gateway_ip}",
96+
# Block all private networks and localhost:
97+
"--netfilter=reject 10.0.0.0/8",
98+
"--netfilter=reject 172.16.0.0/12",
99+
"--netfilter=reject 192.168.0.0/16",
100+
"--netfilter=reject 127.0.0.0/8",
101+
"--netfilter=reject 169.254.0.0/16",
102+
"--netfilter=reject ::1/128",
103+
"--netfilter=reject fc00::/7",
104+
"--netfilter=reject fe80::/10",
105+
]
106+
107+
# Use Google DNS resolution. It is fine to use others but we just don't want to block DNS.
108+
dns_args = [
109+
"--dns=8.8.8.8",
110+
"--dns=8.8.4.4",
111+
]
112+
# Firejail Command with DNS resolution allowed
113+
firejail_args = (
114+
[
115+
"--private", # Isolates the filesystem (prevents access to user files)
116+
"--net=none", # Ensures restricted networking
117+
"--seccomp", # Enable seccomp-bpf syscall filtering
118+
"--blacklist=/var/run/" # Block system sockets
119+
"--private-tmp" # Creates an isolated temp directory for each process
120+
"--rlimit-cpu=120", # Limits CPU time to 1 second (prevents runaway processes)
121+
"--rlimit-fsize=10000000", # Limits max file size to 10 MB (prevents excessive disk writes)
122+
]
123+
+ netfilter_rules
124+
+ dns_args
125+
)
126+
69127
print("Firejail found. Running with Firejail sandboxing.")
70-
return ["firejail", "--private", "--net=none"] + cmd
128+
return ["firejail"] + firejail_args + cmd
71129

72130

73131
def sandboxed_run():

0 commit comments

Comments
 (0)