Skip to content

bug: govern-shell.sh uses fragile sed to parse JSON — denial reason extraction can fail silently #67

@jpleva91

Description

@jpleva91

Bug: Fragile sed-based JSON Parsing in govern-shell.sh

File: scripts/govern-shell.sh

Description

When a command is denied by governance, the script extracts the reason using sed:

REASON=$(echo "$RESULT" | sed 's/.*"reason":"\([^"]*\)".*/\1/')

This has two failure modes:

  1. Silent fallback: If the JSON doesn't contain a "reason" field (e.g., the key is different, or shellforge evaluate returns a different format), sed outputs the entire raw JSON string unchanged. The error message shown to the user becomes the raw JSON blob.

  2. Regex failure on special characters: If reason contains a forward slash /, backslash \, or other sed delimiter characters, the sed expression corrupts or truncates the output.

Reproduction

# If reason contains a slash:
echo '{"allowed":false,"reason":"Path not under outputs/dir"}' | sed 's/.*"reason":"\([^"]*\)".*/\1/'
# → "Path not under outputs" (truncated at the slash — BRE [^"]* stops at /)
# Actually [^"]* continues through /, this is OK. But still fragile.

More critically: if shellforge evaluate fails and returns {"allowed":true} (the hardcoded fallback), but somehow the grep still fires, the sed parsing of an unrelated string gives garbage output.

Fix

Use python3 or jq for robust JSON parsing if available, with a safe fallback:

if command -v jq &>/dev/null; then
    REASON=$(echo "$RESULT" | jq -r '.reason // "policy violation"')
else
    REASON=$(echo "$RESULT" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('reason','policy violation'))" 2>/dev/null || echo "policy violation")
fi

Impact

Users see confusing raw JSON in their terminal when a command is denied, instead of a clear human-readable reason.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High priority bugbugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions