vskill 1.2.6 → 1.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -55,7 +55,7 @@ And the ones that aren't malicious often *don't even improve the model* — they
55
55
 
56
56
  vskill is built around three problems:
57
57
 
58
- - **Trust** — every install runs a 3-tier scan (52 patterns → blocklist → LLM intent). No `--skip-scan`.
58
+ - **Trust** — every install runs a 3-tier scan (58 patterns + hidden-content checks → blocklist → LLM intent). No `--skip-scan`.
59
59
  - **Proof** — Skill Studio runs A/B evals so you can *show* a skill makes a model better, not assume it.
60
60
  - **Reach** — one skill, 53 agents (Claude Code, Cursor, Copilot, Codex, Windsurf, Zed, Gemini CLI, Ollama, …).
61
61
 
@@ -87,7 +87,7 @@ CORS-free by design: the browser only ever talks to localhost. The server proxie
87
87
  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
88
88
  │ Source │────>│ Scan │────>│ Verify │────>│ Install │
89
89
  │ │ │ │ │ │ │ │
90
- │ GitHub │ │ 52 rules │ │ LLM │ │ Pin SHA │
90
+ │ GitHub │ │ 58 rules │ │ LLM │ │ Pin SHA │
91
91
  │ Registry │ │ Blocklist│ │ intent │ │ Lock ver │
92
92
  │ Local │ │ Patterns │ │ analysis │ │ Symlink │
93
93
  └──────────┘ └──────────┘ └──────────┘ └──────────┘
package/agents.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 1,
3
- "generatedAt": "2026-10-11T11:51:33.859Z",
3
+ "generatedAt": "2026-10-11T14:38:20.036Z",
4
4
  "agentPrefixes": [
5
5
  ".adal",
6
6
  ".agent",
@@ -44,6 +44,12 @@ export const FIX_SUGGESTIONS = {
44
44
  "CE-001": "Replace eval() with JSON.parse() for data or Function constructor for code; never eval user input",
45
45
  "CE-002": "Avoid new Function(); use explicit function definitions instead",
46
46
  "CE-003": "Avoid dynamic imports with user-controlled paths; use a module allowlist",
47
+ "CE-004": "Never unpickle or exec decoded data; use a safe format such as JSON and import modules statically",
48
+ "CI-009": "Call subprocess with an argument list and shell=False instead of os.system/os.popen or shell=True",
49
+ "CI-010": "Avoid Invoke-Expression and encoded PowerShell commands; run reviewed scripts with explicit parameters",
50
+ "CI-011": "Download the PowerShell script, review it, then run it by path instead of piping irm/iwr output into iex",
51
+ "NA-004": "Do not ask users to download and run external binaries or scripts as a prerequisite; ship reviewed code with the skill or name a package-manager install",
52
+ "NA-005": "Do not distribute password-protected archives; publish contents that can be reviewed and scanned",
47
53
  // --- DCI-abuse patterns ---
48
54
  "DCI-001": "Remove DCI blocks that read credential files (~/.ssh/, ~/.aws/, .env); use a secrets manager instead",
49
55
  "DCI-002": "Remove DCI blocks that write to agent config files (CLAUDE.md, .claude/); legitimate skills do not modify agent configuration",
@@ -1 +1 @@
1
- {"version":3,"file":"fix-suggestions.js","sourceRoot":"","sources":["../../src/audit/fix-suggestions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fix-suggestions.js","sourceRoot":"","sources":["../../src/audit/fix-suggestions.ts"],"names":[],"mappings":"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"}
@@ -73,4 +73,9 @@ export declare function enableAfterInstall(skillName: string, entry: {
73
73
  * @internal exported for unit tests; see `enableAfterInstall` note above.
74
74
  */
75
75
  export declare function rollbackInstall(skillName: string, agents: AgentDefinition[], opts: AddOptions): void;
76
+ /**
77
+ * Collect all file contents from a plugin directory for security scanning.
78
+ * Concatenates content from all readable files.
79
+ */
80
+ export declare function collectPluginContent(pluginDir: string): string;
76
81
  export declare function addCommand(source: string | undefined, opts: AddOptions): Promise<void>;
@@ -13,6 +13,7 @@ import { ensureLockfile, writeLockfile, readLockfile, removeSkillFromLock } from
13
13
  import { buildGitHubInstallLockEntry } from "./add-lockfile.js";
14
14
  import { prepareGitHubSkillBundle } from "./add-github-bundle.js";
15
15
  import { runTier1Scan } from "../scanner/index.js";
16
+ import { isBinary } from "../scanner/repo-scanner.js";
16
17
  import { getAvailablePlugins, getPluginSource, getPluginVersion, hasPlugin, discoverUnregisteredPlugins } from "../marketplace/index.js";
17
18
  import { checkInstallSafety, checkLocalInstallSafety } from "../blocklist/blocklist.js";
18
19
  import { getSkill, searchSkills } from "../api/client.js";
@@ -1117,17 +1118,22 @@ function listPluginDirPlugins(basePath) {
1117
1118
  * Collect all file contents from a plugin directory for security scanning.
1118
1119
  * Concatenates content from all readable files.
1119
1120
  */
1120
- function collectPluginContent(pluginDir) {
1121
+ export function collectPluginContent(pluginDir) {
1121
1122
  const files = readdirSync(pluginDir, { recursive: true });
1122
1123
  const parts = [];
1123
1124
  for (const file of files) {
1124
1125
  const fullPath = join(pluginDir, file);
1125
1126
  try {
1126
- const content = readFileSync(fullPath, "utf-8");
1127
- parts.push(`--- ${file} ---\n${content}`);
1127
+ const buffer = readFileSync(fullPath);
1128
+ // Images and other binaries decode to junk that looks like hidden
1129
+ // Unicode (a GIF header can spell tag characters); they are not text
1130
+ // an agent reads, so they are not scanned as text.
1131
+ if (isBinary(buffer))
1132
+ continue;
1133
+ parts.push(`--- ${file} ---\n${buffer.toString("utf-8")}`);
1128
1134
  }
1129
1135
  catch {
1130
- // Skip unreadable files (directories, binary, etc.)
1136
+ // Skip unreadable files (directories, etc.)
1131
1137
  }
1132
1138
  }
1133
1139
  return parts.join("\n");