19 KiB
Executable File
name, version, description, author, license, tags, compatibility, requirements, environment_variables, parameters, outputs, metadata
| name | version | description | author | license | tags | compatibility | requirements | environment_variables | parameters | outputs | metadata | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| security-scan-gorm | 1.0.0 | Detect GORM security issues including ID leaks, exposed secrets, and common GORM misconfigurations. Use when asked to validate GORM models, check for ID exposure vulnerabilities, scan for API key leaks, verify database security patterns, or ensure GORM best practices compliance. Detects numeric ID exposure (json:id on uint/int fields), exposed API keys/secrets, DTO embedding issues, missing primary key tags, and foreign key indexing problems. | Charon Project | MIT |
|
|
|
|
|
|
|
GORM Security Scanner
Overview
The GORM Security Scanner is a static analysis tool that automatically detects GORM security issues and common mistakes in Go codebases. It focuses on preventing ID leak vulnerabilities (IDOR attacks), detecting exposed secrets, and enforcing GORM best practices.
This skill is essential for maintaining secure database models and preventing information disclosure vulnerabilities before they reach production.
When to Use This Skill
Use this skill when:
- ✅ Creating or modifying GORM database models
- ✅ Reviewing code for security issues before commit
- ✅ Validating API response DTOs for ID exposure
- ✅ Checking for exposed API keys, tokens, or passwords
- ✅ Auditing codebase for GORM best practices compliance
- ✅ Running pre-commit security checks
- ✅ Performing security audits in CI/CD pipelines
Prerequisites
- Bash 4.0 or higher
- GNU grep (standard on Linux/macOS)
- Read permissions for backend directory
- Project must have Go code with GORM models
Security Issues Detected
🔴 CRITICAL: Numeric ID Exposure
What: GORM models with uint/int primary keys that have json:"id" tags
Risk: Information disclosure, IDOR vulnerability, database enumeration
Example:
// ❌ BAD: Internal database ID exposed
type User struct {
ID uint `json:"id" gorm:"primaryKey"` // CRITICAL ISSUE
UUID string `json:"uuid"`
}
// ✅ GOOD: ID hidden, UUID exposed
type User struct {
ID uint `json:"-" gorm:"primaryKey"`
UUID string `json:"uuid" gorm:"uniqueIndex"`
}
Note: String-based IDs are allowed (assumed to be UUIDs/opaque identifiers)
🔴 CRITICAL: Exposed API Keys/Secrets
What: Fields with sensitive names (APIKey, Secret, Token, Password) that have visible JSON tags
Risk: Credential exposure, unauthorized access
Example:
// ❌ BAD: API key visible in responses
type User struct {
APIKey string `json:"api_key"` // CRITICAL ISSUE
}
// ✅ GOOD: API key hidden
type User struct {
APIKey string `json:"-"`
}
🟡 HIGH: Response DTO Embedding Models
What: Response structs that embed GORM models, inheriting exposed ID fields
Risk: Unintentional ID exposure through embedding
Example:
// ❌ BAD: Inherits exposed ID from models.ProxyHost
type ProxyHostResponse struct {
models.ProxyHost // HIGH ISSUE
Warnings []string `json:"warnings"`
}
// ✅ GOOD: Explicitly define fields
type ProxyHostResponse struct {
UUID string `json:"uuid"`
Name string `json:"name"`
DomainNames string `json:"domain_names"`
Warnings []string `json:"warnings"`
}
🔵 MEDIUM: Missing Primary Key Tag
What: ID fields with GORM tags but missing primaryKey directive
Risk: GORM may not recognize field as primary key, causing indexing issues
🟢 INFO: Missing Foreign Key Index
What: Foreign key fields (ending with ID) without index tags
Impact: Query performance degradation
Suggestion: Add gorm:"index" for better performance
Usage
Via VS Code Task (Recommended for Development)
- Open Command Palette (
Cmd/Ctrl+Shift+P) - Select "Tasks: Run Task"
- Choose "Lint: GORM Security Scan"
- View results in dedicated output panel
Via Script Runner
# Report mode - Show all issues, always exits 0
.github/skills/scripts/skill-runner.sh security-scan-gorm
# Report mode with file output
.github/skills/scripts/skill-runner.sh security-scan-gorm --report docs/reports/gorm-scan.txt
# Check mode - Exit 1 if issues found (for CI/pre-commit)
.github/skills/scripts/skill-runner.sh security-scan-gorm --check
# Check mode with file output (for CI artifacts)
.github/skills/scripts/skill-runner.sh security-scan-gorm --check docs/reports/gorm-scan-ci.txt
# Enforce mode - Same as check (future: stricter rules)
.github/skills/scripts/skill-runner.sh security-scan-gorm --enforce
Via Pre-commit Hook (Manual Stage)
# Run manually on all files
pre-commit run --hook-stage manual gorm-security-scan --all-files
# Run on staged files
pre-commit run --hook-stage manual gorm-security-scan
Direct Script Execution
# Report mode
./scripts/scan-gorm-security.sh --report
# Check mode (exits 1 if issues found)
./scripts/scan-gorm-security.sh --check
# Verbose mode
VERBOSE=1 ./scripts/scan-gorm-security.sh --report
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| mode | string | No | --report | Operating mode (--report, --check, --enforce) |
| output_file | string | No | (stdout) | Path to save report file (e.g., docs/reports/gorm-scan.txt) |
Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
| VERBOSE | No | 0 | Enable verbose debug output (set to 1) |
Outputs
Exit Codes
- 0: Success (report mode) or no issues (check/enforce mode)
- 1: Issues found (check/enforce mode)
- 2: Invalid arguments
- 3: File system error
Output Format
🔍 GORM Security Scanner v1.0.0
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📂 Scanning: backend/
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔴 CRITICAL: ID Field Exposed in JSON
📄 File: backend/internal/models/user.go:23
🏗️ Struct: User
💡 Fix: Change json:"id" to json:"-" and use UUID for external references
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 SUMMARY
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Scanned: 40 Go files (2,031 lines)
Duration: 2.1 seconds
🔴 CRITICAL: 3 issues
🟡 HIGH: 2 issues
🔵 MEDIUM: 0 issues
🟢 INFO: 5 suggestions
Total Issues: 5 (excluding informational)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
❌ FAILED: 5 security issues detected
Detection Patterns
Pattern 1: ID Leak Detection
Target: GORM models with numeric IDs exposed in JSON
Detection Logic:
- Find
type XXX structdeclarations - Apply GORM model detection heuristics:
- File in
internal/models/directory, OR - Struct has 2+ fields with
gorm:tags, OR - Struct embeds
gorm.Model
- File in
- Check for
IDfield with numeric type (uint,int,int64, etc.) - Check for
json:"id"tag (notjson:"-") - Flag as CRITICAL
String ID Policy: String-based IDs are NOT flagged (assumed to be UUIDs)
Pattern 2: DTO Embedding
Target: Response/DTO structs that embed GORM models
Detection Logic:
- Find structs with "Response" or "DTO" in name
- Look for embedded model types (from
modelspackage) - Check if embedded model has exposed ID field
- Flag as HIGH
Pattern 3: Exposed Secrets
Target: API keys, tokens, passwords, secrets with visible JSON tags
Detection Logic:
- Find fields matching:
APIKey,Secret,Token,Password,Hash - Check if JSON tag is NOT
json:"-" - Flag as CRITICAL
Pattern 4: Missing Primary Key Tag
Target: ID fields without gorm:"primaryKey"
Detection Logic:
- Find ID fields with GORM tags
- Check if
primaryKeydirective is missing - Flag as MEDIUM
Pattern 5: Missing Foreign Key Index
Target: Foreign key fields without index tags
Detection Logic:
- Find fields ending with
IDorId - Check if GORM tag lacks
indexdirective - Flag as INFO
Pattern 6: Missing UUID Fields
Target: Models with exposed IDs but no external identifier
Detection Logic:
- Find models with exposed
json:"id" - Check if
UUIDfield exists - Flag as HIGH if missing
Suppression Mechanism
Use inline comments to suppress false positives:
Comment Format
// gorm-scanner:ignore [optional reason]
Examples
External API Response:
// gorm-scanner:ignore External API response, not a GORM model
type GitHubUser struct {
ID int `json:"id"` // Won't be flagged
}
Legacy Code During Migration:
// gorm-scanner:ignore Legacy model, scheduled for refactor in #1234
type OldModel struct {
ID uint `json:"id" gorm:"primaryKey"`
}
Internal Service (Never Serialized):
// gorm-scanner:ignore Internal service struct, never serialized to HTTP
type InternalProcessorState struct {
ID uint `json:"id"`
}
GORM Model Detection Heuristics
The scanner uses three heuristics to identify GORM models (prevents false positives):
- Location-based: File is in
internal/models/directory - Tag-based: Struct has 2+ fields with
gorm:tags - Embedding-based: Struct embeds
gorm.Model
Non-GORM structs are ignored:
- Docker container info structs
- External API response structs
- WebSocket connection tracking
- Manual challenge structs
Performance Metrics
Measured Performance:
- Execution Time: 2.1 seconds (average)
- Target: <5 seconds per full scan
- Performance Rating: ✅ Excellent (58% faster than requirement)
- Files Scanned: 40 Go files
- Lines Processed: 2,031 lines
Examples
Example 1: Development Workflow
# Before committing changes to GORM models
.github/skills/scripts/skill-runner.sh security-scan-gorm
# Save report for later review
.github/skills/scripts/skill-runner.sh security-scan-gorm --report docs/reports/gorm-scan-$(date +%Y%m%d).txt
# If issues found, fix them
# Re-run to verify fixes
Example 2: CI/CD Pipeline
# GitHub Actions workflow
- name: GORM Security Scanner
run: .github/skills/scripts/skill-runner.sh security-scan-gorm --check docs/reports/gorm-scan-ci.txt
continue-on-error: false
- name: Upload GORM Scan Report
if: always()
uses: actions/upload-artifact@v4
with:
name: gorm-security-report
path: docs/reports/gorm-scan-ci.txt
retention-days: 30
Example 3: Pre-commit Hook
# Manual invocation
pre-commit run --hook-stage manual gorm-security-scan --all-files
# After remediation, move to blocking stage
# Edit .pre-commit-config.yaml:
# stages: [commit] # Change from [manual]
Example 4: Verbose Mode for Debugging
# Enable debug output
VERBOSE=1 ./scripts/scan-gorm-security.sh --report
# Shows:
# - File scanning progress
# - GORM model detection decisions
# - Suppression comment handling
# - Pattern matching logic
Error Handling
Common Issues
Scanner not found:
Error: ./scripts/scan-gorm-security.sh not found
Solution: Ensure script has execute permissions: chmod +x scripts/scan-gorm-security.sh
Permission denied:
Error: Permission denied: backend/internal/models/user.go
Solution: Check file permissions and current user access
No Go files found:
Warning: No Go files found in backend/
Solution: Verify you're running from project root
False positive on valid code:
Solution: Add suppression comment: // gorm-scanner:ignore [reason]
Troubleshooting
Issue: Scanner reports false positives
Cause: Non-GORM struct incorrectly flagged
Solution:
- Add suppression comment with reason
- Verify struct doesn't match GORM heuristics
- Report as enhancement if pattern needs refinement
Issue: Scanner misses known issues
Cause: Custom MarshalJSON implementation or XML/YAML tags
Solution:
- Manual code review for custom marshaling
- Check for
xml:oryaml:tags (not yet supported) - See "Known Limitations" section
Issue: Scanner runs slowly
Cause: Large codebase or slow filesystem
Solution:
- Run on specific directory:
cd backend && ../scripts/scan-gorm-security.sh - Use incremental scanning in pre-commit (only changed files)
- Check filesystem performance
Known Limitations
-
Custom MarshalJSON Not Detected
- Scanner can't detect ID leaks in custom JSON marshaling logic
- Mitigation: Manual code review
-
XML and YAML Tags Not Checked
- Only
json:tags are scanned currently - Future: Pattern 7 (XML) and Pattern 8 (YAML)
- Only
-
Multi-line Tag Handling
- Tags split across lines may not be detected
- Enforce single-line tags in style guide
-
Interface Implementations
- Models returned through interfaces may bypass detection
- Future: Type-based analysis
-
Map Conversions and Reflection
- Runtime conversions not analyzed
- Mitigation: Code review, runtime monitoring
Security Thresholds
Project Standards:
- 🔴 CRITICAL: Must fix immediately (blocking)
- 🟡 HIGH: Should fix before PR merge (warning)
- 🔵 MEDIUM: Fix in current sprint (informational)
- 🟢 INFO: Optimize when convenient (suggestion)
Integration Points
- Pre-commit: Manual stage (soft launch), move to commit stage after remediation
- VS Code: Command Palette → "Lint: GORM Security Scan"
- CI/CD: GitHub Actions quality-checks workflow
- Definition of Done: Required check before task completion
Related Skills
- security-scan-trivy - Container vulnerability scanning
- security-scan-codeql - Static analysis for Go/JS
- qa-lefthook-all - Lefthook pre-commit-phase quality checks
Best Practices
- Run Before Every Commit: Catch issues early in development
- Fix Critical Issues Immediately: Don't ignore CRITICAL/HIGH findings
- Document Suppressions: Always explain why an issue is suppressed
- Review Periodically: Audit suppression comments quarterly
- Integrate in CI: Prevent regressions from reaching production
- Use UUIDs for External IDs: Never expose internal database IDs
- Hide Sensitive Fields: All API keys, tokens, passwords should have
json:"-" - Save Reports for Audit: Export scan results to
docs/reports/for tracking and compliance - Track Progress: Compare reports over time to verify issue remediation
Remediation Guidance
Fix ID Leak
// Before
type User struct {
ID uint `json:"id" gorm:"primaryKey"`
UUID string `json:"uuid"`
}
// After
type User struct {
ID uint `json:"-" gorm:"primaryKey"` // Hidden
UUID string `json:"uuid" gorm:"uniqueIndex"` // Exposed
}
// Update API clients to use UUID instead of ID
Fix Exposed Secret
// Before
type User struct {
APIKey string `json:"api_key"`
}
// After
type User struct {
APIKey string `json:"-"` // Never expose credentials
}
Fix DTO Embedding
// Before
type ProxyHostResponse struct {
models.ProxyHost // Inherits exposed ID
Warnings []string `json:"warnings"`
}
// After
type ProxyHostResponse struct {
UUID string `json:"uuid"` // Explicit fields only
Name string `json:"name"`
DomainNames string `json:"domain_names"`
Warnings []string `json:"warnings"`
}
Report Files
Recommended Locations:
- Development:
docs/reports/gorm-scan-YYYYMMDD.txt(dated reports) - CI/CD:
docs/reports/gorm-scan-ci.txt(uploaded as artifact) - Pre-Release:
docs/reports/gorm-scan-release.txt(audit trail)
Report Format:
- Plain text with ANSI color codes (terminal-friendly)
- Includes severity breakdown and summary metrics
- Contains file:line references for all issues
- Provides remediation guidance for each finding
Agent Usage: AI agents can read saved reports instead of parsing terminal output:
# Generate report
.github/skills/scripts/skill-runner.sh security-scan-gorm --report docs/reports/gorm-scan.txt
# Agent reads report
# File contains structured findings with severity, location, and fixes
Documentation
Specification: docs/plans/gorm_security_scanner_spec.md
Implementation: docs/implementation/gorm_security_scanner_complete.md
QA Report: docs/reports/gorm_scanner_qa_report.md
Scan Reports: docs/reports/gorm-scan-*.txt (generated by skill)
Security References
- OWASP API Security Top 10
- OWASP Direct Object Reference (IDOR)
- CWE-639: Authorization Bypass Through User-Controlled Key
- GORM Documentation
Last Updated: 2026-01-28 Status: ✅ Production Ready Maintained by: Charon Project Source: scripts/scan-gorm-security.sh