Security Model
Gaivota plugins run in a secure Lua sandbox that prevents malicious code from accessing your system.
Sandbox Constraints
Resource Limits
| Protection | Limit | Purpose |
|---|---|---|
| Memory | 10 MB | Prevents memory exhaustion |
| Timeout | 5 seconds | Prevents infinite loops |
| Instructions | 1,000,000 | Prevents CPU exhaustion |
If a plugin exceeds these limits, execution is terminated and an error is logged.
Blocked Lua APIs
The following Lua standard library functions are removed for security:
| API | Reason |
|---|---|
os.* | No system access (files, env vars, processes) |
io.* | No file I/O operations |
debug.* | No debugging/introspection |
loadfile | Cannot load files from disk |
dofile | Cannot execute files from disk |
require | Cannot load external modules |
package.* | No package system access |
collectgarbage | No GC manipulation |
rawget, rawset, rawequal | No metatable bypassing |
Available APIs
Plugins have access to:
-- String manipulation
string.match, string.sub, string.gsub, string.lower, string.upper,
string.find, string.format, string.len, string.rep, string.reverse
-- Table operations
table.insert, table.remove, table.concat, table.sort
-- Math functions
math.floor, math.ceil, math.abs, math.min, math.max,
math.random, math.sqrt, math.sin, math.cos
-- Basic functions
type, tostring, tonumber, pairs, ipairs, next,
select, unpack, print, error, assert, pcall
What Plugins CAN Do
- Read email metadata (subject, sender, recipients, etc.)
- Read extracted URL metadata (title, description, image)
- Generate HTML for display
- Use pattern matching on email content
- Perform calculations and transformations
What Plugins CANNOT Do
- Access the filesystem
- Make network requests
- Access environment variables
- Execute system commands
- Modify other emails
- Access other plugins' data
- Persist data between executions
- Access Gaivota internals
Plugin Isolation
Each plugin execution is isolated:
- Fresh Lua state - No data persists between filter/render calls
- No shared state - Plugins cannot communicate with each other
- Read-only email data - Plugins cannot modify emails
- Sandboxed output - HTML is sanitized before display
HTML Sanitization
The HTML returned by render() is sanitized using DOMPurify before display:
Allowed Elements
div, span, p, h1-h6, a, img, ul, ol, li,
table, tr, td, th, thead, tbody,
strong, em, b, i, u, br, hr
Allowed Attributes
class, style, src, href, alt, title,
data-action, data-url (for plugin actions)
Blocked Content
- JavaScript (
<script>,onclick, etc.) - External resources (except images)
- Iframes
- Forms
- Object/embed elements
Best Practices
1. Validate Input
Don't assume email data is well-formed:
function filter(email, user_email)
local subject = email:subject()
if not subject then
return false -- Handle missing subject
end
return subject:match("important")
end
2. Escape User Content
When building HTML, be careful with user data:
-- Potentially dangerous: Raw email content in HTML
local html = "<div>" .. email:subject() .. "</div>"
-- Safer: Content will be sanitized anyway, but be mindful
local subject = email:subject() or ""
-- Replace < and > to prevent HTML injection
subject = subject:gsub("<", "<"):gsub(">", ">")
local html = "<div>" .. subject .. "</div>"
3. Handle Errors Gracefully
Use pcall for potentially failing operations:
function filter(email, user_email)
local ok, result = pcall(function()
-- Complex logic that might fail
return email:subject():match("pattern")
end)
if not ok then
print("Filter error: " .. tostring(result))
return false
end
return result
end
4. Avoid Resource-Intensive Operations
Keep plugins lightweight:
-- Bad: Creating huge strings
local html = ""
for i = 1, 100000 do
html = html .. "<div>" .. i .. "</div>"
end
-- Better: Use table.concat
local parts = {}
for i = 1, 1000 do
parts[#parts + 1] = "<div>" .. i .. "</div>"
end
local html = table.concat(parts)
Reporting Security Issues
If you discover a security vulnerability in the plugin system, please report it responsibly:
- Do not create a public issue
- Email security concerns to the maintainers
- Provide details about the vulnerability
- Allow time for a fix before disclosure
Plugin Review
Before installing third-party plugins:
- Read the source code - Plugins are plain Lua files
- Check the author - Prefer plugins from known sources
- Test in isolation - Try with a test account first
- Review permissions - Understand what the plugin does
Remember: Only install plugins you trust. While the sandbox prevents system access, malicious plugins could still display misleading content or leak email metadata through rendered HTML.