Skip to content

Commit f8467f3

Browse files
rubenfiszelclaude
andauthored
fix: prevent cross-tenant DNS poisoning via writable /etc in nsjail (#9194)
* fix: bind /etc resolver files read-only in nsjail sandboxes * docs(nsjail): explain why per-file /etc resolver binds are load-bearing The explicit /etc/hosts, /etc/resolv.conf and /etc/hostname binds look like removable duplication of the read-only /etc bind above them. They are not: on Kubernetes those files are separate kubelet bind-mounts on top of /etc and nsjail's read-only remount is non-recursive, so without these shadow binds they stay writable and a job can persist cross-tenant DNS poisoning for the pod lifetime. Comment guards against a future "dedup cleanup" silently reintroducing the vulnerability. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(nsjail): shorten the load-bearing-bind comment to 3 lines Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 25172bd commit f8467f3

18 files changed

Lines changed: 432 additions & 0 deletions

backend/windmill-worker/nsjail/download.py.config.proto

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,30 @@ mount {
5555
is_bind: true
5656
}
5757

58+
# Container runtimes bind exactly these 3 files as separate submounts over
59+
# /etc; nsjail's ro remount of /etc is non-recursive so they stay writable.
60+
# Load-bearing -- do not remove as redundant with the /etc bind above.
61+
mount {
62+
src: "/etc/resolv.conf"
63+
dst: "/etc/resolv.conf"
64+
is_bind: true
65+
mandatory: false
66+
}
67+
68+
mount {
69+
src: "/etc/hosts"
70+
dst: "/etc/hosts"
71+
is_bind: true
72+
mandatory: false
73+
}
74+
75+
mount {
76+
src: "/etc/hostname"
77+
dst: "/etc/hostname"
78+
is_bind: true
79+
mandatory: false
80+
}
81+
5882
mount {
5983
src: "/dev/null"
6084
dst: "/dev/null"

backend/windmill-worker/nsjail/download.ruby.config.proto

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,30 @@ mount {
5555
is_bind: true
5656
}
5757

58+
# Container runtimes bind exactly these 3 files as separate submounts over
59+
# /etc; nsjail's ro remount of /etc is non-recursive so they stay writable.
60+
# Load-bearing -- do not remove as redundant with the /etc bind above.
61+
mount {
62+
src: "/etc/resolv.conf"
63+
dst: "/etc/resolv.conf"
64+
is_bind: true
65+
mandatory: false
66+
}
67+
68+
mount {
69+
src: "/etc/hosts"
70+
dst: "/etc/hosts"
71+
is_bind: true
72+
mandatory: false
73+
}
74+
75+
mount {
76+
src: "/etc/hostname"
77+
dst: "/etc/hostname"
78+
is_bind: true
79+
mandatory: false
80+
}
81+
5882
mount {
5983
src: "/dev/null"
6084
dst: "/dev/null"

backend/windmill-worker/nsjail/download.rust.config.proto

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,30 @@ mount {
6262
is_bind: true
6363
}
6464

65+
# Container runtimes bind exactly these 3 files as separate submounts over
66+
# /etc; nsjail's ro remount of /etc is non-recursive so they stay writable.
67+
# Load-bearing -- do not remove as redundant with the /etc bind above.
68+
mount {
69+
src: "/etc/resolv.conf"
70+
dst: "/etc/resolv.conf"
71+
is_bind: true
72+
mandatory: false
73+
}
74+
75+
mount {
76+
src: "/etc/hosts"
77+
dst: "/etc/hosts"
78+
is_bind: true
79+
mandatory: false
80+
}
81+
82+
mount {
83+
src: "/etc/hostname"
84+
dst: "/etc/hostname"
85+
is_bind: true
86+
mandatory: false
87+
}
88+
6589
mount {
6690
src: "/dev/random"
6791
dst: "/dev/random"

backend/windmill-worker/nsjail/install.r.config.proto

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,30 @@ mount {
5555
is_bind: true
5656
}
5757

58+
# Container runtimes bind exactly these 3 files as separate submounts over
59+
# /etc; nsjail's ro remount of /etc is non-recursive so they stay writable.
60+
# Load-bearing -- do not remove as redundant with the /etc bind above.
61+
mount {
62+
src: "/etc/resolv.conf"
63+
dst: "/etc/resolv.conf"
64+
is_bind: true
65+
mandatory: false
66+
}
67+
68+
mount {
69+
src: "/etc/hosts"
70+
dst: "/etc/hosts"
71+
is_bind: true
72+
mandatory: false
73+
}
74+
75+
mount {
76+
src: "/etc/hostname"
77+
dst: "/etc/hostname"
78+
is_bind: true
79+
mandatory: false
80+
}
81+
5882
mount {
5983
src: "/dev/null"
6084
dst: "/dev/null"

backend/windmill-worker/nsjail/lock.ruby.config.proto

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,30 @@ mount {
5555
is_bind: true
5656
}
5757

58+
# Container runtimes bind exactly these 3 files as separate submounts over
59+
# /etc; nsjail's ro remount of /etc is non-recursive so they stay writable.
60+
# Load-bearing -- do not remove as redundant with the /etc bind above.
61+
mount {
62+
src: "/etc/resolv.conf"
63+
dst: "/etc/resolv.conf"
64+
is_bind: true
65+
mandatory: false
66+
}
67+
68+
mount {
69+
src: "/etc/hosts"
70+
dst: "/etc/hosts"
71+
is_bind: true
72+
mandatory: false
73+
}
74+
75+
mount {
76+
src: "/etc/hostname"
77+
dst: "/etc/hostname"
78+
is_bind: true
79+
mandatory: false
80+
}
81+
5882
mount {
5983
src: "/dev/null"
6084
dst: "/dev/null"

backend/windmill-worker/nsjail/run.ansible.config.proto

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,30 @@ mount {
123123
is_bind: true
124124
}
125125

126+
# Container runtimes bind exactly these 3 files as separate submounts over
127+
# /etc; nsjail's ro remount of /etc is non-recursive so they stay writable.
128+
# Load-bearing -- do not remove as redundant with the /etc bind above.
129+
mount {
130+
src: "/etc/resolv.conf"
131+
dst: "/etc/resolv.conf"
132+
is_bind: true
133+
mandatory: false
134+
}
135+
136+
mount {
137+
src: "/etc/hosts"
138+
dst: "/etc/hosts"
139+
is_bind: true
140+
mandatory: false
141+
}
142+
143+
mount {
144+
src: "/etc/hostname"
145+
dst: "/etc/hostname"
146+
is_bind: true
147+
mandatory: false
148+
}
149+
126150
mount {
127151
src: "/dev/random"
128152
dst: "/dev/random"

backend/windmill-worker/nsjail/run.bash.config.proto

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,30 @@ mount {
9595
is_bind: true
9696
}
9797

98+
# Container runtimes bind exactly these 3 files as separate submounts over
99+
# /etc; nsjail's ro remount of /etc is non-recursive so they stay writable.
100+
# Load-bearing -- do not remove as redundant with the /etc bind above.
101+
mount {
102+
src: "/etc/resolv.conf"
103+
dst: "/etc/resolv.conf"
104+
is_bind: true
105+
mandatory: false
106+
}
107+
108+
mount {
109+
src: "/etc/hosts"
110+
dst: "/etc/hosts"
111+
is_bind: true
112+
mandatory: false
113+
}
114+
115+
mount {
116+
src: "/etc/hostname"
117+
dst: "/etc/hostname"
118+
is_bind: true
119+
mandatory: false
120+
}
121+
98122
mount {
99123
src: "/dev/random"
100124
dst: "/dev/random"

backend/windmill-worker/nsjail/run.bun.config.proto

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,30 @@ mount {
153153
is_bind: true
154154
}
155155

156+
# Container runtimes bind exactly these 3 files as separate submounts over
157+
# /etc; nsjail's ro remount of /etc is non-recursive so they stay writable.
158+
# Load-bearing -- do not remove as redundant with the /etc bind above.
159+
mount {
160+
src: "/etc/resolv.conf"
161+
dst: "/etc/resolv.conf"
162+
is_bind: true
163+
mandatory: false
164+
}
165+
166+
mount {
167+
src: "/etc/hosts"
168+
dst: "/etc/hosts"
169+
is_bind: true
170+
mandatory: false
171+
}
172+
173+
mount {
174+
src: "/etc/hostname"
175+
dst: "/etc/hostname"
176+
is_bind: true
177+
mandatory: false
178+
}
179+
156180
mount {
157181
src: "/dev/random"
158182
dst: "/dev/random"

backend/windmill-worker/nsjail/run.csharp.config.proto

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,30 @@ mount {
9191
is_bind: true
9292
}
9393

94+
# Container runtimes bind exactly these 3 files as separate submounts over
95+
# /etc; nsjail's ro remount of /etc is non-recursive so they stay writable.
96+
# Load-bearing -- do not remove as redundant with the /etc bind above.
97+
mount {
98+
src: "/etc/resolv.conf"
99+
dst: "/etc/resolv.conf"
100+
is_bind: true
101+
mandatory: false
102+
}
103+
104+
mount {
105+
src: "/etc/hosts"
106+
dst: "/etc/hosts"
107+
is_bind: true
108+
mandatory: false
109+
}
110+
111+
mount {
112+
src: "/etc/hostname"
113+
dst: "/etc/hostname"
114+
is_bind: true
115+
mandatory: false
116+
}
117+
94118
mount {
95119
src: "/dev/random"
96120
dst: "/dev/random"

backend/windmill-worker/nsjail/run.go.config.proto

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,30 @@ mount {
8484
is_bind: true
8585
}
8686

87+
# Container runtimes bind exactly these 3 files as separate submounts over
88+
# /etc; nsjail's ro remount of /etc is non-recursive so they stay writable.
89+
# Load-bearing -- do not remove as redundant with the /etc bind above.
90+
mount {
91+
src: "/etc/resolv.conf"
92+
dst: "/etc/resolv.conf"
93+
is_bind: true
94+
mandatory: false
95+
}
96+
97+
mount {
98+
src: "/etc/hosts"
99+
dst: "/etc/hosts"
100+
is_bind: true
101+
mandatory: false
102+
}
103+
104+
mount {
105+
src: "/etc/hostname"
106+
dst: "/etc/hostname"
107+
is_bind: true
108+
mandatory: false
109+
}
110+
87111
mount {
88112
src: "/dev/random"
89113
dst: "/dev/random"

0 commit comments

Comments
 (0)