Skip to content

Instantly share code, notes, and snippets.

@mrreband
Last active June 12, 2026 15:55
Show Gist options
  • Select an option

  • Save mrreband/7e676b9e0a63599731d0d041af4a4659 to your computer and use it in GitHub Desktop.

Select an option

Save mrreband/7e676b9e0a63599731d0d041af4a4659 to your computer and use it in GitHub Desktop.
audit and install vscode extensions with a configurable buffer to guard against recent exploits

vscode-extensions

scripts to audit and update extensions, with a configurable buffer to guard against recent exploits (default 30 days)

  • audit.py audit installed VS Code extensions against the marketplace
  • audit.sh run audit.py to a timestamped, gitignored output folder
  • update.py install available updates that are old enough to be considered stable (default 30 days)
# audit: report supply-chain flags and available updates, generate a markdown report, generate a restore script
./audit.sh

# update: install updates whose marketplace version has been stable for at least 30 days
python3 update.py           # dry-run
python3 update.py --apply   # install

note: audit.py uses datetime.UTC which requires python 3.11 or later

#!/usr/bin/env python3
"""
list installed VS Code extensions with local install date, marketplace last-updated.
Flags extensions whose marketplace update is recent (potential supply-chain risk).
"""
import json
import subprocess
import time
from datetime import datetime, UTC
from pathlib import Path
from urllib import error, request
EXTENSIONS_DIR = Path.home() / ".vscode" / "extensions"
SCRIPT_DIR = Path(__file__).parent
RESTORE_SCRIPT = SCRIPT_DIR / "install-extensions.sh"
MD_REPORT = SCRIPT_DIR / "vscode-extensions.md"
MARKET_DAYS = 30
BATCH_SIZE = 50
BOLD = "\033[1m"
RESET = "\033[0m"
YELLOW = "\033[33m"
GREEN = "\033[32m"
DIM = "\033[2m"
def collect_extensions():
raw = subprocess.check_output(["code", "--list-extensions", "--show-versions"], text=True)
extensions = []
for line in raw.strip().splitlines():
line = line.strip()
if "@" not in line:
continue
ext_id, _, version = line.rpartition("@")
ext_id = ext_id.lower()
local_epoch = 0
try:
matches = [p for p in EXTENSIONS_DIR.iterdir() if p.name.lower().startswith(ext_id + "-")]
if matches:
local_epoch = int(max(p.stat().st_mtime for p in matches))
except OSError:
pass
extensions.append((ext_id, version, local_epoch))
return extensions
def parse_iso(s):
if not s:
return 0
s = s.rstrip("Z")
if "." in s:
s = s[:s.index(".") + 7]
try:
return int(datetime.fromisoformat(s).replace(tzinfo=UTC).timestamp())
except ValueError:
return 0
def query_marketplace(ext_ids):
criteria = [{"filterType": 7, "value": i} for i in ext_ids]
payload = json.dumps({"filters": [{"criteria": criteria}], "flags": 512}).encode()
req = request.Request(
"https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery",
data=payload,
headers={
"Content-Type": "application/json",
"Accept": "application/json;api-version=3.0-preview.1",
},
)
with request.urlopen(req, timeout=30) as resp:
return json.load(resp)
def fetch_marketplace_info(ext_ids):
info = {}
for i in range(0, len(ext_ids), BATCH_SIZE):
batch = ext_ids[i:i + BATCH_SIZE]
try:
data = query_marketplace(batch)
for ext in data.get("results", [{}])[0].get("extensions", []):
pub = ext.get("publisher", {}).get("publisherName", "")
name = ext.get("extensionName", "")
eid = f"{pub}.{name}".lower()
versions = ext.get("versions", [])
info[eid] = {
"last_updated": parse_iso(ext.get("lastUpdated", "")),
"latest_version": versions[0].get("version", "?") if versions else "?",
}
except error.URLError as e:
print(f" [warning] marketplace query failed: {e}", flush=True)
return info
def fmt_epoch(epoch):
return datetime.fromtimestamp(epoch).strftime("%Y-%m-%d %H:%M") if epoch else "not found"
def write_restore_script(extensions):
lines = [
"#!/usr/bin/env bash",
f"# auto-generated by audit.py on {datetime.now().strftime('%Y-%m-%d')}",
"# installs all vscode extensions at their currently-installed versions",
"",
]
for ext_id, version, _ in extensions:
lines.append(f"code --install-extension {ext_id}@{version}")
RESTORE_SCRIPT.write_text("\n".join(lines) + "\n")
RESTORE_SCRIPT.chmod(0o755)
def write_md_report(rows, total):
now_epoch = int(time.time())
recent_cutoff = now_epoch - MARKET_DAYS * 86400
def fmt_md(epoch):
s = fmt_epoch(epoch)
return f"{s} ⚠️" if epoch > recent_cutoff else s
lines = [
"# VS Code Extensions",
"",
f"_generated {datetime.now().strftime('%Y-%m-%d %H:%M')}{total} extensions total_",
"",
]
md_header = "| Extension | Installed | Latest | Local Install Date | Marketplace Updated |"
md_sep = "| --- | --- | --- | --- | --- |"
for flag_label, _, sort_key, _ in GROUPS:
group = sorted([r for r in rows if r["flag"] == flag_label], key=sort_key)
if not group:
continue
lines += [f"## {MD_GROUP_HEADINGS[flag_label]}", "", md_header, md_sep]
for r in group:
lines.append(
f"| {r['ext_id']} | {r['inst_ver']} | {r['latest_ver']} "
f"| {fmt_md(r['local_epoch'])} | {fmt_md(r['mkt_epoch'])} |"
)
lines.append("")
MD_REPORT.write_text("\n".join(lines))
MD_GROUP_HEADINGS = {
"⚠ recently updated": "⚠ Recently Updated (potential supply-chain risk)",
"↑ update available": "↑ Update Available",
"": "Current",
}
GROUPS = [
# (flag_label, color, sort_key, print_to_stdout) -- order here controls print order
("⚠ recently updated", YELLOW, lambda r: (-r["mkt_epoch"], -r["local_epoch"]), True),
("↑ update available", DIM, lambda r: (-r["local_epoch"], -r["mkt_epoch"]), False),
("", "", lambda r: (-r["local_epoch"], -r["mkt_epoch"]), False),
]
def main():
extensions = collect_extensions()
print(f"Found {len(extensions)} installed extensions. Querying marketplace...", flush=True)
mkt = fetch_marketplace_info([e[0] for e in extensions])
now_epoch = int(time.time())
recent_cutoff = now_epoch - MARKET_DAYS * 86400
# build row dicts
rows = []
for ext_id, inst_ver, local_epoch in extensions:
info = mkt.get(ext_id, {})
mkt_epoch = info.get("last_updated", 0)
latest_ver = info.get("latest_version", "?")
if mkt_epoch > recent_cutoff and mkt_epoch > local_epoch:
flag = "⚠ recently updated"
elif latest_ver != "?" and inst_ver != latest_ver:
flag = "↑ update available"
else:
flag = ""
rows.append({
"ext_id": ext_id,
"inst_ver": inst_ver,
"latest_ver": latest_ver,
"local_epoch": local_epoch,
"mkt_epoch": mkt_epoch,
"flag": flag,
})
col = [50, 12, 12, 22, 22]
header = (
f"{'EXTENSION':<{col[0]}} {'INSTALLED':<{col[1]}} {'LATEST':<{col[2]}} "
f"{'LOCAL INSTALL DATE':<{col[3]}} {'MARKETPLACE UPDATED':<{col[4]}} FLAGS"
)
for flag_label, color, sort_key, print_to_stdout in GROUPS:
group = sorted([r for r in rows if r["flag"] == flag_label], key=sort_key)
if not group:
continue
if not print_to_stdout:
continue
print(f"\n{BOLD}{header}{RESET}")
print("-" * 140)
for r in group:
print(
f"{color}{r['ext_id']:<{col[0]}} {r['inst_ver']:<{col[1]}} {r['latest_ver']:<{col[2]}} "
f"{fmt_epoch(r['local_epoch']):<{col[3]}} {fmt_epoch(r['mkt_epoch']):<{col[4]}} {r['flag']}{RESET}"
)
flagged = [r["ext_id"] for r in rows if r["flag"] == "⚠ recently updated"]
updates = [r for r in rows if r["flag"] == "↑ update available"]
safe_updates = [r["ext_id"] for r in updates if r["mkt_epoch"] <= recent_cutoff]
print(f"\n{BOLD}Summary:{RESET}")
print(f" Total extensions : {len(extensions)}")
if flagged:
print(f" {YELLOW}{BOLD}Recently updated (⚠) : {len(flagged)}{RESET}")
for eid in flagged:
print(f" - {eid}")
else:
print(f" {GREEN}No extensions flagged as recently updated.{RESET}")
print(f" Updates available (↑) : {len(updates)}")
print(f" Updates older than {MARKET_DAYS}d : {len(safe_updates)}")
write_restore_script(extensions)
write_md_report(rows, len(extensions))
print(f"\nRestore script written to: {RESTORE_SCRIPT}")
print(f"Markdown report written to: {MD_REPORT}")
if __name__ == "__main__":
main()
#!/usr/bin/env bash
set -euo pipefail
DIR="$(dirname "$0")"
python3 "$DIR/audit.py" "$@"
OUTDIR="$DIR/output/$(date +%Y%m%d)"
mkdir -p "$OUTDIR"
mv "$DIR/install-extensions.sh" "$DIR/vscode-extensions.md" "$OUTDIR/"
echo "Output moved to: $OUTDIR"
#!/usr/bin/env python3
"""
install updates for VS Code extensions to a version that has been available long enough to be trusted
`dry-run` by default; pass --apply to actually install
running with the same --market-days as audit-vscode-extensions.py's MARKET_DAYS
means this script will never touch anything the audit script flags as a supply-chain risk
"""
import argparse
import json
import subprocess
from datetime import datetime, UTC
from pathlib import Path
from urllib import error, request
EXTENSIONS_DIR = Path.home() / ".vscode" / "extensions"
BATCH_SIZE = 50
BOLD = "\033[1m"
RESET = "\033[0m"
GREEN = "\033[32m"
DIM = "\033[2m"
def collect_extensions():
raw = subprocess.check_output(["code", "--list-extensions", "--show-versions"], text=True)
extensions = []
for line in raw.strip().splitlines():
line = line.strip()
if "@" not in line:
continue
ext_id, _, version = line.rpartition("@")
ext_id = ext_id.lower()
local_epoch = 0
try:
matches = [p for p in EXTENSIONS_DIR.iterdir() if p.name.lower().startswith(ext_id + "-")]
if matches:
local_epoch = int(max(p.stat().st_mtime for p in matches))
except OSError:
pass
extensions.append((ext_id, version, local_epoch))
return extensions
def parse_iso(s):
if not s:
return 0
s = s.rstrip("Z")
if "." in s:
s = s[:s.index(".") + 7]
try:
return int(datetime.fromisoformat(s).replace(tzinfo=UTC).timestamp())
except ValueError:
return 0
def query_marketplace(ext_ids):
criteria = [{"filterType": 7, "value": i} for i in ext_ids]
payload = json.dumps({"filters": [{"criteria": criteria}], "flags": 512}).encode()
req = request.Request(
"https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery",
data=payload,
headers={
"Content-Type": "application/json",
"Accept": "application/json;api-version=3.0-preview.1",
},
)
with request.urlopen(req, timeout=30) as resp:
return json.load(resp)
def fetch_marketplace_info(ext_ids):
info = {}
for i in range(0, len(ext_ids), BATCH_SIZE):
batch = ext_ids[i:i + BATCH_SIZE]
try:
data = query_marketplace(batch)
for ext in data.get("results", [{}])[0].get("extensions", []):
pub = ext.get("publisher", {}).get("publisherName", "")
name = ext.get("extensionName", "")
eid = f"{pub}.{name}".lower()
versions = ext.get("versions", [])
info[eid] = {
"last_updated": parse_iso(ext.get("lastUpdated", "")),
"latest_version": versions[0].get("version", "?") if versions else "?",
}
except error.URLError as e:
print(f" [warning] marketplace query failed: {e}", flush=True)
return info
def fmt_epoch(epoch):
return datetime.fromtimestamp(epoch).strftime("%Y-%m-%d") if epoch else "unknown"
def main():
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("--apply", action="store_true", help="install updates (default: dry-run)")
parser.add_argument("--market-days", type=int, default=30, metavar="M", help="min age of marketplace version in days (default: 30)")
args = parser.parse_args()
import time
now_epoch = int(time.time())
market_cutoff = now_epoch - args.market_days * 86400
extensions = collect_extensions()
print(f"Found {len(extensions)} installed extensions. Querying marketplace...", flush=True)
mkt = fetch_marketplace_info([e[0] for e in extensions])
candidates = []
for ext_id, inst_ver, local_epoch in extensions:
info = mkt.get(ext_id, {})
mkt_epoch = info.get("last_updated", 0)
latest_ver = info.get("latest_version", "?")
if latest_ver == "?" or inst_ver == latest_ver:
continue
if mkt_epoch > market_cutoff:
continue
candidates.append({
"ext_id": ext_id,
"inst_ver": inst_ver,
"latest_ver": latest_ver,
"local_epoch": local_epoch,
"mkt_epoch": mkt_epoch,
})
# sort oldest local install first
candidates.sort(key=lambda r: r["local_epoch"])
if not candidates:
print(f"\n{GREEN}No extensions eligible for update.{RESET}")
return
col = [50, 12, 12, 14, 14]
header = f"{'EXTENSION':<{col[0]}} {'INSTALLED':<{col[1]}} {'LATEST':<{col[2]}} {'LOCAL DATE':<{col[3]}} {'MKT DATE':<{col[4]}}"
mode_label = "APPLYING" if args.apply else "DRY RUN"
print(f"\n{BOLD}[{mode_label}] {len(candidates)} extension(s) eligible:{RESET}")
print(f"{DIM}{header}{RESET}")
print(DIM + "-" * sum(col) + RESET)
for r in candidates:
print(
f"{r['ext_id']:<{col[0]}} {r['inst_ver']:<{col[1]}} {r['latest_ver']:<{col[2]}} "
f"{fmt_epoch(r['local_epoch']):<{col[3]}} {fmt_epoch(r['mkt_epoch']):<{col[4]}}"
)
if not args.apply:
print(f"\n{DIM}Pass --apply to install.{RESET}")
return
print()
for r in candidates:
spec = f"{r['ext_id']}@{r['latest_ver']}"
print(f" installing {spec}...", flush=True)
subprocess.run(["code", "--install-extension", spec, "--force"], check=True)
print(f"\n{GREEN}{BOLD}Done. {len(candidates)} extension(s) updated.{RESET}")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment