agentsclimarketplace

Run1 package lock json parsing

Skill cxcscmu/SkillLearnBench/skills/b3-teacher-feedback-claude-opus-4-6/dependency-vulnerability-check/run1_package-lock-json-parsing

How to parse package-lock.json to extract all dependency names and versions for vulnerability lookups, covering both lockfile v1, v2, and v3 formats.From its SKILL.md

Install
npx -y skills add cxcscmu/SkillLearnBench --skill run1_package-lock-json-parsing

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

SKILL.md

2.6 KB, 698 tokens by cl100k_base, as published. Nobody here has run it

package-lock.json Format

Lockfile Version 2/3 (npm 7+)

{
  "name": "my-app",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "packages": {
    "": {
      "name": "my-app",
      "dependencies": { "express": "^4.17.1" }
    },
    "node_modules/express": {
      "version": "4.17.1",
      "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
      "dependencies": { "accepts": "~1.3.7" }
    },
    "node_modules/accepts": {
      "version": "1.3.7"
    }
  }
}

Lockfile Version 1 (npm 5-6)

{
  "name": "my-app",
  "version": "1.0.0",
  "lockfileVersion": 1,
  "dependencies": {
    "express": {
      "version": "4.17.1",
      "resolved": "...",
      "requires": { "accepts": "~1.3.7" },
      "dependencies": {
        "accepts": { "version": "1.3.7" }
      }
    }
  }
}

Extracting Dependencies with Python

import json

def extract_deps_v2v3(lockfile_path):
    """Extract from lockfileVersion 2 or 3."""
    with open(lockfile_path) as f:
        data = json.load(f)
    deps = {}
    for path, info in data.get("packages", {}).items():
        if path == "":
            continue  # skip root
        name = path.split("node_modules/")[-1]
        version = info.get("version", "unknown")
        deps[name] = version
    return deps

def extract_deps_v1(lockfile_path):
    """Extract from lockfileVersion 1 (recursive)."""
    with open(lockfile_path) as f:
        data = json.load(f)
    deps = {}
    def recurse(dep_dict):
        for name, info in dep_dict.items():
            version = info.get("version", "unknown")
            # Keep highest-level version or first found
            if name not in deps:
                deps[name] = version
            if "dependencies" in info:
                recurse(info["dependencies"])
    recurse(data.get("dependencies", {}))
    return deps

def extract_all_deps(lockfile_path):
    with open(lockfile_path) as f:
        data = json.load(f)
    version = data.get("lockfileVersion", 1)
    if version >= 2:
        return extract_deps_v2v3(lockfile_path)
    else:
        return extract_deps_v1(lockfile_path)

Extracting with jq

# Lockfile v2/v3
jq -r '.packages | to_entries[] | select(.key != "") | "\(.key | split("node_modules/") | last)\t\(.value.version)"' package-lock.json

# Lockfile v1
jq -r '.dependencies | to_entries[] | "\(.key)\t\(.value.version)"' package-lock.json

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.