Skip to content

feat(providers): add opencode_cli semantic-scan provider - #536

Open
Yoseph-Zuskin wants to merge 1 commit into
NVIDIA:mainfrom
Yoseph-Zuskin:feat/opencode-cli-provider
Open

Yoseph-Zuskin wants to merge 1 commit into
NVIDIA:mainfrom
Yoseph-Zuskin:feat/opencode-cli-provider

Conversation

@Yoseph-Zuskin

Copy link
Copy Markdown

Add opencode_cli semantic-scan provider

Problem

SkillSpector ships CLI providers for Claude, Codex, and Gemini, but none
for OpenCode, so OpenCode users get static-only scans (llm_available
stays false and the three semantic analyzers are skipped).

Fixes: #534

Approach

  • New opencode_cli provider mirroring the codex_cli shape:
    providers/opencode_cli/{provider.py,__init__.py}, registry entry,
    SKILLSPECTOR_PROVIDER=opencode_cli selection, provider_name() label,
    CLI help text.
  • Transport is argv flags + piped stdin: opencode run --format json
    with --model added only when SKILLSPECTOR_MODEL is set. Verified
    live that opencode run consumes piped stdin (nonce round-trip)
    despite no documented stdin flag; list form throughout, shell never
    invoked. Windows hostile-prompt roundtrips covered by test
    (spaces, quotes, unicode, backslashes).
  • JSON-event output parsing accepts the observed --format json
    envelopes, skips non-JSON noise lines, raises fail-closed on empty
    output. Auth check is opencode auth list with a 15s timeout,
    fail-closed.
  • Docs trio updated in the same PR (README provider table, .env.example,
    docs/DEVELOPMENT.md); provider tests live in tests/provider/
    per repo convention.
  • Registry scope kept minimal: free-model token-budget catalog split out
    of this change (separate chore).

Verification

  • tests/provider/test_opencode_cli.py: 31 passed (TDD: argv, auth,
    parser, wiring, registry label).
  • tests/unit/test_agent_cli.py: 87 passed.
  • ruff check + ruff format --check: clean on all touched files.
  • Full unit suite: 4787 passed; 24 failed + 4 errors, all in
    tests/nodes/test_build_context.py (Windows symlink limits),
    test_security_end_to_end.py, test_compare_scan_accuracy.py,
    test_create_github_release.py, test_input_handler.py — none in
    files this PR touches; pre-existing/environmental.
  • Live single-skill probe (opencode 1.18.30, CLI-default model):
    llm_available: true, 3/3 semantic calls succeeded, risk 0/LOW,
    0 findings.
  • Self-scan of the new provider package (opencode 1.18.30,
    CLI-default model): llm_available: true, 3/3 semantic calls
    succeeded, 100% coverage, 0 semantic issues — 3 SC8 bytecode FPs
    from stale local __pycache__, since cleaned.
  • Tested with opencode/nemotron-3-ultra-free and opencode/muse-spark-1.3-contributor-free
    (both free-tier models via OpenCode's zen endpoint); semantic stage
    degraded on shared runtime budget exhaustion (4 parallel calls at once),
    not model failure — confirmed by spacing calls manually.

Sample

Probe scan of one small skill returned
risk: score 0 / LOW / CAUTION, llm_calls_attempted: 3,
llm_calls_succeeded: 3, zero findings.

Risks

  • Event-envelope drift: a future opencode run --format json shape
    change degrades to fail-closed (empty-output raise), never silent
    heuristic-only.
  • inference_usage is empty on this path (no token counters from CLI
    subprocesses); scan integrity unaffected, cost accounting unavailable.
  • DCO: all commits carry Signed-off-by (maintainer: verify on push).
  • Free-tier budget: 4 parallel semantic analyzers exhaust per-minute
    budget instantly; users on free models should use local Ollama or
    add credits for genuine semantic analysis.

- Add providers/opencode_cli/provider.py and __init__.py mirroring codex_cli
- Register opencode in _agent_cli.py: argv builder (opencode run --format json),
  JSON-event parser, auth check (opencode auth list)
- Wire SKILLSPECTOR_PROVIDER=opencode_cli in providers/__init__.py and
  inference_usage.py
- Update docs trio: README provider table, .env.example, docs/DEVELOPMENT.md
- Add model-registry entries for opencode/nemotron-3-ultra-free and
  opencode/nemotron-3.5-lightning-free (1M context)
- Add tests/provider/test_opencode_cli.py (31 tests: argv, auth, parser,
  wiring, registry label)
- Verified: live probe and self-scan with opencode 1.18.30 (CLI-default
  model), llm_available=true, 3/3 semantic calls succeeded; self-scan of
  the provider package found 0 semantic issues

Signed-off-by: Yoseph Zuskin <zuskinyoseph@gmail.com>
Co-Authored-By: OpenCode Muse Spark 1.3 Free (1M context) <noreply@opencode.ai>
Co-Authored-By: OpenCode Nemotron 3 Ultra Free (1M context) <noreply@opencode.ai>

@rng1995 rng1995 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[SkillSpector Review]

Reviewed current head 4e36534712752b3c2a61762f6f0e435b01f1a3ca. Required checks pass, but the new transport is not safe for its trust boundary: untrusted skill text is sent to OpenCode while built-in host tools remain enabled under permissive defaults. --pure removes plugins only; the temporary working directory and scrubbed environment do not prevent shell/network side effects or ambient auto-sharing. Establish a fixed deny-all, non-overridable OpenCode policy and prove it with adversarial tests before enabling this provider.

The security change and mergeStateStatus=BEHIND block merging.

return [
binary,
"run",
"--pure",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Deny OpenCode's built-in tools before scanning untrusted skills

--pure disables external plugins, not built-in tools. OpenCode's default policy permits most host capabilities, and noninteractive run rejects only operations that resolve to ask, so attacker-controlled skill text can induce shell, filesystem, or network side effects. A temporary CWD and environment scrubbing are not an OS sandbox. Launch with a fixed, non-overridable deny-all tool/permission configuration (including ambient sharing/config), and add an adversarial test proving bash/web/file side effects cannot occur; otherwise this provider must not be exposed.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add OpenCode CLI Provider

2 participants