This document outlines the security measures implemented in the static calendar component to prevent code injection vulnerabilities.
Never use complete function declarations in callback options:
# π¨ DANGEROUS - Code injection vulnerability
<.static_calendar
id="calendar"
events={@events}
options={%{
eventClick: "function(info) { eval('malicious code'); }"
}}
/>This approach is completely blocked in the current implementation to prevent JavaScript code injection attacks.
Safest approach - Define functions in separate JavaScript files:
// In your app.js
window.MyApp = {
Calendar: {
handleEventClick(info) {
console.log('Safe event handling:', info.event.title);
}
}
};# In your Elixir template
<.static_calendar
id="calendar"
events={@events}
options={%{
eventClick: "MyApp.Calendar.handleEventClick"
}}
/>For very simple cases only, with strict security restrictions:
# β
SAFE - Simple expression, under 200 chars
<.static_calendar
id="calendar"
events={@events}
options={%{
eventClick: "console.log('Event:', info.event.title)"
}}
/>-
Dangerous Keyword Detection:
function,eval,setTimeout,setIntervalnew Function,constructor,__proto__,prototype
-
Content Length Limits:
- Function body strings limited to 200 characters
- Prevents complex malicious code injection
-
Function Name Validation:
- Global function references use regex validation
- Only allows valid JavaScript identifier names
-
Error Logging:
- All security violations are logged to console
- Clear error messages for debugging
// These are automatically blocked by the security system:
"eval('alert(1)')" // β Contains 'eval'
"setTimeout(() => hack(), 1000)" // β Contains 'setTimeout'
"function() { return 'blocked'; }" // β Contains 'function'
"new Function('return alert(1)')()" // β Contains 'new Function'
"a".repeat(300) // β Exceeds 200 char limit-
Use Global Function References:
options: %{eventClick: "MyApp.handleEvent"}
-
Keep JavaScript in .js Files:
// calendar-handlers.js window.CalendarHandlers = { onEventClick(info) { /* complex logic here */ } };
-
Validate User Input:
# In your controller/context def build_calendar_options(user_preferences) do %{ view: sanitize_view(user_preferences.view), eventClick: "MyApp.handleEvent" # Always hardcoded, never from user input } end
-
Never Pass User Input to Callbacks:
# π¨ DANGEROUS - User input could contain malicious code options: %{eventClick: user_provided_callback}
-
Don't Use Complex Strings:
# π¨ BAD - Complex logic should be in JS files options: %{eventClick: "if(confirm('Delete?')){fetch('/delete/'+info.event.id)}"}
-
Don't Bypass Security:
# π¨ DON'T try to work around the security measures # Use proper global function references instead
The library includes comprehensive security tests:
# Security measures are tested to ensure they work
test "rejects dangerous function strings for security" do
# Verifies that dangerous keywords are rejected
# Confirms length limits are enforced
# Validates function name restrictions
endIf you have existing code using function strings, migrate as follows:
<.static_calendar
options={%{
eventClick: "function(info) { showModal(info.event); }"
}}
/>- Move to JavaScript file:
window.MyCalendar = {
showEventModal(info) {
showModal(info.event);
}
};- Reference by name:
<.static_calendar
options={%{
eventClick: "MyCalendar.showEventModal"
}}
/>If you discover a security vulnerability in the calendar component:
- Do NOT open a public issue
- Contact the maintainers directly
- Provide detailed reproduction steps
- Allow time for patching before disclosure
Remember: Security is everyone's responsibility. Always prefer explicit, separated JavaScript functions over inline string-based code.