opencode-skills-collection 3.1.6 → 3.1.8

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.
Files changed (59) hide show
  1. package/bundled-skills/.antigravity-install-manifest.json +9 -1
  2. package/bundled-skills/007/scripts/scanners/dependency_scanner.py +2 -2
  3. package/bundled-skills/arrowspace/SKILL.md +116 -0
  4. package/bundled-skills/docs/contributors/quality-bar.md +1 -0
  5. package/bundled-skills/docs/contributors/skill-anatomy.md +19 -3
  6. package/bundled-skills/docs/integrations/jetski-cortex.md +3 -3
  7. package/bundled-skills/docs/integrations/jetski-gemini-loader/README.md +1 -1
  8. package/bundled-skills/docs/maintainers/categorization-implementation.md +14 -24
  9. package/bundled-skills/docs/maintainers/repo-growth-seo.md +3 -3
  10. package/bundled-skills/docs/maintainers/skills-update-guide.md +1 -1
  11. package/bundled-skills/docs/maintainers/smart-auto-categorization.md +24 -25
  12. package/bundled-skills/docs/users/bundles.md +1 -1
  13. package/bundled-skills/docs/users/claude-code-skills.md +1 -1
  14. package/bundled-skills/docs/users/faq.md +5 -5
  15. package/bundled-skills/docs/users/gemini-cli-skills.md +1 -1
  16. package/bundled-skills/docs/users/getting-started.md +1 -1
  17. package/bundled-skills/docs/users/kiro-integration.md +1 -1
  18. package/bundled-skills/docs/users/local-config.md +11 -11
  19. package/bundled-skills/docs/users/specialized-plugin-roadmap.md +3 -3
  20. package/bundled-skills/docs/users/usage.md +4 -4
  21. package/bundled-skills/docs/users/visual-guide.md +4 -4
  22. package/bundled-skills/docs/vietnamese/BUNDLES.vi.md +1 -1
  23. package/bundled-skills/docs/vietnamese/CONTRIBUTING.vi.md +15 -9
  24. package/bundled-skills/docs/vietnamese/FAQ.vi.md +30 -20
  25. package/bundled-skills/docs/vietnamese/GETTING_STARTED.vi.md +22 -14
  26. package/bundled-skills/docs/vietnamese/QUALITY_BAR.vi.md +9 -4
  27. package/bundled-skills/docs/vietnamese/README.vi.md +29 -30
  28. package/bundled-skills/docs/vietnamese/SKILLS_README.vi.md +3 -3
  29. package/bundled-skills/docs/vietnamese/SKILL_ANATOMY.vi.md +33 -5
  30. package/bundled-skills/docs/vietnamese/TRANSLATION_PLAN.vi.md +1 -1
  31. package/bundled-skills/docs/vietnamese/VISUAL_GUIDE.vi.md +17 -18
  32. package/bundled-skills/docx-official/ooxml/scripts/pack.py +12 -0
  33. package/bundled-skills/docx-official/ooxml/scripts/unpack.py +28 -7
  34. package/bundled-skills/docx-official/ooxml/scripts/validation/base.py +18 -13
  35. package/bundled-skills/docx-official/ooxml/scripts/validation/docx.py +6 -6
  36. package/bundled-skills/docx-official/ooxml/scripts/validation/pptx.py +6 -6
  37. package/bundled-skills/emil-design-eng/SKILL.md +702 -0
  38. package/bundled-skills/gh-image/SKILL.md +122 -0
  39. package/bundled-skills/github-actions-debugger/SKILL.md +99 -0
  40. package/bundled-skills/hugging-face-model-trainer/scripts/convert_to_gguf.py +3 -2
  41. package/bundled-skills/infinity/SKILL.md +173 -0
  42. package/bundled-skills/loki-mode/autonomy/run.sh +17 -8
  43. package/bundled-skills/loki-mode/examples/todo-app-generated/backend/package-lock.json +17 -13
  44. package/bundled-skills/loki-mode/examples/todo-app-generated/backend/package.json +3 -3
  45. package/bundled-skills/loki-mode/examples/todo-app-generated/frontend/package-lock.json +9 -9
  46. package/bundled-skills/loki-mode/examples/todo-app-generated/frontend/package.json +2 -2
  47. package/bundled-skills/macos-spm-app-packaging/assets/templates/setup_dev_signing.sh +11 -8
  48. package/bundled-skills/macos-spm-app-packaging/assets/templates/sign-and-notarize.sh +10 -5
  49. package/bundled-skills/pptx-official/ooxml/scripts/pack.py +12 -0
  50. package/bundled-skills/pptx-official/ooxml/scripts/unpack.py +28 -7
  51. package/bundled-skills/pptx-official/ooxml/scripts/validation/base.py +18 -13
  52. package/bundled-skills/pptx-official/ooxml/scripts/validation/docx.py +6 -6
  53. package/bundled-skills/pptx-official/ooxml/scripts/validation/pptx.py +6 -6
  54. package/bundled-skills/premium-3d-website/SKILL.md +133 -0
  55. package/bundled-skills/review-animations/SKILL.md +139 -0
  56. package/bundled-skills/review-animations/STANDARDS.md +188 -0
  57. package/bundled-skills/skill-creator/scripts/package_skill.py +11 -1
  58. package/package.json +1 -1
  59. package/skills_index.json +132 -0
