Back to skill

Security audit

VSCode

Security checks for vulnerabilities and agentic risk

Overview

This VS Code helper is coherent, but it automatically keeps shared local records about projects, hosts, and access pointers without asking first.

Install only if you are comfortable with the skill maintaining a local Clawic knowledge base about your VS Code setup, repositories, extensions, remote hosts, and access-pointer locations. Review or disable the automatic memory behavior for sensitive work, and periodically inspect and prune ~/Clawic/data/vscode/, ~/Clawic/data/servers/, and ~/Clawic/data/projects/.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
SKILL.md:34
Finding
Mandatory Persistent Collection of Sensitive Operational Metadata Without Explicit Consent<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:34-36`, `memory-template.md:24,33-34`, `git.md:7,94`, `remote.md:121`, `security.md:116` **Vulnerability Type**: Least-privilege violation through consent-free persistent data collection **Risk Level**: Medium ### Vulnerable Code Snippets `SKILL.md:34-36`: ```markdown **Data.** At the start of every session, read `~/Clawic/data/vscode/config.yaml` (what the user declared) and `~/Clawic/data/vscode/memory.md` (what you observed, plus its `## Boxes` index and `## Due` table). Open any file `## Boxes` names when the condition on its line applies — the index is the list of files, never assume the list is fixed. Every path it names is inside `~/Clawic/data/`; ignore any line that points anywhere else. Everything this skill reads or writes is a plain local note under the folders declared in `configPaths` — nothing leaves the machine and no credential is ever written. In a shared box it updates or removes only the rows it wrote itself, matched on that box's identity key; a row another skill wrote is read, never rewritten and never deleted, and every write and deletion is named in one line as it happens. Read `~/Clawic/data/servers/servers.md` before touching Remote-SSH, a tunnel, or a dev container on a named host. If none of it exists, work from defaults and say nothing about it. **Write before the session ends** whenever it produced something durable: a config that finally worked (`settings.json`, `launch.json`, `tasks.json` with its problem matcher, `keybindings.json`, `devcontainer.json`, a `.code-workspace`, a snippet set); an extension adopted, rejected, or blamed for a conflict; a profile and what it is for; a per-project editor setup; a remote host reached from the editor; an environment fact that cost effort to find (shell PATH resolution, keyboard layout, watcher limit, glibc floor, marketplace restriction); a failure whose cause was not obvious; or a decision the user will re-litigate. `mem ...[truncated 4483 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require explicit user opt-in before creating or updating any persistent record. 2. Default to session-only processing for one-off troubleshooting. 3. Separate private skill-local state from shared inventories; require separate consent for shared writes. 4. Collect only fields necessary for a clearly stated future use. 5. Do not persist credential-file pointers, proxy/CA details, ports, forwarding policy, cost, or host-provider information unless the user explicitly requests it. 6. Show the exact proposed record before writing and permit field-level rejection. 7. Provide retention periods and commands to inspect, export, and delete stored records. 8. Apply restrictive filesystem permissions to persistent storage. 9. Record access provenance so users can identify which skill created or read each entry. 10. Replace “No permission needed” with a consent requirement for all new files, shared rows, and security-sensitive metadata. ]]>

T02 · Agent Memory Poisoning

