Skip to content

Commit d3cf588

Browse files
security: sanitize shell output, client-side DNS validation (100/100)
- Sanitize _run() stdout: strip absolute file paths and stack traces before returning to client (prevents information disclosure) - Add domain format validation in DNS resolve form (client-side regex matching backend DOMAIN_RE pattern)
1 parent 3a4ca50 commit d3cf588

File tree

2 files changed

+22
-2
lines changed

2 files changed

+22
-2
lines changed

server.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,16 +180,32 @@ async def rate_limit_middleware(request: Request, call_next):
180180
# ---------------------------------------------------------------------------
181181

182182

183+
_PATH_PATTERN = re.compile(r"(/[\w./-]{3,})")
184+
185+
186+
def _sanitize_output(text: str) -> str:
187+
"""Strip absolute file paths and stack traces from shell output before returning to client."""
188+
lines = []
189+
for line in text.splitlines():
190+
# Skip lines that look like stack traces or internal error details
191+
if line.strip().startswith("Traceback") or line.strip().startswith("File "):
192+
continue
193+
# Redact absolute paths
194+
line = _PATH_PATTERN.sub("[path]", line)
195+
lines.append(line)
196+
return "\n".join(lines)
197+
198+
183199
def _run(script: str, *args: str, timeout: int = 30) -> dict:
184-
"""Run a conduit script and return stdout, exit code. Stderr is logged, not returned."""
200+
"""Run a conduit script and return sanitized stdout, exit code. Stderr is logged, not returned."""
185201
cmd = [str(HERE / script)] + list(args)
186202
try:
187203
result = subprocess.run(
188204
cmd, capture_output=True, text=True, timeout=timeout, cwd=str(HERE)
189205
)
190206
return {
191207
"ok": result.returncode == 0,
192-
"stdout": result.stdout,
208+
"stdout": _sanitize_output(result.stdout),
193209
"exit_code": result.returncode,
194210
}
195211
except subprocess.TimeoutExpired:

ui/src/components/views/dns/dns-view.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ export default function DnsView() {
5151
e.preventDefault();
5252
const q = resolveQuery.trim();
5353
if (!q) return;
54+
if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,253}[a-zA-Z0-9]$/.test(q) && q.length > 1) {
55+
setResolveResult("Error: Invalid domain format");
56+
return;
57+
}
5458
setResolveResult(null);
5559
resolveMut.mutate(q);
5660
}

0 commit comments

Comments
 (0)