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.
This commit is contained in:
sickn33
2026-03-29 11:13:05 +02:00
parent d63d99381b
commit 98299deb2d
4 changed files with 102 additions and 1 deletions

View File

@@ -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.

View File

@@ -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`)

View File

@@ -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.

View File

@@ -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