Security Triage
symfony/symfony
Triage a reported security finding into a disposition: a private CVE (coordinated disclosure + advisory), a public hardening PR (fix in the open, no CVE), or not-a-security-issue (reply to reporter).
Triage a security finding in a Symfony UX package into a disposition: a private CVE (coordinated disclosure through the Symfony security process), a public hardening PR (fix in the open, no CVE), or…
$ npx skills add symfony/ux --skill security-triage -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install symfony/ux security-triage --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/symfony/ux.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/security-triage .claude/skills/security-triage && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "security-triage" agent skill from https://github.com/symfony/ux/tree/3.x/.agents/skills/security-triage into .claude/skills/security-triage/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "security-triage", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/symfony/ux/tree/3.x/.agents/skills/security-triageType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add symfony/ux --skill security-triage -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install symfony/ux security-triage --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/symfony/ux.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/security-triage .agents/skills/security-triage && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "security-triage" agent skill from https://github.com/symfony/ux/tree/3.x/.agents/skills/security-triage into .agents/skills/security-triage/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "security-triage", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add symfony/ux --skill security-triage -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install symfony/ux security-triage --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/symfony/ux.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/security-triage .cursor/skills/security-triage && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "security-triage" agent skill from https://github.com/symfony/ux/tree/3.x/.agents/skills/security-triage into .cursor/skills/security-triage/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "security-triage", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/symfony/ux.git --path .agents/skills/security-triage--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add symfony/ux --skill security-triage -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install symfony/ux security-triage --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/symfony/ux.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/security-triage .gemini/skills/security-triage && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "security-triage" agent skill from https://github.com/symfony/ux/tree/3.x/.agents/skills/security-triage into .gemini/skills/security-triage/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "security-triage", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install symfony/ux security-triageInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add symfony/ux --skill security-triage -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/symfony/ux.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/security-triage .github/skills/security-triage && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "security-triage" agent skill from https://github.com/symfony/ux/tree/3.x/.agents/skills/security-triage into .github/skills/security-triage/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "security-triage", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add symfony/ux --skill security-triage -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install symfony/ux security-triage --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/symfony/ux.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/security-triage .opencode/skills/security-triage && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "security-triage" agent skill from https://github.com/symfony/ux/tree/3.x/.agents/skills/security-triage into .opencode/skills/security-triage/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "security-triage", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
security-triageTriage a security finding in a Symfony UX package into a disposition: a private CVE (coordinated disclosure through the Symfony security process), a public hardening PR (fix in the open, no CVE), or…
Security Triage is an agent skill from symfony/ux. Triage a security finding in a Symfony UX package into a disposition: a private CVE (coordinated disclosure through the Symfony security process), a public hardening PR (fix in the open, no CVE), or not-a-security-issue (reply to the reporter). Assigns severity and the affected maintained branches, and routes to the next step. Use when deciding whether a report or a discovered weakness needs a CVE, how it should be disclosed, or whether it is a security issue at all.
Its SKILL.md is about 3.2k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Security, covering Vulnerability scanning. It works with Symfony. The repository describes itself as: Symfony UX initiative: a JavaScript ecosystem for Symfony. The licence is MIT.
4 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 5e9614c. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
pnpmgitcomposerphpFrom the folder's file list and the shell code blocks in SKILL.md.
Links to these hosts (documentation or services it may open):
symfony.comFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Security Triage loads about 3.2k tokens when it runs. Until then it costs about 122 tokens; SKILL.md has 1,746 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from symfony/ux at commit 5e9614c, republished under its MIT licence (© symfony). 1,746 words, ~3,239 tokens.
.claude/skills/security-triage/SKILL.md (or your agent's skills folder).Decides how a finding is handled, not whether the code is wrong. It complements symfony-security-review (which finds missing hardening) by making the disclosure call on a report.
Symfony UX follows the Symfony security process (https://symfony.com/security): reports go privately to security@symfony.com, the security team works on the fix in a private Git repository, and the release publishes a GitHub Security Advisory (GHSA) with a CVE and a severity. The fix lands as a merge titled security #cve-<year>-<number> [<Package>] <title>, for example security #cve-2026-55878 [Toolkit] Harden recipe installer against path traversal. A security fix is always published as one, never disguised as a refactor or a routine bug fix: users decide whether to upgrade from that signal.
The three dispositions:
| Disposition | Branch | Process |
|---|---|---|
| CVE | cve-<year>-<number> | Private fix, GHSA + CVE with severity, reporter credit, coordinated release, merge titled security #cve-... |
| Public hardening | normal topic branch | Normal open PR, merged as bug #<number>, no embargo |
| Not a security issue | none, or a normal topic branch | Reply to the reporter; optionally a doc or robustness PR |
The symfony/ux repository has no security or severity labels: the severity lives in the GHSA.
This skill produces a recommendation. The final call belongs to the Symfony security team; treat its output as a structured argument, and defer to https://symfony.com/security for the authoritative list of what is not a vulnerability.
Whenever this skill says "Wait for confirmation", treat anything other than an explicit affirmative as no: stop and ask the user how they want to proceed.
Before classifying, pin down four things. Guessing any of them produces a wrong call.
writable: true LiveProp accepts values from the client by design, options_as_html: true renders Autocomplete results as raw HTML on purpose, and an autocompleter left with the default security: false is public (see src/Autocomplete/doc/index.rst).Reproduce if at all possible; an unreproducible report is not yet triable.
Apply in order. The first matching bucket wins.
Pure DoS / resource exhaustion is listed by the Symfony policy among the issues not considered security issues. ux has nevertheless published CVE-2026-49209 (low) for the unbounded _batch action fan-out in LiveComponent. For a DoS on a ux endpoint, recommend hardening, cite that precedent, and leave the call to the security team.
2.x or 3.x.A genuine improvement where a CVE condition fails. Shapes from ux history:
LiveComponentSubscriber's test mode defaulted to true in the constructor, but the bundle's compiler pass already overrode it for non-test kernels; flipping the default was a bug PR (#3566).extra_options checksum moved from !== to hash_equals() as a bug PR (#3565).ux has also published CVEs for fixes that close a boundary a default install already guards: CVE-2026-49210 (child component tag, rejected even though the request is gated by the live endpoint checks) and CVE-2026-49212 (checksum bound to component name and slot). When a finding has that defense-in-depth shape, present both kinds of precedent instead of deciding.
Severity (the GHSA severity; CVSS is a sanity check, not the goal). ux precedent:
_batch DoS, CVE-2026-49211 LIKE wildcards in Autocomplete, CVE-2026-49212 checksum binding, CVE-2026-49215 CSRF through the CORS-safelisted Accept header).Affected branches: find the oldest version where the vulnerable code exists and intersect with the maintained branches, 2.x and 3.x (ux publishes no releases.json). Fix on the lowest maintained affected branch, then merge up with the merge-up skill: every 2026 CVE fix landed on 2.x and reached 3.x that way. Code that exists only on 3.x is fixed on 3.x. Record the oldest exposure even if it predates maintained versions; it becomes the GHSA affected range.
State the recommendation as: disposition + severity + affected maintained branches + the one-line rationale (which decision-tree conditions decided it), then route:
cve-<year>-<number>. The fix is prepared privately and goes through the coordinated-disclosure process (GHSA + CVE, reporter credit, security release). Do not open a public PR or push to a public remote before the release; origin is a public fork, so it counts. The fix carries a src/<Package>/CHANGELOG.md entry ending with (security fix), plus a BC note when the fix changes behaviour users can see (see the LiveComponent 2.36 entries). Wait for confirmation before any outward step, and print any git push command for the user instead of running it.symfony-security-review to confirm the fix. Hardening PRs such as #3565 and #3566 carried no CHANGELOG entry; add one only when users see a behaviour change.In every case, the fix follows TDD and runs only the affected package's tests: cd src/<Package> && composer update && php vendor/bin/phpunit, plus pnpm run test:unit and pnpm run build in src/<Package>/assets for a JS change, since dist/ is committed. No Claude/Anthropic credit, comments sparingly, no issue references in code.
From ux's published advisories and merged fixes:
| Finding shape | Disposition | Deciding factor |
|---|---|---|
A third-party kit's copy-files entry with .. makes the installer write outside the project (CVE-2026-55878) | CVE, high | the author of a remote kit is untrusted; arbitrary file write |
{{ attributes }} renders attribute values unescaped (CVE-2025-47946) | CVE, medium | default rendering path, XSS |
| Iconify API or local SVG rendered without sanitization (CVE-2026-55877) | CVE, medium | ux outputs the markup, so it owns sanitizing it |
Autocomplete Stimulus controller renders AJAX text unescaped (CVE-2026-49216) | CVE, medium | stored XSS through a default option |
| Client-sent child component tag interpolated into HTML (CVE-2026-49210) | CVE, medium | XSS, published even though the live endpoint checks gate it by default |
Accept header used as the only CSRF gate on live endpoints (CVE-2026-49215) | CVE, low | Accept is CORS-safelisted, so cross-origin fetch() sets it without a preflight |
Unbounded _batch actions, one sub-request each (CVE-2026-49209) | CVE, low | DoS; ux precedent differs from the Symfony policy default |
LiveComponentSubscriber test mode defaulting to on outside the compiler pass (#3566) | Hardening | the unsafe default never reached production through the bundle's DI |
extra_options checksum compared with !== (#3565) | Hardening | timing nuance, no working exploit |
Not-a-security-issue shapes follow from the documented contracts in Step 0.4 (a writable LiveProp set by the client, options_as_html: true, an autocompleter left public). They come from the documentation, not from a ruling on record, so say so in the reply.
cve-* branch, or open a public issue or PR for a CVE-class finding before the coordinated release. Wait for confirmation.© symfony, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .agents/skills/security-triage of symfony/ux.
Open the folder on GitHubat commit 5e9614c
Security Triage next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Security Triage this skillsymfony/ux | 1.1k | — | ~3.2k | Automated safety check: Pass | MIT | |
| Security Triagesymfony/symfony | 31k | — | ~2.6k | Automated safety check: Pass | MIT | |
| Deepsec Documentation Guidevercel-labs/deepsec | 8.1k | — | ~956 | Automated safety check: Pass | Apache-2.0 | |
| Shiro Attack CLISummerSec/ShiroAttack2 | 2.6k | — | ~945 | Automated safety check: Pass | MIT | |
| Cve Remediationrundeck/rundeck | 6.3k | — | ~2.9k | Automated safety check: Pass | Apache-2.0 | |
| Native Dependency Updatemono/SkiaSharp | 5.6k | — | ~4.1k | Automated safety check: Pass | MIT |
symfony/symfony
Triage a reported security finding into a disposition: a private CVE (coordinated disclosure + advisory), a public hardening PR (fix in the open, no CVE), or not-a-security-issue (reply to reporter).
vercel-labs/deepsec
Points the agent at deepsec's own docs to answer questions about initializing, configuring, resuming, scanning with and extending the vulnerability scanner.
SummerSec/ShiroAttack2
当用户要求利用、检测或测试 Apache Shiro rememberMe 反序列化漏洞 (Shiro-550, CVE-2016-4437) 时使用。触发词包括 "Shiro"、"rememberMe"、"shiro attack"、"CVE-2016-4437"、"Shiro-550"、"爆破 Shiro key"、"利用 Shiro"、"Shiro…
rundeck/rundeck
Verify if a CVE affects the project and remediate it. An agent skill from rundeck/rundeck.
mono/SkiaSharp
Update native dependencies (libpng, libexpat, zlib, libwebp, harfbuzz, freetype, libjpeg-turbo, etc.) in SkiaSharp's Skia fork.
alexgreensh/repo-forensics
Cross-agent self-inspection of your AI-agent stack. An agent skill from alexgreensh/repo-forensics.
symfony/ux
Cascade-merge the maintained Symfony UX branches from oldest to newest (2.x - 3.x), resolve conflicts, run the affected packages' tests and prepare the push.
symfony/ux
Principles for rigorously reviewing a Symfony UX pull request and making it merge-ready.
symfony/ux
Review a change (a PR, the current branch diff, or a set of files) or audit a Symfony UX package or the whole src/ tree for missing or incorrect security hardening.
symfony/ux
Generate, modify, or review Symfony UX Toolkit kit recipes (shadcn, flowbite-4, bootstrap, common).
Works with
Categories
Triage a security finding in a Symfony UX package into a disposition: a private CVE (coordinated disclosure through the Symfony security process), a public hardening PR (fix in the open, no CVE), or…. Security Triage is an agent skill from symfony/ux. Triage a security finding in a Symfony UX package into a disposition: a private CVE (coordinated disclosure through the Symfony security process), a public hardening PR (fix in the open, no CVE), or not-a-security-issue (reply to the reporter).
Security Triage fits situations like: deciding whether a report; A discovered weakness needs a CVE; how it should be disclosed; whether it is a security issue at all.
Run `npx skills add symfony/ux --skill security-triage -a claude-code`. Or copy the skill folder (.agents/skills/security-triage in symfony/ux) into .claude/skills/security-triage in your project. Claude Code loads it when a task matches its description.
Run `npx skills add symfony/ux --skill security-triage -a codex`. Or copy the skill folder (.agents/skills/security-triage in symfony/ux) into .agents/skills/security-triage in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add symfony/ux --skill security-triage -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/security-triage, .gemini/skills/security-triage, .github/skills/security-triage and .opencode/skills/security-triage in your project.
Going by SKILL.md and its folder, Security Triage needs the command-line tools its instructions call (pnpm, git, composer and php).
SKILL.md names 1 domain. As links in the text: symfony.com. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Security Triage is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 3.2k tokens (SKILL.md is roughly 13k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Security Triage: Security Triage (symfony/symfony, 31k stars), Deepsec Documentation Guide (vercel-labs/deepsec, 8.1k stars), Shiro Attack CLI (SummerSec/ShiroAttack2, 2.6k stars) and Cve Remediation (rundeck/rundeck, 6.3k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
symfony (a GitHub organization) maintains it in symfony/ux, which has 1,080 GitHub stars. The repository holds 5 skills in this directory. The repository was last updated on October 8, 2026.
Source: symfony/ux on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.