Agent skill

Symfony Security Review

by symfony in 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.

MITAuto-check passedSecurity

Install Symfony Security Review

skills CLI
$ npx skills add symfony/ux --skill symfony-security-review -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install symfony/ux symfony-security-review --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/symfony/ux.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/symfony-security-review .claude/skills/symfony-security-review && rm -rf skills-src

Use ~/.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/

Facts

Skill name
symfony-security-review
GitHub stars
1.1k
Token cost
~2.9k tokens
SKILL.md length
1,544 words
Files
2
Skills in repo
5
Repo updated
First seen
Licence
MIT

At a glance

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.

  • Works in 6 steps: Pick mode and resolve the scope → First-principles boundary pass… → Map to families (known-class checklist) → …
  • Asked for a security review
  • SKILL.md covers Scope and non-goals, Progress checklist, Confirmation rule and Parallelism (large audits only), plus 9 more sections
  • Calls git, gh and pnpm; reaches github.com

What it does

Symfony Security Review is an agent skill from 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. Reasons about trust boundaries from first principles, then checks the code against the hardening families catalogued from ux's past security fixes. Use when asked for a security review or a security audit of ux code, whether a change weakens a security control, or to hunt a vulnerability class across the packages.

Its SKILL.md is about 2.9k tokens, which your agent loads only when the skill is triggered. The skill folder holds 1 other file (for example `hardening-families.md`).

It sits in Security, covering Security review. It works with Symfony. The repository describes itself as: Symfony UX initiative: a JavaScript ecosystem for Symfony. The licence is MIT.

When your agent uses it

  • Asked for a security review
  • A security audit of ux code
  • Whether a change weakens a security control
  • Hunt a vulnerability class across the packages

Example prompts

  • “/symfony-security-review”

Workflow steps

6 steps, taken from the step headings in SKILL.md.

  1. Pick mode and resolve the scope
  2. First-principles boundary pass (open-world)
  3. Map to families (known-class checklist)
  4. Check the automated gates
  5. Manual per-family review
  6. Report findings

What it can do on your machine

Read from SKILL.md and the folder at commit 93cda70. It shows what the files ask for, not the result of running them.

  • Tool permissions

    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.

  • Runs code

    Shell commands in SKILL.md call:

    • git
    • gh
    • pnpm
    • composer
    • php

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Hosts in commands or code, which the agent is likely to contact:

    • github.com

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Symfony Security Review loads about 2.9k tokens when it runs. Until then it costs about 127 tokens; SKILL.md has 1,544 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~127
When it runs · the whole SKILL.md, loaded when a task matches
~2.9k

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.

Safety

Auto-check passed

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.

SKILL.md

The full file from symfony/ux at commit 93cda70, republished under its MIT licence (© symfony). 1,544 words, ~2,916 tokens.

Download SKILL.mdSave it as .claude/skills/symfony-security-review/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.
name
symfony-security-review
description
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. Reasons about trust boundaries from first principles, then checks the code against the hardening families catalogued from ux's past security fixes. Use when asked for a security review or a security audit of ux code, whether a change weakens a security control, or to hunt a vulnerability class across the packages.

Symfony UX Security Review

Finds hardening that is missing or wrong, grounded in code. It runs in two modes:

  • Review a change (default): a PR, the current branch vs its base, or named files.
  • Audit a target: a package path (e.g. src/LiveComponent) or the whole src/ tree, for one or all families.

Both modes run two passes: first reason about the change's trust boundaries from first principles (to catch novel issues), then check it against the hardening families catalogued in hardening-families.md. Each family comes from a real ux fix; the catalogue is a checklist of known classes, not the search space.

Scope and non-goals

  • This skill spots missing hardening. It does not triage an incoming report end to end, assign a CVE, or merge a fix. security-triage makes the disclosure call.
  • Every finding must point at a real sink (a concrete file and line). No speculative findings. A family with no sink in scope is not in scope; but a sink that matches no family is still in scope (that is what Step 1 is for).
  • Respect the decision boundaries in the catalogue: several plausible-looking shapes are documented app responsibilities. Do not raise those.

Progress checklist

  • Step 0: Pick mode and resolve the scope
  • Step 1: First-principles boundary pass (open-world)
  • Step 2: Map to families (known-class checklist)
  • Step 3: Check the automated gates
  • Step 4: Manual per-family review
  • Step 5: Report findings

Confirmation rule

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.

Parallelism (large audits only)

