rails-guarddog 0.1.0 → 0.1.1
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.
- checksums.yaml +4 -4
- data/README.md +383 -66
- data/lib/rails/guarddog/checkers/sql_injection_checker.rb +1 -1
- data/lib/rails/guarddog/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ce1243897a581352571855426cfa802e854ea49e4bc175590689584468185a89
|
|
4
|
+
data.tar.gz: a1f2593ca6f6846a40d5664f82d3865fdcc4c508dcbfe7123cb6cdaac5874824
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8d72dcedb4906ddce7552688440c06367e02e8a1050787e5dd148c77d7df76302fbaad57f70e25504ef45c281cf55d53ece722e7945777297d2a89c2fc38f265
|
|
7
|
+
data.tar.gz: 74a571887c5bc2504b7bd0c755e0f54bb85ec5145fae8501ac8d3d993670033bb2bcc981803dd995c069c9687a7b2ece78f98c6af7274f91a3b69fdeee56a435
|
data/README.md
CHANGED
|
@@ -1,66 +1,383 @@
|
|
|
1
|
-
# Rails GuardDog 🐕
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
|
|
12
|
-
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
1
|
+
# Rails GuardDog 🐕 v0.1.0
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/rb/rails-guarddog)
|
|
4
|
+
[](https://rubygems.org/gems/rails-guarddog)
|
|
5
|
+
[](https://github.com/sghani001/rails-guarddog)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](https://www.ruby-lang.org/)
|
|
8
|
+
[](https://rubyonrails.org/)
|
|
9
|
+
[](https://github.com/sghani001/rails-guarddog)
|
|
10
|
+

|
|
11
|
+
|
|
12
|
+
Production-grade security scanner for Rails applications. **Beyond brakeman** — detects AI injection, DoS patterns, supply chain attacks, GraphQL authorization gaps, and more.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## ✨ Why Rails GuardDog?
|
|
17
|
+
|
|
18
|
+
| Feature | Brakeman | bundler-audit | rack-attack | GuardDog |
|
|
19
|
+
|---------|----------|---------------|-------------|----------|
|
|
20
|
+
| SQL Injection | ✅ | - | - | ✅ Enhanced |
|
|
21
|
+
| XSS Detection | ✅ | - | - | ✅ Extended |
|
|
22
|
+
| CSRF Checks | ✅ | - | - | ✅ Full |
|
|
23
|
+
| Mass Assignment | ✅ Partial | - | - | ✅ **permit! fixed** |
|
|
24
|
+
| Hardcoded Secrets | ⚠️ Optional | - | - | ✅ **Always-on** |
|
|
25
|
+
| Open Redirect | ✅ | - | - | ✅ |
|
|
26
|
+
| **DoS/ReDoS** | ❌ | - | - | ✅ **NEW** |
|
|
27
|
+
| **IDOR** | ❌ | - | - | ✅ **NEW** |
|
|
28
|
+
| **AI Injection** | ❌ | - | - | ✅ **ORIGINAL** |
|
|
29
|
+
| **Supply Chain** | ❌ | ⚠️ Limited | - | ✅ **Typosquatting** |
|
|
30
|
+
| **Rate Limiting** | ❌ | - | ⚠️ Config only | ✅ **Audit** |
|
|
31
|
+
| **GraphQL Auth** | ❌ | - | - | ✅ **BONUS** |
|
|
32
|
+
|
|
33
|
+
## 📊 Stats
|
|
34
|
+
|
|
35
|
+
| Metric | Value |
|
|
36
|
+
|--------|-------|
|
|
37
|
+
| **Version** | 1.0.0 |
|
|
38
|
+
| **Security Checkers** | 12 |
|
|
39
|
+
| **Report Formats** | 3 (Console, HTML, JSON) |
|
|
40
|
+
| **Dependencies** | 2 (parser, ast) |
|
|
41
|
+
| **Lines of Code** | ~2,000 |
|
|
42
|
+
| **Test Coverage** | Ready for RSpec |
|
|
43
|
+
| **License** | MIT |
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 🚀 Quick Start
|
|
48
|
+
|
|
49
|
+
### Installation
|
|
50
|
+
|
|
51
|
+
Add to your Gemfile:
|
|
52
|
+
```ruby
|
|
53
|
+
gem 'rails-guarddog'
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Then run:
|
|
57
|
+
```bash
|
|
58
|
+
bundle install
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### First Scan
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# See results in terminal
|
|
65
|
+
rake guarddog:scan
|
|
66
|
+
|
|
67
|
+
# Generate HTML + JSON reports
|
|
68
|
+
rake guarddog:report
|
|
69
|
+
|
|
70
|
+
# CI/CD integration (exits 1 if critical found)
|
|
71
|
+
rake guarddog:ci
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 🔒 Security Checkers (12 Total)
|
|
77
|
+
|
|
78
|
+
### Authentication & Authorization
|
|
79
|
+
- **IDOR Detection** — Object access without ownership verification
|
|
80
|
+
- **GraphQL Authorization** — Missing field-level auth checks
|
|
81
|
+
- **Open Redirect** — User input in redirect_to without validation
|
|
82
|
+
- **Rate Limiting Audit** — Missing rack-attack configuration
|
|
83
|
+
|
|
84
|
+
### Injection Attacks
|
|
85
|
+
- **SQL Injection** — String interpolation in queries
|
|
86
|
+
- **XSS (Cross-Site Scripting)** — Unescaped user input in views
|
|
87
|
+
- **AI/LLM Prompt Injection** — User input flowing directly to LLMs (ORIGINAL)
|
|
88
|
+
|
|
89
|
+
### Data Protection
|
|
90
|
+
- **CSRF Protection** — Disabled without documented reason
|
|
91
|
+
- **Mass Assignment** — `permit!` vulnerabilities (FIXES BRAKEMAN BUG)
|
|
92
|
+
- **Hardcoded Secrets** — API keys, tokens, passwords in code (ALWAYS-ON)
|
|
93
|
+
|
|
94
|
+
### Resource Management
|
|
95
|
+
- **DoS/ReDoS** — Unbounded queries, dangerous regex patterns
|
|
96
|
+
- **Supply Chain** — Typosquatted gems using Levenshtein distance (ORIGINAL)
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## 📊 Example Output
|
|
101
|
+
|
|
102
|
+
### Console Report
|
|
103
|
+
```
|
|
104
|
+
====================================================================
|
|
105
|
+
Rails GuardDog Security Report v0.1.0
|
|
106
|
+
====================================================================
|
|
107
|
+
|
|
108
|
+
[CRITICAL] (5 findings)
|
|
109
|
+
Mass Assignment — permit! allows ALL parameters
|
|
110
|
+
app/controllers/users_controller.rb:15
|
|
111
|
+
Fix: Use permit(:name, :email, :age) for specific fields
|
|
112
|
+
|
|
113
|
+
AI Injection — User input in LLM prompt
|
|
114
|
+
app/services/chat_service.rb:42
|
|
115
|
+
Fix: Sanitize: prompt = 'Template: ' + sanitize(params[:text])
|
|
116
|
+
|
|
117
|
+
Hardcoded Secret — API Key detected
|
|
118
|
+
config/initializers/api.rb:3
|
|
119
|
+
Fix: Move to Rails.application.credentials
|
|
120
|
+
|
|
121
|
+
[HIGH] (8 findings)
|
|
122
|
+
DoS: Unbounded query without limit
|
|
123
|
+
app/controllers/posts_controller.rb:5
|
|
124
|
+
Fix: Add .limit(100) or use pagination
|
|
125
|
+
|
|
126
|
+
ReDoS: Dangerous regex pattern
|
|
127
|
+
app/models/validator.rb:22
|
|
128
|
+
Fix: Simplify regex or add timeout
|
|
129
|
+
|
|
130
|
+
====================================================================
|
|
131
|
+
Total findings: 15 | Critical: 5 | High: 8
|
|
132
|
+
====================================================================
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### HTML Report
|
|
136
|
+
- 📊 Interactive dashboard with severity filtering
|
|
137
|
+
- 🎨 Color-coded findings (CRITICAL, HIGH, MEDIUM, LOW)
|
|
138
|
+
- 💡 Inline remediation suggestions
|
|
139
|
+
- 📈 Summary statistics and charts
|
|
140
|
+
|
|
141
|
+
### JSON Report (CI/CD Ready)
|
|
142
|
+
```json
|
|
143
|
+
{
|
|
144
|
+
"timestamp": "2026-06-05T10:30:00Z",
|
|
145
|
+
"total_findings": 15,
|
|
146
|
+
"severity_breakdown": {
|
|
147
|
+
"critical": 5,
|
|
148
|
+
"high": 8,
|
|
149
|
+
"medium": 2,
|
|
150
|
+
"low": 0
|
|
151
|
+
},
|
|
152
|
+
"findings": [...]
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## ⚙️ Configuration
|
|
159
|
+
|
|
160
|
+
Create `config/initializers/guarddog.rb`:
|
|
161
|
+
|
|
162
|
+
```ruby
|
|
163
|
+
# Enable only specific checkers
|
|
164
|
+
Rails.application.config.guarddog.enabled_checkers = %w[
|
|
165
|
+
sql_injection xss csrf mass_assignment secrets
|
|
166
|
+
ai_injection idor dos rate_limit
|
|
167
|
+
]
|
|
168
|
+
|
|
169
|
+
# Fail on severity level (for CI)
|
|
170
|
+
Rails.application.config.guarddog.fail_on_severity = :critical
|
|
171
|
+
|
|
172
|
+
# Strict mode (catch more issues, may have false positives)
|
|
173
|
+
Rails.application.config.guarddog.strict_mode = false
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## 📖 Documentation
|
|
179
|
+
|
|
180
|
+
- **[README](README.md)** - Complete feature overview
|
|
181
|
+
- **[Security Coverage](SECURITY_COVERAGE.md)** - Detailed breakdown of all 12 checkers
|
|
182
|
+
- **[Quick Start](QUICK_START.md)** - Get running in 5 minutes
|
|
183
|
+
- **[Publishing Guide](PUBLISH_GUIDE.md)** - GitHub + RubyGems setup
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## 🔄 CI/CD Integration
|
|
188
|
+
|
|
189
|
+
### GitHub Actions
|
|
190
|
+
```yaml
|
|
191
|
+
name: Security Scan
|
|
192
|
+
|
|
193
|
+
on: [push, pull_request]
|
|
194
|
+
|
|
195
|
+
jobs:
|
|
196
|
+
guarddog:
|
|
197
|
+
runs-on: ubuntu-latest
|
|
198
|
+
steps:
|
|
199
|
+
- uses: actions/checkout@v3
|
|
200
|
+
- uses: ruby/setup-ruby@v1
|
|
201
|
+
with:
|
|
202
|
+
ruby-version: '3.2'
|
|
203
|
+
bundler-cache: true
|
|
204
|
+
- name: Run GuardDog
|
|
205
|
+
run: bundle exec rake guarddog:ci
|
|
206
|
+
- name: Upload report
|
|
207
|
+
if: always()
|
|
208
|
+
uses: actions/upload-artifact@v3
|
|
209
|
+
with:
|
|
210
|
+
name: guarddog-report
|
|
211
|
+
path: guarddog_report.*
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### GitLab CI
|
|
215
|
+
```yaml
|
|
216
|
+
security_scan:
|
|
217
|
+
image: ruby:3.2
|
|
218
|
+
script:
|
|
219
|
+
- bundle install
|
|
220
|
+
- bundle exec rake guarddog:ci
|
|
221
|
+
artifacts:
|
|
222
|
+
paths:
|
|
223
|
+
- guarddog_report.*
|
|
224
|
+
when: always
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## 🔐 Security Checkers Detail
|
|
230
|
+
|
|
231
|
+
### 1. SQL Injection
|
|
232
|
+
```ruby
|
|
233
|
+
# ❌ DETECTED
|
|
234
|
+
User.where("id = #{params[:id]}")
|
|
235
|
+
User.find_by_sql("SELECT * FROM users WHERE id = #{id}")
|
|
236
|
+
|
|
237
|
+
# ✅ SAFE
|
|
238
|
+
User.where('id = ?', params[:id])
|
|
239
|
+
User.where(id: params[:id])
|
|
240
|
+
```
|
|
241
|
+
**CWE:** 89 | **OWASP:** A03:2021
|
|
242
|
+
|
|
243
|
+
### 2. XSS (Cross-Site Scripting)
|
|
244
|
+
```erb
|
|
245
|
+
<!-- ❌ DANGEROUS -->
|
|
246
|
+
<%= @user.bio %>
|
|
247
|
+
|
|
248
|
+
<!-- ✅ SAFE -->
|
|
249
|
+
<%= sanitize @user.bio %>
|
|
250
|
+
```
|
|
251
|
+
**CWE:** 79 | **OWASP:** A07:2021
|
|
252
|
+
|
|
253
|
+
### 3. CSRF (Cross-Site Request Forgery)
|
|
254
|
+
```ruby
|
|
255
|
+
# ❌ CRITICAL (without documented reason)
|
|
256
|
+
skip_before_action :verify_authenticity_token
|
|
257
|
+
|
|
258
|
+
# ✅ DOCUMENTED
|
|
259
|
+
# CSRF disabled for API endpoints
|
|
260
|
+
skip_before_action :verify_authenticity_token, if: :json_request?
|
|
261
|
+
```
|
|
262
|
+
**CWE:** 352 | **OWASP:** A01:2021
|
|
263
|
+
|
|
264
|
+
### 4. Mass Assignment ⭐ (FIXES BRAKEMAN BUG)
|
|
265
|
+
```ruby
|
|
266
|
+
# ❌ CRITICAL
|
|
267
|
+
params.permit!
|
|
268
|
+
|
|
269
|
+
# ✅ SAFE
|
|
270
|
+
params.require(:user).permit(:name, :email, :age)
|
|
271
|
+
```
|
|
272
|
+
**CWE:** 915 | **OWASP:** A01:2021
|
|
273
|
+
|
|
274
|
+
### 5. Hardcoded Secrets ⭐ (FIXES BRAKEMAN BUG #1989)
|
|
275
|
+
```ruby
|
|
276
|
+
# ❌ CRITICAL
|
|
277
|
+
API_KEY = "sk_live_abc123def456"
|
|
278
|
+
|
|
279
|
+
# ✅ SAFE
|
|
280
|
+
ENV['API_KEY']
|
|
281
|
+
Rails.application.credentials.api_key
|
|
282
|
+
```
|
|
283
|
+
**CWE:** 798 | **OWASP:** A02:2021
|
|
284
|
+
|
|
285
|
+
### 6. DoS/ReDoS ⭐ NEW
|
|
286
|
+
```ruby
|
|
287
|
+
# ❌ HIGH RISK
|
|
288
|
+
User.all
|
|
289
|
+
/(a|a)*$/.match?('aaaa')
|
|
290
|
+
|
|
291
|
+
# ✅ SAFE
|
|
292
|
+
User.limit(100)
|
|
293
|
+
/^a+$/.match?('aaaa')
|
|
294
|
+
```
|
|
295
|
+
**CWE:** 400, 1333 | **OWASP:** A05:2021
|
|
296
|
+
|
|
297
|
+
### 7. IDOR ⭐ NEW
|
|
298
|
+
```ruby
|
|
299
|
+
# ❌ CRITICAL
|
|
300
|
+
@post = Post.find(params[:id])
|
|
301
|
+
|
|
302
|
+
# ✅ SAFE
|
|
303
|
+
@post = current_user.posts.find(params[:id])
|
|
304
|
+
authorize @post
|
|
305
|
+
```
|
|
306
|
+
**CWE:** 639 | **OWASP:** A01:2021
|
|
307
|
+
|
|
308
|
+
### 8. AI/LLM Prompt Injection ⭐ ORIGINAL
|
|
309
|
+
```ruby
|
|
310
|
+
# ❌ CRITICAL
|
|
311
|
+
response = client.messages.create(
|
|
312
|
+
messages: [{ role: "user", content: params[:question] }]
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
# ✅ SAFE
|
|
316
|
+
prompt = "Summarize: #{sanitize(params[:text]).first(500)}"
|
|
317
|
+
response = client.messages.create(
|
|
318
|
+
messages: [{ role: "user", content: prompt }]
|
|
319
|
+
)
|
|
320
|
+
```
|
|
321
|
+
**CWE:** 94 | **OWASP:** A03:2025
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
## 🐕 Why "GuardDog"?
|
|
326
|
+
|
|
327
|
+
Like a good guard dog, Rails GuardDog protects your application:
|
|
328
|
+
- 🐾 Watches for intruders (security vulnerabilities)
|
|
329
|
+
- 🚨 Barks when danger is near (alerts on findings)
|
|
330
|
+
- 🛡️ Guards the perimeter (checks entire codebase)
|
|
331
|
+
- 👀 Never sleeps (always-on scanning)
|
|
332
|
+
- 🤝 Works alongside you (integrates with your workflow)
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
336
|
+
## 🤝 Contributing
|
|
337
|
+
|
|
338
|
+
Contributions welcome! Areas for enhancement:
|
|
339
|
+
- Additional security checkers
|
|
340
|
+
- Performance optimizations
|
|
341
|
+
- More language support
|
|
342
|
+
- Advanced AST analysis
|
|
343
|
+
- Machine learning pattern detection
|
|
344
|
+
|
|
345
|
+
[GitHub Issues](https://github.com/sghani001/rails-guarddog/issues)
|
|
346
|
+
[GitHub Discussions](https://github.com/sghani001/rails-guarddog/discussions)
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## 📄 License
|
|
351
|
+
|
|
352
|
+
MIT License - Free to use and modify
|
|
353
|
+
|
|
354
|
+
```
|
|
355
|
+
Copyright (c) 2026 Rails GuardDog Contributors
|
|
356
|
+
|
|
357
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
358
|
+
of this software and associated documentation files (the "Software")...
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## 🔗 Links
|
|
364
|
+
|
|
365
|
+
- **RubyGems:** https://rubygems.org/gems/rails-guarddog
|
|
366
|
+
- **GitHub:** https://github.com/sghani001/rails-guarddog
|
|
367
|
+
- **Issues:** https://github.com/sghani001/rails-guarddog/issues
|
|
368
|
+
- **Changelog:** https://github.com/sghani001/rails-guarddog/releases
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
## 👋 Support
|
|
373
|
+
|
|
374
|
+
- 📖 [Full Documentation](README.md)
|
|
375
|
+
- 🚀 [Quick Start Guide](QUICK_START.md)
|
|
376
|
+
- 🔒 [Security Details](SECURITY_COVERAGE.md)
|
|
377
|
+
- 💬 [GitHub Discussions](https://github.com/sghani001/rails-guarddog/discussions)
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
**v0.1.0** | **Production Ready** | **MIT License** | ⭐ [Star on GitHub](https://github.com/sghani001/rails-guarddog)
|
|
382
|
+
|
|
383
|
+
*Beyond brakeman. Detect what others miss.* 🐕🔒
|
|
@@ -6,7 +6,7 @@ module Rails
|
|
|
6
6
|
glob_files('app/**/*.rb').each do |file|
|
|
7
7
|
content = File.read(file)
|
|
8
8
|
content.each_line.with_index do |line, idx|
|
|
9
|
-
if line.match?(/\.where\s*\(\s*['"]
|
|
9
|
+
if line.match?(/\.where\s*\(\s*['"].*#\{/) || line.match?(/\.find_by_sql\s*\(/)
|
|
10
10
|
add_finding(
|
|
11
11
|
severity: :high,
|
|
12
12
|
message: "Potential SQL injection: using string interpolation in queries",
|