rails-cto-security
Skill15 starsChanged 7 months agoMITView on GitHub
Run Brakeman and bundler-audit security scans on changed files and fix high/medium confidence warnings. Use when any .rb or .html.erb file is created or modified. Also use when the user mentions "security", "brakeman", "bundle-audit", "audit", "vulnerability", "XSS", "SQL injection", "CVE", "advisory", "mass assignment", "CSRF", or asks about secure coding practices. Proactively invoke this skill after code changes, even if the user doesn't ask.
In this repository17 other files it gives its agents.
- claude/CLAUDE.mdCLAUDE.md
- rails-cto-apiSkill
- rails-cto-architectSkill
- rails-cto-commitSkill
- rails-cto-engineerSkill
- rails-cto-erbSkill
- rails-cto-minitestSkill
- rails-cto-production-prSkill
- rails-cto-pull-requestSkill
- rails-cto-qaSkill
- rails-cto-restfulSkill
- rails-ctoSkill
- rails-cto-static-analysisSkill
- rails-cto-stimulusSkill
- rails-cto-tailwindSkill
- rails-upgradeSkill
- rails-viewcomponentsSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
23 rules. About 0 are common, 17 are distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈17
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 26
If the command fails, inform the user:
- Distinctive: line 38
If Brakeman is not available, skip the scanning steps below and continue.
- Distinctive: line 42
Check if the project already has a Brakeman config:
- Distinctive: line 48
If the file does not exist, create it:
- Very specific: line 70
Use git to find only the .rb and .html.erb files that were modified:
- Distinctive: line 76
If there are unstaged changes too:
- Distinctive: line 86
Run Brakeman scoped to only the changed files, outputting JSON to stdout:
- Very specific: line 134
Read the warning's file, line, code, and message
- Distinctive: line 160
Do not attempt to fix weak warnings.
- Very specific: line 164
If a warning's fingerprint is listed in config/brakeman.yml under :ignored_warnings, skip it silently.
- Distinctive: line 170
After fixing all high and medium warnings, re-run Brakeman on the same files:
- Distinctive: line 176
If all high/medium warnings are resolved: the scan passes.
- Distinctive: line 177
If warnings remain after one fix attempt: stop and report the remaining warnings to the user.
- Distinctive: line 183
After the Brakeman scan, run bundler-audit to check for known vulnerabilities in gem dependencies.
- Distinctive: line 203
If bundler-audit is not available, skip the audit steps below and continue.
- Distinctive: line 207
Always update the advisory database before scanning to catch the latest CVEs:
- Distinctive: line 217
Check for a config file:
- Distinctive: line 258
Check the Solution field for the required version
- Very specific: line 259
Update the gem in the Gemfile if it has a pinned version
- Very specific: line 260
Run bundle update <gem_name> to pull the patched version
- Distinctive: line 263
If a gem cannot be updated (dependency conflicts, breaking changes), report it to the user with the CVE, current version, and required …
- Distinctive: line 274
Do not block completion on low criticality advisories.
- Very specific: line 278
If an advisory ID is listed in .bundler-audit.yml under ignore, bundler-audit skips it automatically.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Security Scanning in This Project
Every .rb and .html.erb change is scanned with Brakeman and bundler-audit before the work is considered done. Brakeman catches code-level vulnerabilities; bundler-audit catches known CVEs in your gem dependencies. High and medium confidence warnings must be fixed. This skill runs after code changes are made — it is a post-change quality gate, not a write blocker.
Pre-flight: Check Brakeman Setup (MANDATORY)
You MUST run these steps every time this skill is invoked.
1. Check if Brakeman is available
bundle exec brakeman --version 2>/dev/nullIf the command fails, inform the user:
"This project doesn't have the
brakemangem installed. Add it to your Gemfile:group :development do gem "brakeman", require: false endThen run
bundle install."
If Brakeman is not available, skip the scanning steps below and continue. Do not block on Brakeman installation. But if Brakeman IS available, you MUST run the scanning steps — do not skip them.
2. Install the recommended config (if missing)
Check if the project already has a Brakeman config:
ls config/brakeman.yml 2>/dev/nullIf the file does not exist, create it:
---
# Brakeman configuration
# See https://brakemanscanner.org/docs/options/ for all options
# Only report high and medium confidence warnings
:min_confidence: 1
# Output format (overridden by CLI flags, but serves as default)
:output_format: json
# Quiet mode — suppress informational messages
:quiet: true
# Ignored warning fingerprints (add false positives here)
:ignored_warnings: []3. Identify changed files
Use git to find only the .rb and .html.erb files that were modified:
git diff --name-only --diff-filter=ACMR HEAD 2>/dev/null | grep -E '\.(rb|html\.erb)$'If there are unstaged changes too:
git diff --name-only --diff-filter=ACMR 2>/dev/null | grep -E '\.(rb|html\.erb)$'Combine both lists and deduplicate. If no matching files were changed, skip the scan — there is nothing to check.
4. Run Brakeman on changed files
Run Brakeman scoped to only the changed files, outputting JSON to stdout:
bundle exec brakeman --only-files file1.rb,file2.rb -f json -q --no-pagerFor example, if app/controllers/users_controller.rb and app/models/user.rb were changed:
bundle exec brakeman --only-files app/controllers/users_controller.rb,app/models/user.rb -f json -q --no-pagerImportant: Pass file paths as a comma-separated list to --only-files. Use relative paths from the Rails root.
Reading Brakeman JSON Output
The JSON output contains a warnings array. Each warning has:
{
"warning_type": "SQL Injection",
"warning_code": 0,
"message": "Possible SQL injection",
"file": "app/controllers/users_controller.rb",
"line": 42,
"code": "User.where(params[:query])",
"confidence": "High",
"fingerprint": "abc123..."
}Key fields:
confidence— "High", "Medium", or "Weak"warning_type— Category (SQL Injection, Cross-Site Scripting, Mass Assignment, etc.)fileandline— Exact location of the issuecode— The vulnerable code snippetfingerprint— Unique identifier (used for ignoring false positives)
Fixing Warnings
High and Medium confidence: fix immediately
For each high or medium confidence warning:
- Read the warning's
file,line,code, andmessage - Fix the underlying vulnerability — do not suppress or ignore it
- Common fixes by warning type:
| Warning Type | Typical Fix |
| SQL Injection | Use parameterized queries, where(field: value), or sanitize_sql |
| Cross-Site Scripting (XSS) | Use sanitize, h(), or content_tag instead of raw/html_safe |
| Mass Assignment | Use strong_parameters — never permit! |
| Command Injection | Use Open3.capture3 or array form of system instead of backticks/exec |
| Dynamic Render Path | Use explicit template names, not user-controlled paths |
| File Access | Validate and sanitize file paths, use ActiveStorage |
| Redirect | Use _path/_url helpers, validate redirect targets with url_from |
| Unsafe Deserialization | Avoid Marshal.load, YAML.unsafe_load on user input |
| Session Manipulation | Use reset_session, don't store sensitive data in sessions |
| Dangerous Send | Validate method names against an allowlist before .send |
Weak confidence: mention but do not fix
For weak confidence warnings, list them once as informational:
"Brakeman also reported N weak-confidence warnings that may be false positives:
- [file:line] warning_type: message
These are informational only — review them if you'd like, but no action is required."
Do not attempt to fix weak warnings. Do not block completion on them.
False positives
If a warning's fingerprint is listed in config/brakeman.yml under :ignored_warnings, skip it silently. Do not mention ignored warnings in the output.
Verify Fixes
After fixing all high and medium warnings, re-run Brakeman on the same files:
bundle exec brakeman --only-files file1.rb,file2.rb -f json -q --no-pager- If all high/medium warnings are resolved: the scan passes. Continue.
- If warnings remain after one fix attempt: stop and report the remaining warnings to the user. Do not attempt a second fix cycle. List each remaining warning with its file, line, type, and message so the user can decide how to proceed.
Dependency Audit: bundler-audit
After the Brakeman scan, run bundler-audit to check for known vulnerabilities in gem dependencies.
1. Check if bundler-audit is available
bundle-audit --version 2>/dev/nullIf the command fails, inform the user:
"This project doesn't have the
bundler-auditgem installed. Add it to your Gemfile:group :development do gem "bundler-audit", require: false endThen run
bundle install."
If bundler-audit is not available, skip the audit steps below and continue. Do not block on installation. But if bundler-audit IS available, you MUST run it — do not skip.
2. Update the advisory database and run the audit
Always update the advisory database before scanning to catch the latest CVEs:
bundle-audit check --updateThis updates the ruby-advisory-db and immediately runs the check.
3. Install .bundler-audit.yml if missing
Check for a config file:
ls .bundler-audit.yml 2>/dev/nullIf the file does not exist, create it:
---
# bundler-audit configuration
# Add advisory IDs here to ignore known false positives
ignore: []Reading bundler-audit output
bundler-audit reports vulnerable gems in this format:
Name: actionpack
Version: 7.0.4
Advisory: CVE-2023-22796
Criticality: High
URL: https://nvd.nist.gov/vuln/detail/CVE-2023-22796
Title: ReDoS vulnerability in Active Support
Solution: upgrade to >= 7.0.4.1Key fields:
- Name and Version — the vulnerable gem and its current version
- Advisory — CVE or OSVDB identifier
- Criticality — High, Medium, or Low
- Solution — the version to upgrade to
Fixing vulnerabilities
High and Medium criticality: fix immediately
For each high or medium advisory:
- Check the Solution field for the required version
- Update the gem in the
Gemfileif it has a pinned version - Run
bundle update <gem_name>to pull the patched version - Re-run
bundle-audit checkto verify the vulnerability is resolved
If a gem cannot be updated (dependency conflicts, breaking changes), report it to the user with the CVE, current version, and required version so they can decide how to proceed.
Low criticality: mention but do not fix
For low criticality advisories, list them as informational:
"bundler-audit also reported N low-criticality advisories:
- [gem_name] (version) — CVE-XXXX-XXXX: title
These are informational only — review them if you'd like, but no action is required."
Do not block completion on low criticality advisories.
Ignored advisories
If an advisory ID is listed in .bundler-audit.yml under ignore, bundler-audit skips it automatically. Do not mention ignored advisories in the output.
Integration with QA
This skill runs alongside /rails-cto-qa, not as a replacement. The typical end-of-task flow is:
/rails-cto-qa— RuboCop linting + test suite/rails-cto-security— Brakeman scan + bundler-audit- Fix any issues from either skill
- Task complete
Both must pass before the work is considered done.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