When auditing the whole src/ tree or a large package, fan Step 1 and Step 4 out to subagents: one per family, or one per package, each returning findings that point at a concrete file and line (no speculative findings leaking in through parallelism). Keep the rest in the main loop: aggregation, de-duplication, the completeness check, and the report are synthesis and must see every finding at once. For a single PR or a small diff, run every step inline; subagents are pure overhead there.


Step 0 — Pick mode and resolve the scope

Review a change. Check the PR out locally so the whole package is readable, and diff against its real base:

bash
# A public PR
git worktree add --detach .claude/worktrees/pr<n>
cd .claude/worktrees/pr<n> && gh pr checkout <n>
gh pr view <n> --json baseRefName --jq .baseRefName
git diff upstream/<base>...HEAD --stat
# The current branch against its base (2.x or 3.x)
git diff upstream/<base>...HEAD --stat

Audit a target. Take a package path or the whole src/ tree. There is no diff; the "changed files" are the target files.

In both modes, build the file list from src/<Package>/src/ (PHP), src/<Package>/assets/src/ (TypeScript), src/<Package>/config/ and src/<Package>/templates/. Drop tests/, assets/test/ and the built assets/dist/: hardening lives in the implementation, and dist/ is generated from assets/src/.

State the resolved mode and scope back to the user in one line before continuing.

Step 1 — First-principles boundary pass (open-world)