@@ -0,0 +1,122 @@
1
+ ---
2
+ name: gh-image
3
+ description: "Upload local images to GitHub and get canonical user-attachments embed URLs; use when asked to attach a screenshot to a PR, issue, or comment, or to embed before/after images in a README."
4
+ category: developer-tools
5
+ risk: safe
6
+ source: community
7
+ source_type: community
8
+ source_repo: drogers0/gh-image
9
+ date_added: "2026-06-25"
10
+ author: drogers0
11
+ license: MIT
12
+ license_source: "https://github.com/drogers0/gh-image/blob/main/LICENSE"
13
+ tags:
14
+ - github
15
+ - images
16
+ - screenshots
17
+ - gh-extension
18
+ - cli
19
+ tools:
20
+ - claude-code
21
+ - codex-cli
22
+ - cursor
23
+ - gemini-cli
24
+ ---
25
+
26
+ # Upload images to GitHub (gh-image)
27
+
28
+ GitHub has **no public API** for image uploads — the web UI uses an internal
29
+ endpoint that mints `user-attachments` URLs scoped to the repo's visibility.
30
+ [`gh-image`](https://github.com/drogers0/gh-image) (MIT, © drogers0) replicates
31
+ that flow as a `gh` CLI extension, so an agent can upload a local image from the
32
+ terminal and get a ready-to-embed Markdown image line back.
33
+
34
+ ## Overview
35
+
36
+ This skill drives `gh-image` to turn a local image file into a hosted GitHub
37
+ `user-attachments` URL, then embeds that URL into a pull request, issue, or
38
+ comment. It is the missing "attach a screenshot" capability for terminal agents.
39
+
40
+ ## When to Use This Skill
41
+
42
+ Use this skill when asked to:
43
+
44
+ - "Attach a screenshot to the PR" or "add an image to the PR description"
45
+ - "Put this image in the issue" / "comment with these screenshots"
46
+ - "Show the test results / before-and-after in the PR"
47
+ - Embed any local image into GitHub Markdown without leaving the terminal
48
+
49
+ ## How It Works
50
+
51
+ ### Step 1: Verify prerequisites
52
+
53
+ ```bash
54
+ gh auth status # gh installed & authenticated
55
+ gh extension list | grep -q 'drogers0/gh-image' \
56
+ || gh extension install drogers0/gh-image # idempotent install
57
+ ```
58
+
59
+ `gh-image` does **not** use the `gh` token for the upload (that endpoint rejects
60
+ tokens). It needs a GitHub `user_session` cookie, resolved in this order:
61
+ `--token <value>` flag → `GH_SESSION_TOKEN` env var (use in CI/headless) → a
62
+ logged-in browser's cookie store (default for local use).
63
+
64
+ ### Step 2: Upload
65
+
66
+ ```bash
67
+ # Use an absolute path; --repo is optional inside a repo working dir.
68
+ gh image "/abs/path/screenshot.png" --repo <owner>/<repo>
69
+ ```
70
+
71
+ `gh image` prints Markdown to **stdout**, one line per image:
72
+
73
+ ```
74
+ ![screenshot.png](https://github.com/user-attachments/assets/<uuid>)
75
+ ```
76
+
77
+ Capture that output — it is the embeddable reference.
78
+
79
+ ### Step 3: Embed into the PR / issue / comment
80
+
81
+ ```bash
82
+ MD="$(gh image "/abs/path/shot.png" --repo owner/repo)"
83
+ BODY="$(gh pr view <pr> --repo owner/repo --json body -q .body)"
84
+ printf '%s\n\n## Screenshots\n\n%s\n' "$BODY" "$MD" \
85
+ | gh pr edit <pr> --repo owner/repo --body-file -
86
+ ```
87
+
88
+ Use `gh pr comment`, `gh issue edit`, or `gh issue comment` with `--body-file -`
89
+ for other targets. Always pass `--body-file -` (not inline `--body`) so multi-line
90
+ bodies and special characters can't break shell quoting.
91
+
92
+ ### Step 4: Verify
93
+
94
+ ```bash
95
+ gh pr view <pr> --repo owner/repo --json body -q .body # confirm URL present
96
+ ```
97
+
98
+ ## Examples
99
+
100
+ - **Attach a CleanShot screenshot to PR #42:** upload the file, append it under a
101
+ `## Screenshots` heading in the PR body.
102
+ - **Embed before/after images in a README:** upload both, paste the two Markdown
103
+ lines into the README at the relevant section.
104
+
105
+ ## Best Practices
106
+
107
+ - Resolve globs to absolute paths first; quote paths with spaces/Unicode.
108
+ - For display sizing, embed an HTML tag instead of bare Markdown:
109
+ `<img width="800" src="https://github.com/user-attachments/assets/<uuid>" />`.
110
+ - In CI, set `GH_SESSION_TOKEN` from a dedicated bot account.
111
+
112
+ ## Limitations
113
+
114
+ - **Session cookie required.** A `user_session` cookie grants full account access
115
+ (not scoped like a PAT) — treat it like a password; use a bot account in CI.
116
+ - **Write access to the target repo is required**; orgs that enforce SAML SSO need
117
+ the session authorized at `https://github.com/orgs/<org>/sso` first.
118
+ - **Private-repo images stay private:** the `user-attachments` URL inherits repo
119
+ visibility, so an anonymous fetch on a private repo returns 404/403 by design.
120
+ - **Windows + Chrome 127+** cannot read cookies (library limitation) — use another
121
+ browser or `GH_SESSION_TOKEN`.
122
+ - The skill embeds the Markdown itself; `gh-image` only prints the URL.
@@ -0,0 +1,99 @@
1
+ ---
2
+ name: github-actions-debugger
3
+ description: "Specialized skill for diagnosing, analyzing, and fixing failing GitHub Actions workflows by parsing run logs and pipeline definitions."
4
+ category: devops
5
+ risk: safe
6
+ source: community
7
+ source_type: community
8
+ date_added: "2026-06-25"
9
+ author: Owais
10
+ tags: [github-actions, ci-cd, devops, debugging, workflows]
11
+ tools: [claude, cursor, gemini, antigravity]
12
+ ---
13
+
14
+ # GitHub Actions Pipeline Debugger
15
+
16
+ ## Overview
17
+
18
+ This skill is designed to act as an expert CI/CD diagnostician. It focuses specifically on reading raw logs from failed GitHub Actions, identifying the root cause of the crash or failure, and outputting the precise YAML or code changes required to fix the pipeline.
19
+
20
+ ## When to Use
21
+
22
+ - Use when a GitHub Actions workflow fails unexpectedly and the error log is long, obscure, or misleading.
23
+ - Use when debugging dependency mismatch errors, missing secrets, caching issues, or runner environment problems in CI.
24
+ - Use to optimize slow pipelines by identifying bottlenecks in workflow steps.
25
+ - Use to update and modernize deprecated actions or workflow syntax.
26
+
27
+ ## How It Works
28
+
29
+ 1. **Log Ingestion & Redaction:** Analyze the provided GitHub Actions workflow log (often exported as a raw text file or pasted directly). **CRITICAL SAFETY REQUIREMENT:** The user/agent must redact all sensitive credentials, secrets, tokens, private keys, and internal system paths from the logs before pasting or uploading them.
30
+ 2. **Context Mapping:** Cross-reference the failure point with the specific step and job in the `.github/workflows/*.yml` definition.
31
+ 3. **Root Cause Analysis:** Identify if the failure is due to:
32
+ - Missing or misconfigured secrets (`${{ secrets.API_KEY }}`).
33
+ - Node/Python/OS environment version mismatches.
34
+ - Flaky tests or timeout limits.
35
+ - Syntax errors in bash scripts run within the `run:` block.
36
+ - Invalid action versions or deprecated actions.
37
+ 4. **Resolution Proposal:** Provide a direct `diff` of the `.yml` file or the underlying script that needs to be modified.
38
+
39
+ ## Best Practices
40
+
41
+ - **Provide Full Context:** Always review both the workflow definition (`.yml` file) and the failure log simultaneously to ensure accurate diagnosis.
42
+ - **Check Action Versions:** Many failures are caused by deprecated runtime versions (e.g., Node.js 16) in older third-party actions (e.g., `actions/checkout@v2`). Always recommend upgrading to the latest major versions (e.g., `v4`).
43
+ - **Permissions Audit:** Ensure the workflow has the correct `permissions:` block if it's attempting to write to the repository, packages, or deploy environments.
44
+ - **Reproducibility:** If a test fails in CI but passes locally, investigate environment differences such as timezone, headless browser state, memory limits, or parallel execution race conditions.
45
+
46
+ ## Examples
47
+
48
+ ### Example 1: Fixing a Deprecated Node.js Action Version Error
49
+ **Failing Log:**
50
+ ```text
51
+ Warning: The Go/Node.js/Python version used by this action is deprecated.
52
+ Error: Node.js 16 actions are deprecated. Please update to use Node.js 20.
53
+ ```
54
+
55
+ **Proposed Fix Diff:**
56
+ ```diff
57
+ - name: Checkout Code
58
+ - uses: actions/checkout@v2
59
+ + uses: actions/checkout@v4
60
+ ```
61
+
62
+ ### Example 2: Diagnosing and Fixing a Missing Repository Secret
63
+ **Failing Log:**
64
+ ```text
65
+ Run npm run deploy
66
+ npm run deploy
67
+ shell: /usr/bin/bash -e {0}
68
+ Error: API Key is required for deployment. Process exited with code 1.
69
+ ```
70
+
71
+ **Proposed Fix Diff:**
72
+ ```diff
73
+ - name: Deploy App
74
+ run: npm run deploy
75
+ + env:
76
+ + DEPLOY_API_KEY: ${{ secrets.DEPLOY_API_KEY }}
77
+ ```
78
+
79
+ ## Security & Safety Notes
80
+
81
+ - **Credential Exposure & Raw Log Redaction**: Under no circumstances should raw logs containing unmasked secrets, private URLs, deployment targets, or tokens be processed without prior redaction. Always ensure the user or agent redacts all sensitive info before ingestion.
82
+ - **Dry-Run Mode**: When recommending modifications to bash script steps inside workflows, ensure you suggest adding flags like `--dry-run` or staging execution where possible to prevent unintended side effects in downstream environments during debugging.
83
+
84
+ ## Limitations
85
+
86
+ - The skill cannot securely read repository secrets. It can only infer missing or malformed secrets if the log complains about undefined environment variables or authentication failures.
87
+ - It cannot execute the GitHub action itself to test the fix; validation requires pushing the proposed fix to the repository and triggering a workflow run.
88
+ - Network-related transient failures (e.g., a package registry being down temporarily) might be incorrectly diagnosed as structural workflow issues if not carefully analyzed.
89
+
90
+ ## Common Pitfalls
91
+
92
+ - **Ignoring Transient Failures**: Mistaking temporary network dropouts or registry downtime (e.g., npm or pip install errors) for actual code or configuration bugs. Always check if a rerun succeeds before attempting heavy changes.
93
+ - **Hardcoding Tokens**: Fixing authentication errors by hardcoding secrets or API tokens directly into the YAML files instead of utilizing GitHub Secrets (`${{ secrets.SECRET_NAME }}`).
94
+ - **Overlooking Caching Side Effects**: Forgetting that outdated cache keys can keep corrupt dependencies loaded. If dependency installation is failing, try running a job with actions caching bypassed.
95
+
96
+ ## Related Skills
97
+
98
+ - `@devops-troubleshooter` - General DevOps and infrastructure issue resolution.
99
+ - `@cicd-automation-workflow-automate` - For creating new CI/CD pipelines from scratch.
@@ -132,6 +132,7 @@ ADAPTER_MODEL = require_hf_id(os.environ.get("ADAPTER_MODEL", "evalstate/qwen-ca
132
132
  BASE_MODEL = require_hf_id(os.environ.get("BASE_MODEL", "Qwen/Qwen2.5-0.5B"), "BASE_MODEL")
133
133
  OUTPUT_REPO = require_hf_id(os.environ.get("OUTPUT_REPO", "evalstate/qwen-capybara-medium-gguf"), "OUTPUT_REPO")
134
134
  username = require_hf_id(os.environ.get("HF_USERNAME", ADAPTER_MODEL.split('/')[0]), "HF_USERNAME")
135
+ TRUST_REMOTE_CODE = os.environ.get("TRUST_REMOTE_CODE", "").strip().lower() in {"1", "true", "yes"}
135
136
 
136
137
  print(f"\n📦 Configuration:")
137
138
  print(f" Base model: {BASE_MODEL}")
@@ -147,7 +148,7 @@ try:
147
148
  BASE_MODEL,
148
149
  dtype=torch.float16,
149
150
  device_map="auto",
150
- trust_remote_code=True,
151
+ trust_remote_code=TRUST_REMOTE_CODE,
151
152
  )
152
153
  print(" ✅ Base model loaded")
153
154
  except Exception as e:
@@ -169,7 +170,7 @@ except Exception as e:
169
170
 
170
171
  try:
171
172
  # Load tokenizer
172
- tokenizer = AutoTokenizer.from_pretrained(ADAPTER_MODEL, trust_remote_code=True)
173
+ tokenizer = AutoTokenizer.from_pretrained(ADAPTER_MODEL, trust_remote_code=TRUST_REMOTE_CODE)
173
174
  print(" ✅ Tokenizer loaded")
174
175
  except Exception as e:
175
176
  print(f" ❌ Failed to load tokenizer: {e}")
@@ -0,0 +1,173 @@
1
+ ---
2
+ name: infinity
3
+ description: "Enforces a strict input boundary protocol (detect, classify, filter, verify) to ensure untrusted data never reaches business logic raw."
4
+ risk: safe
5
+ source: community
6
+ date_added: "2026-06-23"
7
+ ---
8
+
9
+ # infinity — Input Boundary & Validation Protocol
10
+
11
+ ## Core Philosophy
12
+
13
+ > Nothing untrusted ever reaches the core — it is stopped before contact. No external data touches the codebase raw. Every boundary where data enters the system must have a filter.
14
+
15
+ The #1 source of silent bugs, crashes, and vulnerabilities is external data that arrives in an unexpected shape and gets used directly without checking. This skill enforces a filter layer at every entry point, every time.
16
+
17
+ ---
18
+
19
+ ## When to Use This Skill
20
+
21
+ - Use when you need to handle an API response
22
+ - Use when reading user input or adding a form handler
23
+ - Use when working with environment variables or CLI arguments
24
+ - Use when parsing webhooks or reading from the filesystem
25
+ - Use when any code calls `.body`, `.params`, `.query`, `.env`, `fs.read`, or a third-party SDK response
26
+
27
+ ---
28
+
29
+ ## The Four Phases
30
+
31
+ ### PHASE 1 — Boundary Detection
32
+
33
+ Before writing or modifying any code that involves external data, the AI must identify and list every entry point in scope:
34
+
35
+ - HTTP request bodies, headers, query params
36
+ - User form inputs and UI-submitted data
37
+ - Environment variables and config files
38
+ - Third-party API responses
39
+ - Webhook payloads
40
+ - File reads from disk
41
+ - CLI arguments
42
+ - Database query results from external sources
43
+ - WebSocket messages
44
+
45
+ > **The AI must not write any data-handling logic until every entry point in scope is listed.**
46
+
47
+ ---
48
+
49
+ ### PHASE 2 — Classify Each Input
50
+
51
+ For every entry point identified, the AI classifies it into one of three trust levels:
52
+
53
+ | Level | Definition | Examples |
54
+ |---|---|---|
55
+ | `TRUSTED` | Internal constants, hardcoded values, your own compile-time config | Enum values, hardcoded defaults, internal constants |
56
+ | `SEMI-TRUSTED` | Your own internal services, internal APIs, controlled infrastructure | Internal microservice responses, your own database reads |
57
+ | `UNTRUSTED` | Anything from users, the internet, third parties, or the filesystem | User input, external API responses, uploaded files, env vars, CLI args |
58
+
59
+ > **Rule:** `TRUSTED` inputs may be used directly. `SEMI-TRUSTED` and `UNTRUSTED` inputs must pass through a filter layer before any use.
60
+
61
+ The AI outputs this classification before writing any handling code:
62
+
63
+ ```
64
+ INFINITY — BOUNDARY MAP
65
+ ─────────────────────────────────────────
66
+ Entry Point | Trust Level | Filter Required
67
+ ─────────────────────────────────────────
68
+ req.body.email | UNTRUSTED | ✓ format + sanitize
69
+ process.env.API_KEY | UNTRUSTED | ✓ presence + non-empty
70
+ internalService.getData()| SEMI-TRUSTED | ✓ schema validate
71
+ PAGINATION_LIMIT = 20 | TRUSTED | ✗ none needed
72
+ ─────────────────────────────────────────
73
+ ```
74
+
75
+ ---
76
+
77
+ ### PHASE 3 — Mandatory Filter Layer
78
+
79
+ Every `UNTRUSTED` and `SEMI-TRUSTED` input must pass through validation before it reaches any business logic, storage, or rendering. The AI must apply the right filter type for the right context:
80
+
81
+ **Type Checking**
82
+ - Verify the input is the expected type before using it
83
+ - Never assume a string is a string, a number is a number, or an array is an array
84
+
85
+ **Schema Validation**
86
+ - For objects and API responses, validate shape before accessing nested fields
87
+ - If a required field is missing, reject — do not use a fallback that hides the problem
88
+
89
+ **Sanitization**
90
+ - Strip or escape content before rendering to UI (prevent XSS)
91
+ - Normalize strings before storage (trim whitespace, consistent casing where appropriate)
92
+
93
+ **Presence & Format Checks**
94
+ - Env vars: must exist and be non-empty before use
95
+ - IDs and tokens: must match expected format before use
96
+
97
+ **Rejection Rule**
98
+ - On invalid input: reject explicitly and return a clear error
99
+ - Never silently use bad data with a fallback
100
+ - Never let bad data pass through to fix itself "downstream"
101
+
102
+ ```
103
+ // WRONG — using raw input directly
104
+ const user = await db.find(req.params.id);
105
+
106
+ // RIGHT — validate before use
107
+ const id = req.params.id;
108
+ if (!id || typeof id !== 'string' || !isValidUUID(id)) {
109
+ return res.status(400).json({ error: 'Invalid ID format' });
110
+ }
111
+ const user = await db.find(id);
112
+ ```
113
+
114
+ ---
115
+
116
+ ### PHASE 4 — Self-Check Before Done
117
+
118
+ Before the AI declares any data-handling code complete, it traces each entry point and confirms:
119
+
120
+ ```
121
+ INFINITY — VERIFICATION
122
+ ─────────────────────────────────────────
123
+ Entry Point | Filter Exists | Filter Type
124
+ ─────────────────────────────────────────
125
+ req.body.email | ✓ YES | format + sanitize
126
+ process.env.API_KEY | ✓ YES | presence check
127
+ internalService.getData()| ✓ YES | schema validation
128
+ ─────────────────────────────────────────
129
+ Unfiltered inputs reaching logic: NONE ✓
130
+ ─────────────────────────────────────────
131
+ ```
132
+
133
+ If any `UNTRUSTED` or `SEMI-TRUSTED` input reaches logic, storage, or rendering without a filter — the AI flags it. It does not silently pass.
134
+
135
+ ---
136
+
137
+ ## Hard Rules (Never Violated)
138
+
139
+ - **No raw external data in business logic.** Ever.
140
+ - **No silent fallbacks on bad input.** Reject explicitly.
141
+ - **No assuming shape.** Even if the API "always" returns a string — validate it.
142
+ - **No skipping env var checks.** Missing env vars must fail loudly at startup, not silently at runtime.
143
+ - **No partial filtering.** If you validate presence but not format, it is not filtered.
144
+ - **No filtering in the wrong place.** Filters go at the entry point — not somewhere downstream after the data has already been used once.
145
+
146
+ ---
147
+
148
+ ## What This Skill Prevents
149
+
150
+ - SQL injection via unvalidated query params
151
+ - Crashes from unexpected API response shapes
152
+ - XSS from unescaped user content rendered to UI
153
+ - Silent failures from missing env variables discovered at runtime
154
+ - Type errors from assuming external data matches expected shape
155
+ - Security vulnerabilities from untrusted data reaching sensitive operations
156
+
157
+ ---
158
+
159
+ ## Quick Reference
160
+
161
+ | Phase | Action | Writes Code? |
162
+ |---|---|---|
163
+ | 1 — Detect | List all entry points in scope | ❌ No |
164
+ | 2 — Classify | Assign trust level to each input | ❌ No |
165
+ | 3 — Filter | Write filter layer for all UNTRUSTED + SEMI-TRUSTED | ✅ Yes |
166
+ | 4 — Verify | Trace each input, confirm filter exists | ❌ No |
167
+
168
+ ---
169
+
170
+ ## Limitations
171
+
172
+ - Does not apply to purely internal logic with no external data involvement.
173
+ - May add verbosity to trivial scripts where strict validation is not required.
@@ -711,21 +711,30 @@ generate_dashboard() {
711
711
  if (seconds < 3600) return Math.floor(seconds / 60) + 'm';
712
712
  return Math.floor(seconds / 3600) + 'h ' + Math.floor((seconds % 3600) / 60) + 'm';
713
713
  }
714
+ function escapeHtml(value) {
715
+ return String(value ?? '').replace(/[&<>"']/g, (char) => ({
716
+ '&': '&amp;',
717
+ '<': '&lt;',
718
+ '>': '&gt;',
719
+ '"': '&quot;',
720
+ "'": '&#39;'
721
+ })[char]);
722
+ }
714
723
  function renderAgent(agent) {
715
724
  const modelClass = getModelClass(agent.model);
716
- const modelName = agent.model || 'Sonnet 4.5';
717
- const agentType = agent.agent_type || 'general-purpose';
725
+ const modelName = escapeHtml(agent.model || 'Sonnet 4.5');
726
+ const agentType = escapeHtml(agent.agent_type || 'general-purpose');
718
727
  const status = agent.status === 'completed' ? 'completed' : 'active';
719
- const currentTask = agent.current_task || (agent.tasks_completed && agent.tasks_completed.length > 0
728
+ const currentTask = escapeHtml(agent.current_task || (agent.tasks_completed && agent.tasks_completed.length > 0
720
729
  ? 'Completed: ' + agent.tasks_completed.join(', ')
721
- : 'Initializing...');
730
+ : 'Initializing...'));
722
731
  const duration = formatDuration(agent.spawned_at);
723
732
  const tasksCount = agent.tasks_completed ? agent.tasks_completed.length : 0;
724
733
 
725
734
  return `
726
735
  <div class="agent-card">
727
736
  <div class="agent-header">
728
- <div class="agent-id">${agent.agent_id || 'Unknown'}</div>
737
+ <div class="agent-id">${escapeHtml(agent.agent_id || 'Unknown')}</div>
729
738
  <div class="model-badge ${modelClass}">${modelName}</div>
730
739
  </div>
731
740
  <div class="agent-type">${agentType}</div>
@@ -740,9 +749,9 @@ generate_dashboard() {
740
749
  }
741
750
  function renderTask(task) {
742
751
  const payload = task.payload || {};
743
- const title = payload.description || payload.action || task.type || 'Task';
744
- const error = task.lastError ? `<div class="error">${task.lastError}</div>` : '';
745
- return `<div class="task"><div class="id">${task.id}</div><span class="type">${task.type || 'general'}</span><div class="title">${title}</div>${error}</div>`;
752
+ const title = escapeHtml(payload.description || payload.action || task.type || 'Task');
753
+ const error = task.lastError ? `<div class="error">${escapeHtml(task.lastError)}</div>` : '';
754
+ return `<div class="task"><div class="id">${escapeHtml(task.id)}</div><span class="type">${escapeHtml(task.type || 'general')}</span><div class="title">${title}</div>${error}</div>`;
746
755
  }
747
756
  async function loadData() {
748
757
  const [pending, progress, completed, failed, agents] = await Promise.all([
@@ -8,10 +8,10 @@
8
8
  "name": "todo-app-backend",
9
9
  "version": "1.0.0",
10
10
  "dependencies": {
11
- "better-sqlite3": "^12.8.0",
12
- "cors": "^2.8.5",
11
+ "better-sqlite3": "^12.10.0",
12
+ "cors": "^2.8.6",
13
13
  "express": "^4.18.2",
14
- "express-rate-limit": "^8.5.1",
14
+ "express-rate-limit": "^8.5.2",
15
15
  "ip-address": "^10.2.0"
16
16
  },
17
17
  "devDependencies": {
@@ -303,9 +303,9 @@
303
303
  "license": "MIT"
304
304
  },
305
305
  "node_modules/better-sqlite3": {
306
- "version": "12.8.0",
307
- "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.8.0.tgz",
308
- "integrity": "sha512-RxD2Vd96sQDjQr20kdP+F+dK/1OUNiVOl200vKBZY8u0vTwysfolF6Hq+3ZK2+h8My9YvZhHsF+RSGZW2VYrPQ==",
306
+ "version": "12.10.0",
307
+ "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.10.0.tgz",
308
+ "integrity": "sha512-CyzaZRQKyHkB2ZInfTTl2nvT33EbDpjkLEbE8/Zck3Ll6O0qqvuGdrJ45HgtH+HykRg88ITY3AdreBGN70aBSQ==",
309
309
  "hasInstallScript": true,
310
310
  "license": "MIT",
311
311
  "dependencies": {
@@ -313,7 +313,7 @@
313
313
  "prebuild-install": "^7.1.1"
314
314
  },
315
315
  "engines": {
316
- "node": "20.x || 22.x || 23.x || 24.x || 25.x"
316
+ "node": "20.x || 22.x || 23.x || 24.x || 25.x || 26.x"
317
317
  }
318
318
  },
319
319
  "node_modules/bindings": {
@@ -459,9 +459,9 @@
459
459
  "license": "MIT"
460
460
  },
461
461
  "node_modules/cors": {
462
- "version": "2.8.5",
463
- "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
464
- "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
462
+ "version": "2.8.6",
463
+ "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz",
464
+ "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==",
465
465
  "license": "MIT",
466
466
  "dependencies": {
467
467
  "object-assign": "^4",
@@ -469,6 +469,10 @@
469
469
  },
470
470
  "engines": {
471
471
  "node": ">= 0.10"
472
+ },
473
+ "funding": {
474
+ "type": "opencollective",
475
+ "url": "https://opencollective.com/express"
472
476
  }
473
477
  },
474
478
  "node_modules/create-require": {
@@ -688,9 +692,9 @@
688
692
  }
689
693
  },
690
694
  "node_modules/express-rate-limit": {
691
- "version": "8.5.1",
692
- "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.5.1.tgz",
693
- "integrity": "sha512-5O6KYmyJEpuPJV5hNTXKbAHWRqrzyu+OI3vUnSd2kXFubIVpG7ezpgxQy76Zo5GQZtrQBg86hF+CM/NX+cioiQ==",
695
+ "version": "8.5.2",
696
+ "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.5.2.tgz",
697
+ "integrity": "sha512-5Kb34ipNX694DH48vN9irak1Qx30nb0PLYHXfJgw4YEjiC3ZEmZJhwOp+VfiCYwFzvFTdB9QkArYS5kXa2cx2A==",
694
698
  "license": "MIT",
695
699
  "dependencies": {
696
700
  "ip-address": "^10.2.0"
@@ -9,10 +9,10 @@
9
9
  "dev": "ts-node src/index.ts"
10
10
  },
11
11
  "dependencies": {
12
- "better-sqlite3": "^12.8.0",
13
- "cors": "^2.8.5",
12
+ "better-sqlite3": "^12.10.0",
13
+ "cors": "^2.8.6",
14
14
  "express": "^4.18.2",
15
- "express-rate-limit": "^8.5.1",
15
+ "express-rate-limit": "^8.5.2",
16
16
  "ip-address": "^10.2.0"
17
17
  },
18
18
  "devDependencies": {
@@ -9,8 +9,8 @@
9
9
  "version": "1.0.0",
10
10
  "license": "ISC",
11
11
  "dependencies": {
12
- "react": "^19.2.3",
13
- "react-dom": "^19.2.3"
12
+ "react": "^19.2.7",
13
+ "react-dom": "^19.2.7"
14
14
  },
15
15
  "devDependencies": {
16
16
  "@types/react": "^19.2.7",
@@ -814,24 +814,24 @@
814
814
  }
815
815
  },
816
816
  "node_modules/react": {
817
- "version": "19.2.3",
818
- "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz",
819
- "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==",
817
+ "version": "19.2.7",
818
+ "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz",
819
+ "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==",
820
820
  "license": "MIT",
821
821
  "engines": {
822
822
  "node": ">=0.10.0"
823
823
  }
824
824
  },
825
825
  "node_modules/react-dom": {
826
- "version": "19.2.3",
827
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz",
828
- "integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==",
826
+ "version": "19.2.7",
827
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.7.tgz",
828
+ "integrity": "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==",
829
829
  "license": "MIT",
830
830
  "dependencies": {
831
831
  "scheduler": "^0.27.0"
832
832
  },
833
833
  "peerDependencies": {
834
- "react": "^19.2.3"
834
+ "react": "^19.2.7"
835
835
  }
836
836
  },
837
837
  "node_modules/rolldown": {
@@ -19,8 +19,8 @@
19
19
  "vite": "^8.0.16"
20
20
  },
21
21
  "dependencies": {
22
- "react": "^19.2.3",
23
- "react-dom": "^19.2.3"
22
+ "react": "^19.2.7",
23
+ "react-dom": "^19.2.7"
24
24
  },
25
25
  "overrides": {
26
26
  "picomatch": "4.0.4",
@@ -14,8 +14,13 @@ fi
14
14
 
15
15
  echo "Creating self-signed certificate '$CERT_NAME'..."
16
16
 
17
- TEMP_CONFIG=$(mktemp)
18
- trap "rm -f $TEMP_CONFIG" EXIT
17
+ TEMP_DIR=$(mktemp -d)
18
+ chmod 700 "$TEMP_DIR"
19
+ TEMP_CONFIG="$TEMP_DIR/dev.cnf"
20
+ KEY_PATH="$TEMP_DIR/dev.key"
21
+ CRT_PATH="$TEMP_DIR/dev.crt"
22
+ P12_PATH="$TEMP_DIR/dev.p12"
23
+ trap 'rm -rf "$TEMP_DIR"' EXIT
19
24
 
20
25
  cat > "$TEMP_CONFIG" <<EOFCONF
21
26
  [ req ]
@@ -34,18 +39,16 @@ extendedKeyUsage = codeSigning
34
39
  EOFCONF
35
40
 
36
41
  openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 \
37
- -nodes -keyout /tmp/dev.key -out /tmp/dev.crt \
42
+ -nodes -keyout "$KEY_PATH" -out "$CRT_PATH" \
38
43
  -config "$TEMP_CONFIG" 2>/dev/null
39
44
 
40
- openssl pkcs12 -export -out /tmp/dev.p12 \
41
- -inkey /tmp/dev.key -in /tmp/dev.crt \
45
+ openssl pkcs12 -export -out "$P12_PATH" \
46
+ -inkey "$KEY_PATH" -in "$CRT_PATH" \
42
47
  -passout pass: 2>/dev/null
43
48
 
44
- security import /tmp/dev.p12 -k ~/Library/Keychains/login.keychain-db \
49
+ security import "$P12_PATH" -k ~/Library/Keychains/login.keychain-db \
45
50
  -T /usr/bin/codesign -T /usr/bin/security
46
51
 
47
- rm -f /tmp/dev.{key,crt,p12}
48
-
49
52
  echo ""
50
53
  echo "Trust this certificate for code signing in Keychain Access."
51
54
  echo "Then export in your shell profile:"