Skip to content

AllowedPaths warning pollutes stderr of every command when a configured path is missing (e.g. C:\var\log on Windows) #191

@AlexandreYang

Description

@AlexandreYang

Summary

When one of the AllowedPaths configured by the caller cannot be opened (e.g. C:\var\log on a Windows host, where /var/log exists on Linux but its Windows counterpart does not), the sandbox emits a diagnostic warning to stderr. Because the warning is flushed to r.stderr during Runner construction, every script execution in that session ends up with a non-empty stderr, which makes the output look like the command itself failed even though exitCode is 0.

Repro

Run ss (or any command) with AllowedPaths including a path that does not exist on the host.

Windows (par-in-windows-smoke-test-remote-action, AllowedPaths contains C:\var\log):

{
  "exitCode": 0,
  "stderr": "AllowedPaths: skipping \"C:\\\\var\\\\log\": open C:\\var\\log: The system cannot find the path specified.\n",
  "stdout": "Netid  State ... (tcp entries) ..."
}

Linux (same command, /var/log exists):

{
  "exitCode": 0,
  "stderr": "",
  "stdout": "Netid  State ... (tcp + udp + unix entries) ..."
}

Root cause

  • allowedpaths/sandbox.go:60-68allowedpaths.New() records a warning whenever os.OpenRoot(abs) fails (missing path, not a directory, no permission, etc.):
    r, err := os.OpenRoot(abs)
    if err != nil {
        fmt.Fprintf(&buf, "AllowedPaths: skipping %q: %v\n", abs, err)
        continue
    }
  • interp/api.go:255-258 — the buffered warnings are flushed to r.stderr once during New():
    if len(r.sandboxWarnings) > 0 {
        r.stderr.Write(r.sandboxWarnings)
        r.sandboxWarnings = nil
    }

This is by design — AllowedPaths is advisory and missing paths must not fail the Runner — but it makes stderr noisy for every caller that ships a cross-platform allowlist containing paths that only exist on one OS.

Impact

  • Callers that inspect stderr to detect command failure see false positives (exit code is 0 but stderr is non-empty).
  • Integrations that pipe stderr into structured output (e.g. the remote-action UI in the screenshots) display the warning on every invocation.
  • On a correctly-configured host (e.g. Linux with /var/log) the stderr is empty, so the noise is purely a platform-skew artefact, not a real operational problem.

Proposals

Pick one (or combine):

  1. Route sandbox diagnostics to a dedicated sink — a SandboxWarnings(io.Writer) option or an accessor (r.Warnings()) so callers can opt in to displaying them without them contaminating command stderr.
  2. Log only once, demote to debug — write to a logger at debug level rather than stderr; still surface via an accessor for tests/diagnostics.
  3. Silently drop missing paths — since the warning content does not change command behaviour, and most deployments will configure cross-platform allowlists, simply omit the fmt.Fprintf for os.OpenRoot failures. Keep the warning for genuinely unexpected errors (e.g. filepath.Abs failure).
  4. Gate behind an env var / option — e.g. RSHELL_VERBOSE_SANDBOX=1, off by default.

Option 1 or 2 preserves the diagnostic for operators who want it; option 3 is simplest if the warning is judged to be more noise than signal in practice.

Workaround for callers today

Strip/replace Unix-shaped paths (/var/log, /etc, /tmp, ...) before sending the allowlist to rshell on Windows — pick platform-appropriate equivalents (C:\ProgramData\Datadog\logs, C:\Windows\Temp, etc.).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions