From elixir-phoenix
Enforces Elixir/Phoenix security patterns for auth, OAuth, sessions, CSRF, XSS, SQL injection, input validation, and secrets. Activates when editing auth files, login flows, RBAC, or API keys.
npx claudepluginhub oliver-kriska/claude-elixir-phoenix --plugin elixir-phoenixThis skill uses the workspace's default tool permissions.
Quick reference for security patterns in Elixir/Phoenix.
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
Quick reference for security patterns in Elixir/Phoenix.
^ operator, never string interpolationto_existing_atom/1raw/1 with untrusted contentruntime.exs from env varsdef authenticate(email, password) do
user = Repo.get_by(User, email: email)
cond do
user && Argon2.verify_pass(password, user.hashed_password) ->
{:ok, user}
user ->
{:error, :invalid_credentials}
true ->
Argon2.no_user_verify() # Timing attack prevention
{:error, :invalid_credentials}
end
end
# RE-AUTHORIZE IN EVERY EVENT HANDLER
def handle_event("delete", %{"id" => id}, socket) do
post = Blog.get_post!(id)
# Don't trust that mount authorized this action!
with :ok <- Bodyguard.permit(Blog, :delete_post, socket.assigns.current_user, post) do
Blog.delete_post(post)
{:noreply, stream_delete(socket, :posts, post)}
else
_ -> {:noreply, put_flash(socket, :error, "Unauthorized")}
end
end
# ✅ SAFE: Parameterized queries
from(u in User, where: u.name == ^user_input)
# ❌ VULNERABLE: String interpolation
from(u in User, where: fragment("name = '#{user_input}'"))
Path.safe_relative/2 for traversalString.to_existing_atom/1 only<%= %>)raw/1 with untrusted content| Wrong | Right |
|---|---|
"SELECT * FROM users WHERE name = '#{name}'" | from(u in User, where: u.name == ^name) |
String.to_atom(user_input) | String.to_existing_atom(user_input) |
<%= raw @user_comment %> | <%= @user_comment %> |
| Hardcoded secrets in config | runtime.exs from env vars |
| Auth only in mount | Re-auth in every handle_event |
For detailed patterns, see:
${CLAUDE_SKILL_DIR}/references/authentication.md - phx.gen.auth, MFA, sessions${CLAUDE_SKILL_DIR}/references/authorization.md - Bodyguard, scopes, LiveView auth${CLAUDE_SKILL_DIR}/references/input-validation.md - Changesets, file uploads, paths${CLAUDE_SKILL_DIR}/references/security-headers.md - CSP, CSRF, rate limiting, headers${CLAUDE_SKILL_DIR}/references/oauth-linking.md - OAuth account linking, token management${CLAUDE_SKILL_DIR}/references/rate-limiting.md - Composite key strategies, Hammer patterns${CLAUDE_SKILL_DIR}/references/advanced-patterns.md - SSRF prevention, secrets management, supply chain