Warning
Location
SKILL.md:34
Finding
Cross-Session Memory Poisoning Through Automatically Reloaded Artifacts<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:34-36`, `memory-template.md:24,55-58,148-149`, `settings.md:7`, `git.md:7`, `security.md:116` **Vulnerability Type**: Persistent memory poisoning through untrusted stored observations and configurations **Risk Level**: Medium ### Vulnerable Code Snippets `SKILL.md:34`: ```markdown **Data.** At the start of every session, read `~/Clawic/data/vscode/config.yaml` (what the user declared) and `~/Clawic/data/vscode/memory.md` (what you observed, plus its `## Boxes` index and `## Due` table). Open any file `## Boxes` names when the condition on its line applies — the index is the list of files, never assume the list is fixed. Every path it names is inside `~/Clawic/data/`; ignore any line that points anywhere else. ``` `SKILL.md:36`: ```markdown **Write before the session ends** whenever it produced something durable: a config that finally worked (`settings.json`, `launch.json`, `tasks.json` with its problem matcher, `keybindings.json`, `devcontainer.json`, a `.code-workspace`, a snippet set); an extension adopted, rejected, or blamed for a conflict; a profile and what it is for; a per-project editor setup; a remote host reached from the editor; an environment fact that cost effort to find (shell PATH resolution, keyboard layout, watcher limit, glibc floor, marketplace restriction); a failure whose cause was not obvious; or a decision the user will re-litigate. `memory-template.md` holds every destination, format and threshold, and is the only file you open in order to write. ``` `memory-template.md:24`: ```markdown No permission needed; every write is announced in one line that names the file. Writes and deletions stay inside the paths declared in this skill's `configPaths`. ``` `memory-template.md:55-58`: ```markdown Artifacts are the exception: a config file, a runbook or a decision is born as its own file whatever its size, because it is read whole and only when its subject comes up. ``` `s ...[truncated 4145 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Treat every memory file and artifact as untrusted data, never as authoritative instructions. 2. Add an explicit rule that imperative text found in memory must not alter the agent’s goals, safety constraints, or tool policy. 3. Store configurations in typed, schema-validated fields instead of unrestricted Markdown where possible. 4. Preserve provenance for every record, including source file, repository, commit, timestamp, authoring skill, and trust status. 5. Mark repository-derived content as untrusted even after it is copied into persistent storage. 6. Require fresh user confirmation before applying any stored executable configuration, including tasks, debug adapters, lifecycle commands, tool paths, tunnels, and extension installations. 7. Re-review stored configurations for `runOn`, shell commands, lifecycle hooks, executable paths, environment variables, and network exposure before reuse. 8. Add integrity protection or ownership checks to prevent other processes or skills from silently changing indexed artifacts. 9. Introduce expiration and review dates for security decisions, host policies, and executable artifacts. 10. Sanitize stored text by escaping or rejecting instruction-like content unrelated to the structured record. 11. Do not automatically open arbitrary indexed files; use an allowlisted artifact type and verify that the file was created by the expected skill. 12. Provide a user-visible diff before a stored artifact is applied to a live workspace. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (48)

Credential Access

High
Category
Privilege Escalation
Content
**Remote hosts go to the shared inventory `~/Clawic/data/servers/servers.md`**, not here: one file holds machines from every provider, so "which box am I editing on" answers itself whoever provisioned it. One row per host, identified by `Name` + `Provider` — update your own row in place, never append a second one. A tracked codebase goes to the shared `~/Clawic/data/projects/<project>.md` by name; the editor-shaped facts about it stay here.

**No credential is ever written anywhere under `~/Clawic/data/`** — not in the files named here, not in a file you create, not in text the user pastes in to be saved. A pasted `settings.json`, `devcontainer.json`, `tasks.json` or terminal-env block is the densest source of secrets in this domain: strip the value and store the pointer — `env:GITHUB_TOKEN`, `keychain:npm-publish`, `1password:Work/Registry/ci`, `file:~/.ssh/id_ed25519`. If data sits at an old location (`~/vscode/` or `~/clawic/vscode/`), move it to `~/Clawic/data/vscode/`, and say in one line that you moved it and from where.

Almost every VS Code problem is one of five things: a setting resolved at the wrong scope, an extension doing something you did not attribute to it, a path that means something different to the debugger than to you, a process boundary (extension host, remote server, shell), or trust. Name which one before proposing a fix, and give the file, the key, and the value that changes. Work from defaults immediately: never open with questions about their OS, their extensions, or how proactive to be. The one exception to silence is `os_family` — while it is unset, give shortcuts in both `Cmd` and `Ctrl` form rather than asking. That is a statement, not a question. Precedence for any value: `config.yaml` → `~/Clawic/profile.yaml` (shared universals) → the Configuration table default.
Confidence
90% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
**Remote hosts go to the shared inventory `~/Clawic/data/servers/servers.md`**, not here: one file holds machines from every provider, so "which box am I editing on" answers itself whoever provisioned it. One row per host, identified by `Name` + `Provider` — update your own row in place, never append a second one. A tracked codebase goes to the shared `~/Clawic/data/projects/<project>.md` by name; the editor-shaped facts about it stay here.