This pass finds what the catalogue does not list. Do it before mapping to families, and do not let the anchors narrow it. For each file in scope, reason as an attacker, independent of any known family:

  1. Inputs: what untrusted data can reach this code? In ux: the LiveComponent request payload (props, updated, propsFromParent, children, action arguments, _batch actions), the Autocomplete query and extra_options, AJAX responses a Stimulus controller renders, Iconify API responses and local SVG files, a third-party Toolkit kit (--kit=https://github.com/...: its manifest and files), values an app passes into component attributes, request headers.
  2. Flow: follow each input to where it is used. Does it reach a sink (HTML output from PHP or from a TypeScript template literal / innerHTML, a Twig function declared is_safe, DQL/SQL, the filesystem, a sub-request, object construction from a client value, a comparison of a secret)?
  3. Boundary: which trust boundary does it cross, and who is the expected actor (unauthenticated visitor, lower-privileged user, a cross-origin page, the author of a remote kit)?
  4. Worst case: if the attacker fully controls the input, what is the maximum impact? State it concretely (file write, XSS, CSRF, forged props, data disclosure, DoS).

Record every input-to-sink path with a non-trivial worst case as a candidate finding, whether or not it matches a catalogued family. An unguarded path from untrusted input to a dangerous sink is a finding even if no anchor names it. This step uses no greps by design; it is meant to see sinks the dictionary misses.

Step 2 — Map to families (known-class checklist)

Now apply the catalogue as a checklist, to confirm no known class slipped past Step 1. Treat each anchor's listed APIs as seed examples of an abstract role (a checksum over client data, a client value interpolated into HTML, a list that fans out into sub-requests, a path built from a manifest); extend to anything in scope that plays that role, including code the grep does not name.

For each file in scope, decide which families it touches using the anchors in hardening-families.md. Run the anchors against the scope, not the whole tree, when reviewing a change:

bash
# Example: which families does this branch touch?
git diff upstream/<base>...HEAD --name-only | grep -vE '/tests/|/assets/test/|/assets/dist/' > /tmp/scope.txt
grep -lE 'hash_hmac|hash_equals|is_safe|innerHTML|new \$|LIKE|Path::|copy-files|_batch|X-Requested-With' $(cat /tmp/scope.txt) 2>/dev/null

Carry forward both Step 1's boundary findings and the families with a sink in scope; they proceed to Step 4. List them.

Step 3 — Check the automated gates

ux has no automated hardening gate for its PHP or TypeScript code, so every family goes through Step 4. Two checks exist around it:

  • zizmor runs on every PR (.github/workflows/zizmor.yaml) and covers GitHub Actions workflows (family W1).
  • PHPStan runs only for src/Turbo (phpstan.dist.neon), with no security-specific rule.

Step 4 — Manual per-family review

For each in-scope family, apply its invariant from hardening-families.md. The catalogue gives, per family: the anchor, the invariant, the fix it comes from, and the decision boundary.

Work the sinks, not the families in the abstract: for every sink site the anchor found, answer the family's check question. If the answer is "no guard / wrong guard", it is a candidate finding; confirm it is not excluded by the decision boundary before reporting.

Show full SKILL.md (581 more words)Show less

Step 5 — Report findings

Output a table, highest severity first:

LocationFamilySeverityInvariant at riskSuggested hardeningRegression test
src/LiveComponent/src/Util/ChildComponentPartialRenderer.php:NNL5 live-markupMediumclient tag interpolated into HTMLvalidate against VALID_TAGmalicious-tag case in InterceptChildComponentRenderSubscriberTest

Severity rubric:

  • Critical: pre-auth RCE or full auth bypass.
  • High: arbitrary file read/write, signature/secret bypass that accepts forged props.
  • Medium: stored/reflected XSS on a default-rendered surface, sensitive data leak.
  • Low: DoS / resource exhaustion, lenient parsing with bounded impact, defense-in-depth only.
  • Not a finding: excluded by a decision boundary (say which one).

When a finding moves on to security-triage, the level becomes the proposed GHSA severity (Critical and High both propose high).

For each real finding, state whether a regression test is required at the boundary, in the shape ux already uses: a malicious input that must be rejected (the tests/Fixtures/kits/malicious kit for the Toolkit installer, the malicious child tags in InterceptChildComponentRenderSubscriberTest).

Completeness check (before you finalise). State explicitly: is there an untrusted input, a sink, a checksum, an HTML output, or a trust boundary in scope that matched no anchor and was not already raised in Step 1? If so, reason about it from scratch before reporting. A clean family sweep is not a clean review.

The table holds findings from both passes: the Step 1 boundary pass (Family column = the vulnerability class, or novel) and the Step 4 family review.

Separate confirmed findings from needs-human-judgement ones. Do not inflate.


If a finding is real: fix handoff

  • A CVE-class finding goes to security-triage first and stays private: no public issue, PR, commit, or pushed branch before the coordinated release (origin is a public fork too). Wait for confirmation.
  • TDD: write the failing regression test first, then the fix.
  • Package-scoped tests only: cd src/<Package> && composer update && php vendor/bin/phpunit. For a TypeScript fix, also pnpm run test:unit and pnpm run build in src/<Package>/assets, and commit dist/.
  • When a limit exists on both sides (PHP and TypeScript), change both in the same commit.
  • No Co-Authored-By, no Claude/Anthropic credit. Comments sparingly, and do not reference issue numbers in code or tests.
  • Never run git push; print the command for the user.

Gotchas

  • Decision boundaries are real. A writable: true LiveProp is client-controlled by design; options_as_html: true renders raw HTML on purpose; an autocompleter with the default security: false is public by documentation; the Icons sanitizer keeps <style> on purpose. The catalogue lists these; respect them or you will cry wolf.
  • Data families are answer-keys. The Icons forbidden-element and URL-scheme lists and the LiveComponent VALID_TAG regex are curated sets; a review only confirms them, it cannot prove the next missing entry. Flag gaps for a data-provider test.
  • Paired limits drift. MAX_ACTIONS_PER_BATCH exists in BatchActionController and in assets/src/Component/index.ts; changing one side alone either breaks the client or reopens the cap.
  • Escaping has to be portable. The Autocomplete LIKE escape character is ! because \ produced invalid SQL on PostgreSQL (#3685). A fix that escapes correctly on one database and breaks another is not done.
  • Anchors are seed examples, not the search space. Novel issues surface in the Step 1 first-principles pass, not the greps. A finding that matches no family is still a finding; do not let the dictionary bound the review.

Error handling

  • Never fabricate a sink. If the anchor finds nothing, say the family is out of scope.
  • Security reports are handled privately. Do not echo report contents into public artifacts.
  • When unsure whether something crosses a decision boundary, report it as needs-human-judgement with the boundary named, and 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

Files

SKILL.md and 1 other file in .agents/skills/symfony-security-review of symfony/ux.

  • SKILL.md
  • hardening-families.md

Open the folder on GitHubat commit 93cda70

Compare with similar skills

Symfony Security Review 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.

Symfony Security Review compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Symfony Security Review this skillsymfony/ux1.1k—~2.9kAutomated safety check: PassMIT
Symfony Security Reviewsymfony/symfony31k—~2.9kAutomated safety check: PassMIT
Deepsec Documentation Guidevercel-labs/deepsec8.1k—~956Automated safety check: PassApache-2.0
Kubernetes Network Security Auditkubeshark/kubeshark12k—~7.3kAutomated safety check: NotesApache-2.0
Native Dependency Updatemono/SkiaSharp5.6k—~4.1kAutomated safety check: PassMIT
Semgrep Security Scantrailofbits/skills7.5k—~3.7kAutomated safety check: NotesCC-BY-SA-4.0

Similar skills

  • Review a change (a PR, the current branch diff, or a set of files) or audit a component or the whole tree for missing or incorrect security hardening.

    31k GitHub stars~2.9k tokensUpdated today
    SecurityAuto-check passed
  • Deepsec Documentation Guide

    vercel-labs/deepsec

    Official

    Points the agent at deepsec's own docs to answer questions about initializing, configuring, resuming, scanning with and extending the vulnerability scanner.

    8.1k GitHub stars~956 tokensUpdated 11 days ago
    SecurityAuto-check passed
  • Hunts for compromised workloads and malicious traffic in a Kubernetes cluster by sweeping network data through Kubeshark MCP, mapped to MITRE ATT&CK.

    12k GitHub stars~7.3k tokensUpdated yesterday
    SecurityAuto-check: notes
  • Update native dependencies (libpng, libexpat, zlib, libwebp, harfbuzz, freetype, libjpeg-turbo, etc.) in SkiaSharp's Skia fork.

    5.6k GitHub stars~4.1k tokensUpdated yesterday
    SecurityAuto-check passed
  • Semgrep Security Scan

    trailofbits/skills

    Official

    Detects languages, proposes rulesets for approval, then runs the approved Semgrep scan across a codebase and merges the output into one SARIF file.

    7.5k GitHub stars~3.7k tokensUpdated yesterday
    SecurityAuto-check: notes
  • Skillward Audit

    Fangcun-AI/SkillWard

    Security-audit a third-party skill bundle (folder with SKILL.md, or .zip / .tar.gz archive) before installing it, using the SkillWard cloud scanner.

    143 GitHub stars~2.9k tokensUpdated 2 mo ago
    SecurityAuto-check passed

More from symfony/ux

  • Merge Up

    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.

    1.1k GitHub stars~3.4k tokensUpdated today
    Auto-check passed
  • Principles for rigorously reviewing a Symfony UX pull request and making it merge-ready.

    1.1k GitHub stars~4.6k tokensUpdated today
    Auto-check passed
  • Security Triage

    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…

    1.1k GitHub stars~3.2k tokensUpdated today
    Auto-check passed
  • Generate, modify, or review Symfony UX Toolkit kit recipes (shadcn, flowbite-4, bootstrap, common).

    1.1k GitHub stars~10k tokensUpdated today
    Auto-check passed

Works with

Categories

Questions about Symfony Security Review

What does Symfony Security Review do?

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 Security Review is an agent skill from 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.

When should I use Symfony Security Review?

Symfony Security Review fits situations like: asked for a security review; A security audit of ux code; whether a change weakens a security control; hunt a vulnerability class across the packages.

How do I install Symfony Security Review in Claude Code?

Run `npx skills add symfony/ux --skill symfony-security-review -a claude-code`. Or copy the skill folder (.agents/skills/symfony-security-review in symfony/ux) into .claude/skills/symfony-security-review in your project. Claude Code loads it when a task matches its description.

How do I install Symfony Security Review in Codex?

Run `npx skills add symfony/ux --skill symfony-security-review -a codex`. Or copy the skill folder (.agents/skills/symfony-security-review in symfony/ux) into .agents/skills/symfony-security-review in your project. Codex loads it when a task matches its description.

Can I use Symfony Security Review in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add symfony/ux --skill symfony-security-review -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/symfony-security-review, .gemini/skills/symfony-security-review, .github/skills/symfony-security-review and .opencode/skills/symfony-security-review in your project.

What does Symfony Security Review need to run?

Going by SKILL.md and its folder, Symfony Security Review needs the command-line tools its instructions call (git, gh, pnpm, composer and php).

Does Symfony Security Review access the network?

SKILL.md names 1 domain. In commands or code: github.com; the agent is likely to contact it when it follows the instructions. This is read from the text; nothing was executed.

Is Symfony Security Review safe to install?

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.

What licence does Symfony Security Review use?

Symfony Security Review is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Symfony Security Review use?

About 2.9k tokens (SKILL.md is roughly 12k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Symfony Security Review?

Skills that share tags, products or a category with Symfony Security Review: Symfony Security Review (symfony/symfony, 31k stars), Deepsec Documentation Guide (vercel-labs/deepsec, 8.1k stars), Kubernetes Network Security Audit (kubeshark/kubeshark, 12k stars) and Native Dependency Update (mono/SkiaSharp, 5.6k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Symfony Security Review?

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 11, 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.