{"id":"MAL-2026-17630","revision":"84626340539e4be1b1b950477c2e4b17","records":[{"revision":"84626340539e4be1b1b950477c2e4b17","observedAt":"2026-10-29T14:12:32.841+00:00","statement":{"source":"osv","id":"MAL-2026-17630","aliases":[],"title":"Malicious code in virgil-cli (npm)","description":"In local mode virgil-cli prints that it runs on the user's machine and is free and private. After each turn, reportLearning() in dist/api.js posts the whole conversation history, including shell and file tool output, to https://api.nm-streetwear.space/vx/learn with a hardcoded token and a device id. I found no mention of this in the README and no setting to turn it off. I did not see it read credentials itself, but tool output can contain secrets. I read 0.1.4 only and did not run it.\n\n---\n_-= Per source details. Do not edit below this line.=-_\n\n## Source: amazon-inspector (a603c1f5f6674c45322b6017e44aa35a824a3c4d57ecf9571b214276b2538624)\nvirgil-cli is an AI agent command-line tool whose README advertises that it 'runs commands' on the user's machine. On explicit CLI invocation (not on npm install or require), api.js POSTs the conversation to a hardcoded control plane at https://api.nm-streetwear.space/vx/agent using a shared static token 'virgil-ext-8528'. The server's response includes tool_calls that loop.js dispatches locally, including a run_shell tool implemented in runShell.js as child_process.spawn(command, { cwd, shell: true,... }). A per-command confirmation prompt exists but is bypassed by the documented --auto / -y flag and by an 'always allow' persistence option. The baseUrl is overridable via ~/.virgil/config.json. Separately, when local-Ollama inference is configured, api.js reportLearning() POSTs the full message history (including read_file contents, run_shell stdout/stderr, and list_dir output harvested from the user's machine during the session) to https://api.nm-streetwear.space/vx/learn after every turn, despite setup.js framing local mode as a privacy option. The destination is the vendor's own first-party endpoint and user-reconfigurable; the shared static bearer token offers no per-installer authentication, so any party able to reach the control plane or MITM the TLS channel can direct shell execution on hosts running the CLI, and the local-mode transcript upload contradicts the local-only privacy framing.\n","state":0,"publishedAt":"2026-10-03T22:47:45+00:00","modifiedAt":"2026-10-29T13:48:11.5823125+00:00","affected":[{"ecosystem":"npm","name":"virgil-cli","ranges":[],"versions":["0.1.4"],"rawVersionEvidence":null}],"metrics":[],"references":["https://www.npmjs.com/package/virgil-cli/v/0.1.4"],"sourceUrl":"https://osv.dev/vulnerability/MAL-2026-17630","license":"OSV · upstream source license applies","key":"osv:MAL-2026-17630","identifiers":["MAL-2026-17630"]},"retained":false,"historicalAffected":[]}],"coverage":[]}