**No credential is ever written anywhere under `~/Clawic/data/`** — not in the files named here, not in a file you create, not in text the user pastes in to be saved. A pasted `settings.json`, `devcontainer.json`, `tasks.json` or terminal-env block is the densest source of secrets in this domain: strip the value and store the pointer — `env:GITHUB_TOKEN`, `keychain:npm-publish`, `1password:Work/Registry/ci`, `file:~/.ssh/id_ed25519`. If data sits at an old location (`~/vscode/` or `~/clawic/vscode/`), move it to `~/Clawic/data/vscode/`, and say in one line that you moved it and from where.

Almost every VS Code problem is one of five things: a setting resolved at the wrong scope, an extension doing something you did not attribute to it, a path that means something different to the debugger than to you, a process boundary (extension host, remote server, shell), or trust. Name which one before proposing a fix, and give the file, the key, and the value that changes. Work from defaults immediately: never open with questions about their OS, their extensions, or how proactive to be. The one exception to silence is `os_family` — while it is unset, give shortcuts in both `Cmd` and `Ctrl` form rather than asking. That is a statement, not a question. Precedence for any value: `config.yaml` → `~/Clawic/profile.yaml` (shared universals) → the Configuration table default.
Confidence
90% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
**Remote hosts go to the shared inventory `~/Clawic/data/servers/servers.md`**, not here: one file holds machines from every provider, so "which box am I editing on" answers itself whoever provisioned it. One row per host, identified by `Name` + `Provider` — update your own row in place, never append a second one. A tracked codebase goes to the shared `~/Clawic/data/projects/<project>.md` by name; the editor-shaped facts about it stay here.

**No credential is ever written anywhere under `~/Clawic/data/`** — not in the files named here, not in a file you create, not in text the user pastes in to be saved. A pasted `settings.json`, `devcontainer.json`, `tasks.json` or terminal-env block is the densest source of secrets in this domain: strip the value and store the pointer — `env:GITHUB_TOKEN`, `keychain:npm-publish`, `1password:Work/Registry/ci`, `file:~/.ssh/id_ed25519`. If data sits at an old location (`~/vscode/` or `~/clawic/vscode/`), move it to `~/Clawic/data/vscode/`, and say in one line that you moved it and from where.

Almost every VS Code problem is one of five things: a setting resolved at the wrong scope, an extension doing something you did not attribute to it, a path that means something different to the debugger than to you, a process boundary (extension host, remote server, shell), or trust. Name which one before proposing a fix, and give the file, the key, and the value that changes. Work from defaults immediately: never open with questions about their OS, their extensions, or how proactive to be. The one exception to silence is `os_family` — while it is unset, give shortcuts in both `Cmd` and `Ctrl` form rather than asking. That is a statement, not a question. Precedence for any value: `config.yaml` → `~/Clawic/profile.yaml` (shared universals) → the Configuration table default.
Confidence
90% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
**Remote hosts go to the shared inventory `~/Clawic/data/servers/servers.md`**, not here: one file holds machines from every provider, so "which box am I editing on" answers itself whoever provisioned it. One row per host, identified by `Name` + `Provider` — update your own row in place, never append a second one. A tracked codebase goes to the shared `~/Clawic/data/projects/<project>.md` by name; the editor-shaped facts about it stay here.

**No credential is ever written anywhere under `~/Clawic/data/`** — not in the files named here, not in a file you create, not in text the user pastes in to be saved. A pasted `settings.json`, `devcontainer.json`, `tasks.json` or terminal-env block is the densest source of secrets in this domain: strip the value and store the pointer — `env:GITHUB_TOKEN`, `keychain:npm-publish`, `1password:Work/Registry/ci`, `file:~/.ssh/id_ed25519`. If data sits at an old location (`~/vscode/` or `~/clawic/vscode/`), move it to `~/Clawic/data/vscode/`, and say in one line that you moved it and from where.

