Skip to content

[Quadlet] HealthCmd fails with shell metacharacters — systemd INI parser mangles values before shell execution #28409

@HoLuLuLu

Description

@HoLuLuLu

Issue Description

Any HealthCmd value in a Quadlet .container file that contains shell metacharacters (single quotes ', brackets []) produces /bin/sh: syntax error: unterminated quoted string at runtime. The identical command works correctly when run via podman exec or directly on the command line.

The only working workaround is moving the command to an external shell script and referencing it as the HealthCmd value.

Steps to reproduce the issue

  1. Create a Quadlet .container file with any of the following HealthCmd values:
# Attempt 1 — single quotes
HealthCmd=/bin/sh -c "netbird status | grep -q 'Management: Connected'"

# Attempt 2 — escaped double quotes
HealthCmd=/bin/sh -c "netbird status | grep -q \"Management: Connected\""

# Attempt 3 — hex escape for single quote
HealthCmd=/bin/sh -c "netbird status | grep -q \x27Management: Connected\x27"

# Attempt 4 — POSIX character class (brackets)
HealthCmd=/bin/sh -c "netbird status | grep -qE Management:[[:space:]]+Connected"

# Attempt 5 — pipe with no quotes
HealthCmd=/bin/sh -c "netbird status | grep Management | grep -qv Not"
  1. Reload and start:
systemctl --user daemon-reload
systemctl --user start <service>.service
  1. Inspect health state:
podman inspect <container> --format "{{json .State.Health}}" | python3 -m json.tool

Describe the results you received

All attempts above produce the same failure:

{
    "Status": "unhealthy",
    "Log": [{
        "Start": "2026-03-29T20:02:35.565735588+02:00",
        "End": "2026-03-29T20:02:35.668385384+02:00",
        "ExitCode": 1,
        "Output": "/bin/sh: syntax error: unterminated quoted string\n"
    }]
}

The same commands execute without error when run directly:

podman exec <container> /bin/sh -c "netbird status | grep -q 'Management: Connected'"
# Exit code: 0 ✓

Describe the results you expected

Healthcheck executes successfully. Exit code 0 when the expected string is present in command output.

podman info output

host:
  arch: amd64
  buildahVersion: 1.39.3
  cgroupControllers:
  - cpu
  - memory
  - pids
  cgroupManager: systemd
  cgroupVersion: v2
  conmon:
    package: conmon_2.1.12-4_amd64
    path: /usr/bin/conmon
    version: 'conmon version 2.1.12, commit: unknown'
  distribution:
    codename: trixie
    distribution: debian
    version: "13"
  kernel: 6.12.74+deb13+1-amd64
  networkBackend: netavark
  networkBackendInfo:
    package: netavark_1.14.0-2_amd64
    version: netavark 1.14.0
  ociRuntime:
    name: crun
    package: crun_1.21-1_amd64
    version: crun version 1.21
  rootlessNetworkCmd: pasta
  security:
    rootless: true
    selinuxEnabled: false
  version:
    APIVersion: 5.4.2
    BuildOrigin: Debian
    Version: 5.4.2

Podman in a container

No

Privileged Or Rootless

Rootless

Upstream Latest Release

Yes

Additional environment details

podman version:   5.4.2 (BuildOrigin: Debian)
OS:               Debian GNU/Linux 13 (trixie)
kernel:           6.12.74+deb13+1-amd64
arch:             amd64
rootless:         true
cgroupManager:    systemd
cgroupVersion:    v2
ociRuntime:       crun 1.21
networkBackend:   netavark 1.14.0
conmon:           2.1.12

Additional information

Potential Root Cause

The HealthCmd value passes through two parsing layers before the shell inside the container sees it:

HealthCmd INI value (raw text)
        ↓
systemd INI parser          ← Layer 1: treats " and ' as its own string delimiters
        ↓
podman --health-cmd "..."   ← receives mangled string
        ↓
/bin/sh -c "..."            ← Layer 2: receives broken string, fails

The systemd INI parser interprets "..." as its own quoted string and strips the outer double quotes. Any remaining shell metacharacters (', [, ]) are then reinterpreted by the systemd parser's own rules — not passed through verbatim to the shell.

Running the command in a terminal bypasses Layer 1 entirely, which is why it works there.

Workaround

Option 1

Use CMD-SHELL for shell execusion:

HealthCmd=CMD-SHELL netbird status | grep -q 'Management: Connected'
Option 2

Move the command to an external script and reference it:

cat > /path/to/healthcheck.sh << 'EOF'
#!/bin/sh
netbird status | grep -q 'Management: Connected'
EOF
chmod +x /path/to/healthcheck.sh
HealthCmd=/path/to/healthcheck.sh

Related Issues

Metadata

Metadata

Assignees

Labels

jirakind/bugCategorizes issue or PR as related to a bug.triagedIssue has been triaged

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions