Skip to main content

Security Model

Gaivota plugins run in a secure Lua sandbox that prevents malicious code from accessing your system.

Sandbox Constraints

Resource Limits

ProtectionLimitPurpose
Memory10 MBPrevents memory exhaustion
Timeout5 secondsPrevents infinite loops
Instructions1,000,000Prevents 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:

APIReason
os.*No system access (files, env vars, processes)
io.*No file I/O operations
debug.*No debugging/introspection
loadfileCannot load files from disk
dofileCannot execute files from disk
requireCannot load external modules
package.*No package system access
collectgarbageNo GC manipulation
rawget, rawset, rawequalNo 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:

  1. Fresh Lua state - No data persists between filter/render calls
  2. No shared state - Plugins cannot communicate with each other
  3. Read-only email data - Plugins cannot modify emails
  4. 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("<", "&lt;"):gsub(">", "&gt;")
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:

  1. Do not create a public issue
  2. Email security concerns to the maintainers
  3. Provide details about the vulnerability
  4. Allow time for a fix before disclosure

Plugin Review

Before installing third-party plugins:

  1. Read the source code - Plugins are plain Lua files
  2. Check the author - Prefer plugins from known sources
  3. Test in isolation - Try with a test account first
  4. 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.