Almost every VS Code problem is one of five things: a setting resolved at the wrong scope, an extension doing something you did not attribute to it, a path that means something different to the debugger than to you, a process boundary (extension host, remote server, shell), or trust. Name which one before proposing a fix, and give the file, the key, and the value that changes. Work from defaults immediately: never open with questions about their OS, their extensions, or how proactive to be. The one exception to silence is `os_family` — while it is unset, give shortcuts in both `Cmd` and `Ctrl` form rather than asking. That is a statement, not a question. Precedence for any value: `config.yaml` → `~/Clawic/profile.yaml` (shared universals) → the Configuration table default.
Confidence
90% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
**Remote hosts go to the shared inventory `~/Clawic/data/servers/servers.md`**, not here: one file holds machines from every provider, so "which box am I editing on" answers itself whoever provisioned it. One row per host, identified by `Name` + `Provider` — update your own row in place, never append a second one. A tracked codebase goes to the shared `~/Clawic/data/projects/<project>.md` by name; the editor-shaped facts about it stay here.

**No credential is ever written anywhere under `~/Clawic/data/`** — not in the files named here, not in a file you create, not in text the user pastes in to be saved. A pasted `settings.json`, `devcontainer.json`, `tasks.json` or terminal-env block is the densest source of secrets in this domain: strip the value and store the pointer — `env:GITHUB_TOKEN`, `keychain:npm-publish`, `1password:Work/Registry/ci`, `file:~/.ssh/id_ed25519`. If data sits at an old location (`~/vscode/` or `~/clawic/vscode/`), move it to `~/Clawic/data/vscode/`, and say in one line that you moved it and from where.

Almost every VS Code problem is one of five things: a setting resolved at the wrong scope, an extension doing something you did not attribute to it, a path that means something different to the debugger than to you, a process boundary (extension host, remote server, shell), or trust. Name which one before proposing a fix, and give the file, the key, and the value that changes. Work from defaults immediately: never open with questions about their OS, their extensions, or how proactive to be. The one exception to silence is `os_family` — while it is unset, give shortcuts in both `Cmd` and `Ctrl` form rather than asking. That is a statement, not a question. Precedence for any value: `config.yaml` → `~/Clawic/profile.yaml` (shared universals) → the Configuration table default.
Confidence
90% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Ae1

