Security - v1.0.3
Security Guidelines
This guide provides comprehensive security best practices for using the ArtisanPack UI Security package effectively to protect your Laravel applications against common web vulnerabilities.
Core Security Principles
1. Input Validation and Sanitization
Always validate and sanitize data received from users or external sources:
// Validate before sanitizing
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
$cleanEmail = sanitizeEmail($email);
} else {
// Handle invalid email
throw new InvalidArgumentException('Invalid email format');
}
// Sanitize all user input
$userData = [
'name' => sanitizeText($_POST['name']),
'email' => sanitizeEmail($_POST['email']),
'age' => sanitizeInt($_POST['age']),
'bio' => sanitizeText($_POST['bio'])
];
2. Output Escaping
Always escape data before rendering it in different contexts:
// HTML context
echo escHtml($userContent);
// HTML attribute context
echo '<img alt="' . escAttr($userTitle) . '">';
// URL context
echo '<a href="' . escUrl($userUrl) . '">Link</a>';
// JavaScript context
echo '<script>var data = ' . escJs($jsonData) . ';</script>';
// CSS context
echo '<style>.class { content: ' . escCss($userContent) . '; }</style>';
Vulnerability Prevention
Cross-Site Scripting (XSS) Prevention
XSS attacks occur when malicious scripts are injected into web pages. Use appropriate escaping functions:
// Prevent XSS in HTML content
$safeContent = escHtml($userContent);
// Prevent XSS in HTML attributes
$safeAttribute = escAttr($userAttribute);
// For rich content that needs some HTML, use kses
$safeHtml = kses($userHtml);
Bad:
echo '<div>' . $userInput . '</div>'; // Vulnerable to XSS
Good:
echo '<div>' . escHtml($userInput) . '</div>'; // Safe from XSS
SQL Injection Prevention
While this package doesn't directly handle database queries, proper input sanitization helps:
// Sanitize before database operations
$userId = sanitizeInt($_GET['id']);
$userName = sanitizeText($_POST['name']);
// Use with Laravel's query builder or Eloquent (which uses parameterized queries)
User::where('id', $userId)->where('name', $userName)->first();
CSRF Protection
Always include CSRF protection in forms when handling user input:
<form method="POST" action="/user/update">
@csrf
<input type="text" name="name" value="{{ escAttr($user->name) }}">
<textarea name="bio">{{ escHtml($user->bio) }}</textarea>
<button type="submit">Update</button>
</form>
Context-Specific Security
Database Context
// Sanitize before storing
$user = new User();
$user->name = sanitizeText($request->name);
$user->email = sanitizeEmail($request->email);
$user->age = sanitizeInt($request->age);
$user->save();
File Handling Context
// Sanitize filenames before file operations
$filename = sanitizeFilename($uploadedFile->getClientOriginalName());
$path = storage_path('uploads/' . $filename);
// Additional file security checks
if (!in_array($uploadedFile->getClientMimeType(), ['image/jpeg', 'image/png'])) {
throw new InvalidArgumentException('Invalid file type');
}
API Responses
// Sanitize data before JSON responses
$responseData = [
'user' => [
'name' => sanitizeText($user->name),
'email' => sanitizeEmail($user->email),
'bio' => sanitizeText($user->bio)
]
];
return response()->json($responseData);
Advanced Security Practices
Defense in Depth
Layer multiple security measures:
class UserController extends Controller
{
public function store(Request $request)
{
// 1. Validate input structure
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|max:255|unique:users',
'bio' => 'nullable|string|max:1000'
]);
// 2. Sanitize input
$userData = [
'name' => sanitizeText($request->name),
'email' => sanitizeEmail($request->email),
'bio' => sanitizeText($request->bio)
];
// 3. Create user with sanitized data
$user = User::create($userData);
// 4. Escape output
return view('user.profile', [
'name' => escHtml($user->name),
'email' => escHtml($user->email),
'bio' => escHtml($user->bio)
]);
}
}
Content Security Policy (CSP)
Implement CSP headers alongside output escaping:
// In your middleware or controller
header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'");
HTML Filtering Best Practices
When using kses() for rich content:
// Allow only safe HTML tags
$allowedTags = [
'p' => [],
'br' => [],
'strong' => [],
'em' => [],
'ul' => [],
'ol' => [],
'li' => []
];
$safeContent = kses($userContent, $allowedTags);
Common Security Mistakes
❌ Don't Do This
// Never trust user input directly
echo $_POST['content']; // Vulnerable to XSS
// Don't escape already escaped content
echo escHtml(escHtml($content)); // Double escaping
// Don't use wrong escaping context
echo '<script>var data = "' . escHtml($data) . '";</script>'; // Should use escJs
// Don't sanitize display data
$displayName = sanitizeText($user->name); // Only sanitize on input
✅ Do This Instead
// Always escape output appropriately
echo escHtml($_POST['content']);
// Escape once, in the right context
echo escHtml($content);
// Use correct escaping for context
echo '<script>var data = ' . escJs($data) . ';</script>';
// Sanitize on input, escape on output
// Input: sanitizeText() -> Store in DB
// Output: escHtml() -> Display to user
Security Checklist
Input Handling
- Validate all user input with Laravel validation rules
- Sanitize input before storing in database
- Use appropriate sanitization function for data type
- Implement rate limiting for forms
Output Handling
- Escape all output with appropriate function
- Use
escHtml()for HTML content - Use
escAttr()for HTML attributes - Use
escUrl()for URLs - Use
escJs()for JavaScript contexts - Use
escCss()for CSS contexts
General Security
- Include CSRF protection on all forms
- Implement Content Security Policy
- Use HTTPS in production
- Keep dependencies updated
- Implement proper error handling
- Log security-related events
Testing Security
Always test your security implementations:
// Test XSS prevention
$maliciousInput = '<script>alert("XSS")</script>';
$safeOutput = escHtml($maliciousInput);
assert($safeOutput === '<script>alert("XSS")</script>');
// Test input sanitization
$dirtyEmail = '<script>bad@email.com';
$cleanEmail = sanitizeEmail($dirtyEmail);
assert($cleanEmail === 'bad@email.com');
Emergency Response
If you discover a security vulnerability:
- Don't panic - Document the issue carefully
- Assess impact - Determine affected systems and data
- Apply immediate fixes - Use security functions to patch
- Monitor logs - Check for exploitation attempts
- Update documentation - Record lessons learned
Additional Resources
For AI-specific security guidelines, see AI Guidelines.