From 98299deb2d3b777f3bbf554f300a4e73ea5600b3 Mon Sep 17 00:00:00 2001 From: sickn33 Date: Sun, 29 Mar 2026 11:13:05 +0200 Subject: [PATCH] docs(security): Refresh current-head triage Re-triage the 2026-03-15 security finding set against current main, keep the old snapshot as historical baseline, and add a current-head refresh with updated counts and finding status.\n\nLink the baseline and addendum to the new refresh report so maintainers have one current source of truth for what is still reproducible on HEAD. --- .../security-findings-triage-2026-03-15.md | 2 +- ...ity-findings-triage-2026-03-29-addendum.md | 3 + ...rity-findings-triage-2026-03-29-refresh.md | 84 +++++++++++++++++++ walkthrough.md | 14 ++++ 4 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 docs/maintainers/security-findings-triage-2026-03-29-refresh.md diff --git a/docs/maintainers/security-findings-triage-2026-03-15.md b/docs/maintainers/security-findings-triage-2026-03-15.md index c6dd13c6..a78ad8a3 100644 --- a/docs/maintainers/security-findings-triage-2026-03-15.md +++ b/docs/maintainers/security-findings-triage-2026-03-15.md @@ -1,6 +1,6 @@ # Security Findings Triage (2026-03-15) -Maintainer note: later fixes changed the status of several findings after this baseline snapshot. See [`security-findings-triage-2026-03-29-addendum.md`](security-findings-triage-2026-03-29-addendum.md) before using this file as the current source of truth. +Maintainer note: later fixes changed the status of several findings after this baseline snapshot. Use [`security-findings-triage-2026-03-29-refresh.md`](security-findings-triage-2026-03-29-refresh.md) as the current source of truth, and keep this file as the historical baseline snapshot. - Baseline: `origin/main@226f10c2a62fc182b4e93458bddea2e60f9b0cb9` - Input CSV was treated as triage input only, not as ground truth. diff --git a/docs/maintainers/security-findings-triage-2026-03-29-addendum.md b/docs/maintainers/security-findings-triage-2026-03-29-addendum.md index 9f66aba6..9db450a6 100644 --- a/docs/maintainers/security-findings-triage-2026-03-29-addendum.md +++ b/docs/maintainers/security-findings-triage-2026-03-29-addendum.md @@ -3,6 +3,9 @@ This addendum updates the 2026-03-15 baseline after the follow-up hardening work shipped on `main`. +For the full current-head re-triage, use +[`security-findings-triage-2026-03-29-refresh.md`](security-findings-triage-2026-03-29-refresh.md). + ## Corrected / Updated Findings - Finding `1` / `7` (`tools/scripts/sync_microsoft_skills.py`) diff --git a/docs/maintainers/security-findings-triage-2026-03-29-refresh.md b/docs/maintainers/security-findings-triage-2026-03-29-refresh.md new file mode 100644 index 00000000..34b581c8 --- /dev/null +++ b/docs/maintainers/security-findings-triage-2026-03-29-refresh.md @@ -0,0 +1,84 @@ +# Security Findings Re-Triage (2026-03-29) + +This document is the current-head refresh of the historical +[`security-findings-triage-2026-03-15.md`](security-findings-triage-2026-03-15.md) +baseline. + +- Baseline snapshot: `origin/main@226f10c2a62fc182b4e93458bddea2e60f9b0cb9` +- Current verification target: `main@d63d99381b8f613f99c8cb7b758e7879b401f8a0` +- The 2026-03-15 markdown file and CSV remain useful as historical input, not + as the current source of truth. +- Status meanings are unchanged: + `still present and exploitable`, `still present but low practical risk`, + `obsolete/not reproducible on current HEAD`, `duplicate of another finding`. + +## Summary On Current HEAD + +- still present and exploitable: 0 +- still present but low practical risk: 0 +- obsolete/not reproducible on current HEAD: 26 +- duplicate of another finding: 7 + +## High-Level Outcome + +The 2026-03-15 finding set no longer contains a currently reproduced open +security issue on `main`. + +The biggest shifts since the original baseline are: + +- filesystem/symlink hardening in `setup_web.js`, `install.js`, + `sync_microsoft_skills.py`, `generate_index.py`, `fix_skills_metadata.py`, + and `skill-utils.js` +- removal of shared frontend writes for skill saves/stars +- parser hardening for non-mapping YAML frontmatter +- secure extraction in the Office unpack helpers +- migration of predictable `/tmp` state files into user-owned state + directories +- documentation hardening for risky command guidance + +## Detailed Findings + +| # | Current Status | Current HEAD Rationale | Evidence | +|---|---|---|---| +| 1 | obsolete/not reproducible on current HEAD | `sync_microsoft_skills.py` now sanitizes flat names and constrains delete/copy targets to safe in-repo paths. | `tools/scripts/sync_microsoft_skills.py`, `tools/scripts/tests/test_sync_microsoft_skills_security.py` | +| 2 | obsolete/not reproducible on current HEAD | `SkillDetail.tsx` still renders markdown without `rehype-raw`; the reported stored-XSS path does not reproduce. | `apps/web-app/src/pages/SkillDetail.tsx` | +| 3 | obsolete/not reproducible on current HEAD | `setup_web.js` now uses `lstatSync` plus `resolveSafeRealPath()` and skips out-of-root symlinks instead of dereferencing them into public assets. | `tools/scripts/setup_web.js`, `tools/scripts/tests/copy_security.test.js` | +| 4 | obsolete/not reproducible on current HEAD | The Apify skill no longer recommends pipe-to-shell installs or token-on-command-line login; the risky documentation pattern was removed. | `skills/apify-actorization/SKILL.md` | +| 5 | duplicate of another finding | Still the same root cause/fix area as finding `3`. | `tools/scripts/setup_web.js` | +| 6 | duplicate of another finding | Still the same root cause/fix area as finding `3`. | `tools/scripts/setup_web.js` | +| 7 | obsolete/not reproducible on current HEAD | Microsoft sync now rejects unsafe symlink targets and only accepts safe regular files that stay within the cloned source root. | `tools/scripts/sync_microsoft_skills.py`, `tools/scripts/tests/test_sync_microsoft_skills_security.py` | +| 8 | duplicate of another finding | Still the same root cause/fix area as finding `7`. | `tools/scripts/sync_microsoft_skills.py` | +| 9 | obsolete/not reproducible on current HEAD | The tracked `__pycache__` artifacts are absent on current `main`, and repo hygiene tests explicitly fail if they reappear. | `tools/scripts/tests/repo_hygiene_security.test.js` | +| 10 | obsolete/not reproducible on current HEAD | `generate_index.py` now ignores symlinked `SKILL.md` files instead of reading them during index generation. | `tools/scripts/generate_index.py`, `tools/scripts/tests/test_frontmatter_parsing_security.py` | +| 11 | obsolete/not reproducible on current HEAD | The Jetski loader rejects symlinked skill directories/files and refuses any resolved `SKILL.md` outside the configured skills root. | `docs/integrations/jetski-gemini-loader/loader.mjs`, `tools/scripts/tests/jetski_gemini_loader.test.cjs` | +| 12 | obsolete/not reproducible on current HEAD | TLS verification is enabled by default again; insecure behavior now requires an explicit opt-out environment flag. | `skills/junta-leiloeiros/scripts/scraper/base_scraper.py`, `skills/junta-leiloeiros/scripts/web_scraper_fallback.py` | +| 13 | obsolete/not reproducible on current HEAD | The old bundle-category omission path still does not drive shipped bundle output; current bundles come from `build-catalog.js`. | `tools/scripts/build-catalog.js`, `data/bundles.json` | +| 14 | obsolete/not reproducible on current HEAD | The malformed `--- Unknown` frontmatter regression is no longer present in `alpha-vantage`. | `skills/alpha-vantage/SKILL.md`, `tools/scripts/tests/repo_hygiene_security.test.js` | +| 15 | obsolete/not reproducible on current HEAD | `ws_listener.py` now defaults to a user-owned state directory and uses secure file creation instead of predictable shared `/tmp` output files. | `skills/videodb/scripts/ws_listener.py`, `tools/scripts/tests/local_temp_safety.test.js` | +| 16 | obsolete/not reproducible on current HEAD | `refresh-skills-plugin.js` now resolves real paths under the skills root before serving `/skills/*`; the public Pages app also no longer exposes the maintainer sync surface. | `apps/web-app/refresh-skills-plugin.js`, `README.md`, `apps/web-app/README.md` | +| 17 | duplicate of another finding | Still the same root cause/fix area as finding `16`. | `apps/web-app/refresh-skills-plugin.js` | +| 18 | obsolete/not reproducible on current HEAD | `validate_skills.py` now rejects non-mapping YAML frontmatter cleanly instead of crashing downstream validation. | `tools/scripts/validate_skills.py`, `tools/scripts/tests/test_frontmatter_parsing_security.py` | +| 19 | obsolete/not reproducible on current HEAD | `useSkillStars` now stores saves locally in the browser and no longer performs shared frontend writes through the public Supabase client. | `apps/web-app/src/hooks/useSkillStars.ts`, `apps/web-app/src/lib/supabase.ts` | +| 20 | obsolete/not reproducible on current HEAD | `fix_skills_metadata.py` now skips symlinked `SKILL.md` files and non-mapping frontmatter instead of rewriting arbitrary targets. | `tools/scripts/fix_skills_metadata.py` | +| 21 | obsolete/not reproducible on current HEAD | `install.js` now uses `lstatSync` plus `resolveSafeRealPath()` and skips symlinks that resolve outside the cloned repo root. | `tools/bin/install.js`, `tools/scripts/tests/copy_security.test.js` | +| 22 | duplicate of another finding | Still the same root cause/fix area as finding `21`. | `tools/bin/install.js` | +| 23 | duplicate of another finding | Still the same root cause/fix area as finding `1`. | `tools/scripts/sync_microsoft_skills.py` | +| 24 | obsolete/not reproducible on current HEAD | The audio transcription example now uses a quoted heredoc and passes values via environment variables instead of interpolating them into Python source. | `skills/audio-transcriber/examples/basic-transcription.sh` | +| 25 | obsolete/not reproducible on current HEAD | The claimed recursive symlink traversal in catalog discovery still does not reproduce on current code paths. | `tools/lib/skill-utils.js`, `tools/scripts/build-catalog.js` | +| 26 | obsolete/not reproducible on current HEAD | Root `skills_index.json` remains the canonical generated index, so the reported release-script path mismatch does not reproduce as a defect. | `tools/scripts/generate_index.py`, `tools/scripts/update_readme.py`, `tools/scripts/release_workflow.js` | +| 27 | obsolete/not reproducible on current HEAD | `skill-utils.js` now relies on `lstatSync`-based safe directory/file discovery, so normalization does not treat symlinked skill folders as writable local skills. | `tools/lib/skill-utils.js`, `tools/scripts/normalize-frontmatter.js` | +| 28 | obsolete/not reproducible on current HEAD | The `last30days` skill still passes `"$ARGUMENTS"` as a quoted value into a temp file, so the reported direct shell-injection sink does not reproduce from current text. | `skills/last30days/SKILL.md` | +| 29 | duplicate of another finding | Still the same root cause/fix area as finding `18`. | `tools/scripts/generate_index.py`, `tools/scripts/validate_skills.py` | +| 30 | obsolete/not reproducible on current HEAD | The strategic compact hook now stores state under `XDG_STATE_HOME` instead of predictable shared `/tmp` paths. | `skills/cc-skill-strategic-compact/suggest-compact.sh`, `tools/scripts/tests/local_temp_safety.test.js` | +| 31 | obsolete/not reproducible on current HEAD | `sync_recommended_skills.sh` now preserves symlinks with `cp -RP` and avoids the destructive glob-delete pattern called out in the original report. | `tools/scripts/sync_recommended_skills.sh`, `tools/scripts/tests/repo_hygiene_security.test.js` | +| 32 | obsolete/not reproducible on current HEAD | `skills_manager.py` now resolves candidate paths relative to the intended base directory and rejects traversal attempts. | `tools/scripts/skills_manager.py`, `tools/scripts/tests/test_skills_manager_security.py` | +| 33 | obsolete/not reproducible on current HEAD | The Office unpack helpers now validate archive members and reject traversal/symlink-style entries before extraction. | `skills/docx-official/ooxml/scripts/unpack.py`, `skills/pptx-official/ooxml/scripts/unpack.py`, `tools/scripts/tests/test_office_unpack_security.py` | + +## Maintainer Notes + +- Keep the 2026-03-15 markdown file and CSV as the historical baseline record. +- Keep the 2026-03-29 addendum as the intermediate transition note. +- Use this refresh when answering “what is still open right now?” for the + original 2026-03-15 finding set. +- If new findings are discovered later, start a fresh triage cycle rather than + mutating the historical baseline counts again. diff --git a/walkthrough.md b/walkthrough.md index 901dd6a3..24055f26 100644 --- a/walkthrough.md +++ b/walkthrough.md @@ -1,5 +1,19 @@ # Maintenance Walkthrough - 2026-03-29 +- Re-triaged the full 2026-03-15 security finding set against current `main` and wrote a fresh current-head report in `docs/maintainers/security-findings-triage-2026-03-29-refresh.md`. +- Kept the old `2026-03-15` markdown/CSV as historical baseline input, preserved the smaller `2026-03-29` addendum as a transition note, and pointed both docs at the new refresh as the current source of truth. +- The refreshed triage currently lands at: + - `0` findings still present and exploitable + - `0` findings still present but low practical risk + - `26` obsolete/not reproducible on current HEAD + - `7` duplicates +- The refresh folds in the hardening shipped today and earlier in the session: + - symlink/path safety in maintainer/install/web copy flows + - frontmatter parser robustness + - removal of shared frontend star writes + - secure Office unpack behavior + - migration away from predictable `/tmp` state files + - Fixed the remaining production/documentation drift introduced by the web-app and CI hardening work: - clarified that the hosted GitHub Pages app runs in static public-catalog mode - documented that `Sync Skills` is development-only unless explicitly enabled in local maintainer runs