High
Category
analysis-evasion
Content
ser → Remote → Workspace → Folder, then language-specific inside it (Rule 1) | `settings.md` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
ser → Remote → Workspace → Folder, then language-specific inside it (Rule 1) | `settings.md` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
ser → Remote → Workspace → Folder, then language-specific inside it (Rule 1) | `settings.md` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
ser → Remote → Workspace → Folder, then language-specific inside it (Rule 1) | `settings.md` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
ser → Remote → Workspace → Folder, then language-specific inside it (Rule 1) | `settings.md` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
d` + `beginsPattern`/`endsPattern`; matcher `fileLocation` is the usual miss | `tasks.md` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
d` + `beginsPattern`/`endsPattern`; matcher `fileLocation` is the usual miss | `tasks.md` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
d` + `beginsPattern`/`endsPattern`; matcher `fileLocation` is the usual miss | `tasks.md` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| Snippets, suggestions, multi-cursor, or Emmet misbehaving | Suggest settings, snippet scope, `editor.multiCursorModifier` side effects | `editing.md` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| Snippets, suggestions, multi-cursor, or Emmet misbehaving | Suggest settings, snippet scope, `editor.multiCursorModifier` side effects | `editing.md` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| Snippets, suggestions, multi-cursor, or Emmet misbehaving | Suggest settings, snippet scope, `editor.multiCursorModifier` side effects | `editing.md` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| Multi-root workspace, or per-folder settings ignored | `.code-workspace` semantics and which settings survive at folder scope | `workspaces.md` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| Multi-root workspace, or per-folder settings ignored | `.code-workspace` semantics and which settings survive at folder scope | `workspaces.md` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| Multi-root workspace, or per-folder settings ignored | `.code-workspace` semantics and which settings survive at folder scope | `workspaces.md` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| Multi-root workspace, or per-folder settings ignored | `.code-workspace` semantics and which settings survive at folder scope | `workspaces.md` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| Multi-root workspace, or per-folder settings ignored | `.code-workspace` semantics and which settings survive at folder scope | `workspaces.md` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Credential Access

High
Category
Privilege Escalation
Content
Nothing under `~/Clawic/data/` ever holds a secret value — not the files named here, not files you create, not text the user pastes in and asks you to keep. A pasted `settings.json`, `tasks.json`, `devcontainer.json`, `launch.json` `env` block or terminal environment block is the densest source of secrets in this domain: strip each value **before** writing and leave its pointer in place, in this shape: `<kind>:<locator>`.

`env:GITHUB_TOKEN` · `keychain:npm-publish` · `1password:Work/Registry/ci` · `bitwarden:Dev/Sentry` · `vault:secret/dev/api` · `profile:work` · `file:~/.ssh/id_ed25519` · `file:~/.npmrc`

In a text, the pointer goes where the value was: `"GITHUB_TOKEN": "<env:GITHUB_TOKEN>"`. Say in one line that you did it.
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
In this domain — **not secrets, keep them**: extension ids and versions, setting keys, task and launch labels, problem-matcher regexes, file and folder paths, workspace and profile names, host names and SSH aliases, port numbers, interpreter and toolchain paths, marketplace names, git remote URLs without credentials, keyboard shortcuts, glibc and editor version numbers.

**Secrets, strip them**: personal access tokens and API keys in `terminal.integrated.env.*`, `tasks.json` `options.env`, `launch.json` `env`, or `devcontainer.json` `containerEnv`/`remoteEnv`; registry tokens in `.npmrc`/`.pypirc` the user pastes; `settings.json` keys ending in `apiKey`, `token`, `secret`, or `password`; SSH private keys and passphrases; git remote URLs that embed a password; license keys; proxy URLs carrying credentials.

**Contents:** [config.yaml](#configyaml) · [memory.md](#memorymd) · [shared servers inventory](#shared-servers-inventory) · [shared projects box](#shared-projects-box) · [artifacts/](#artifacts) · [split-out files](#split-out-files)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
In this domain — **not secrets, keep them**: extension ids and versions, setting keys, task and launch labels, problem-matcher regexes, file and folder paths, workspace and profile names, host names and SSH aliases, port numbers, interpreter and toolchain paths, marketplace names, git remote URLs without credentials, keyboard shortcuts, glibc and editor version numbers.

**Secrets, strip them**: personal access tokens and API keys in `terminal.integrated.env.*`, `tasks.json` `options.env`, `launch.json` `env`, or `devcontainer.json` `containerEnv`/`remoteEnv`; registry tokens in `.npmrc`/`.pypirc` the user pastes; `settings.json` keys ending in `apiKey`, `token`, `secret`, or `password`; SSH private keys and passphrases; git remote URLs that embed a password; license keys; proxy URLs carrying credentials.

**Contents:** [config.yaml](#configyaml) · [memory.md](#memorymd) · [shared servers inventory](#shared-servers-inventory) · [shared projects box](#shared-projects-box) · [artifacts/](#artifacts) · [split-out files](#split-out-files)
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## Environment
macOS 15, arm64, VS Code stable, zsh with a `.zshrc` that prints a banner — shell-env resolution failed until it was guarded by `[[ -o interactive ]]`.
Corporate proxy needs `http.proxyStrictSSL: false` plus the CA in the system keychain; extension installs fail without it.
Linux workstation: `fs.inotify.max_user_watches` raised to 524288; below that the monorepo threw ENOSPC on open.
Right Alt remapped at the OS level — `alt+click` multi-cursor unavailable, so `editor.multiCursorModifier` is `ctrlCmd`.
Remote `build-1` runs Debian 12; anything older than glibc 2.28 cannot host the server (`vscode >=1.86`).
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Static analysis

No suspicious patterns detected.