CRITICAL fixes: - Mask SNMP community string in agent channel logs (CRITICAL-1) - Remove snmpv3 passwords from REST API responses, return _set booleans (CRITICAL-2) - Replace snmp_community with snmp_community_set in GraphQL type (CRITICAL-3) HIGH fixes: - Fix cookie same_site from invalid 'Towerops' to 'Lax' (HIGH-4) - Remove unsafe-eval from CSP script-src (HIGH-6) - Block GraphQL introspection queries in production (HIGH-7) - Sanitize LIKE wildcards in SNMP device name search (HIGH-8) - Reject webhooks when no secret configured instead of accepting (HIGH-9) MEDIUM fixes: - Hash mobile session tokens (SHA-256) before DB storage (MEDIUM-10) - Apply security headers in all environments, not just prod (MEDIUM-14) - Add GraphQL query complexity limit (500) in production (MEDIUM-16) - Fix X-Frame-Options to DENY to match frame-ancestors 'none' (MEDIUM-13)
32 lines
893 B
Elixir
32 lines
893 B
Elixir
defmodule ToweropsWeb.Plugs.GraphQLIntrospection do
|
|
@moduledoc """
|
|
Blocks GraphQL introspection queries in production.
|
|
|
|
Introspection exposes the full schema to API consumers. This is useful
|
|
in development but should be disabled in production to reduce attack surface.
|
|
"""
|
|
import Plug.Conn
|
|
|
|
def init(opts), do: opts
|
|
|
|
def call(conn, _opts) do
|
|
if Application.get_env(:towerops, :env) == :prod and introspection_query?(conn) do
|
|
conn
|
|
|> put_resp_content_type("application/json")
|
|
|> send_resp(400, Jason.encode!(%{errors: [%{message: "Introspection is disabled"}]}))
|
|
|> halt()
|
|
else
|
|
conn
|
|
end
|
|
end
|
|
|
|
defp introspection_query?(conn) do
|
|
case conn.body_params do
|
|
%{"query" => query} when is_binary(query) ->
|
|
String.contains?(query, "__schema") or String.contains?(query, "__type")
|
|
|
|
_ ->
|
|
false
|
|
end
|
|
end
|
|
end
|