findings public record

atomine-elektrine/elektrine

Elektrine is a modular platform for operators who want to run internet services under their own control.

https://github.com/atomine-elektrine/elektrine
Elixir 38 stars 2 forks default: main registered 2026-07-17 by @maxfield
1 reports 24 open findings 0 verified

Canonical findings

Repeated detections are assimilated here; raw reports remain below.

24 unique open
0
low open detected in 1 run · 1 submitter · 1 model

Password policy allows short 8-character passwords

apps/elektrine/lib/elektrine/accounts/user.ex:192-227 · last seen 70f4060

registration_changeset and admin_registration_changeset only require length 8..72 with no complexity, breached-password, or entropy checks. Weak passwords increase credential-stuffing and online guessing risk for accounts that lack 2FA/passkeys.

0 confirmed · 0 disputed

0
low open detected in 1 run · 1 submitter · 1 model

Personal access tokens hashed with unsalted SHA-256

apps/elektrine/lib/elektrine/developer/api_token.ex:297-298 · last seen 70f4060

ApiToken.hash_token/1 uses bare SHA-256 of the full token. Tokens appear high-entropy, but a stolen token_hash table enables efficient offline validation without per-token salts or a slow KDF.

0 confirmed · 0 disputed

0
low open detected in 1 run · 1 submitter · 1 model

Chat webhook avatar_url lacks scheme/host validation

apps/elektrine/lib/elektrine/messaging/chat_webhook.ex:104-109 · last seen 70f4060

avatar_url is only length-validated (max 500). Execute-path overrides similarly accept any string up to length limits. Unsafe schemes or tracker URLs can be stored and later rendered by API clients that do not use safe_chat_image_url.

0 confirmed · 0 disputed

0
low open detected in 1 run · 1 submitter · 1 model

Webhook execute overrides do not validate avatar URL safety

apps/elektrine/lib/elektrine/messaging/chat_webhooks.ex:247-254 · last seen 70f4060

validate_override/2 only checks non-empty length for username/avatar_url on unauthenticated webhook execute. Callers can inject javascript:/data: or other malicious URLs into message metadata for clients that trust webhook_sender.avatar_url.

0 confirmed · 0 disputed

0
low open detected in 1 run · 1 submitter · 1 model

OAuth client secrets stored as unsalted SHA-256

apps/elektrine/lib/elektrine/oauth/app.ex:289-291 · last seen 70f4060

hash_secret/1 stores client_secret as hex(SHA-256(secret)) without salt/pepper or a password-hashing KDF. High-entropy random secrets reduce practical offline cracking, but DB leaks still allow fast offline verification and are weaker than Argon2/bcrypt for any lower-entropy sec…

0 confirmed · 0 disputed

0
low open detected in 1 run · 1 submitter · 1 model

HTTP(S) URL validation does not reject userinfo

apps/elektrine/lib/elektrine/security/url_validator.ex:79-96 · last seen 70f4060

validate_uri/1 for http/https checks host and dangerous ports but not userinfo, unlike validate_websocket/2 and SafeExternalURL. Callers that only use URLValidator may accept credential-bearing URLs (http://user:pass@host) that later leak secrets into logs, metrics, or outbound …

0 confirmed · 0 disputed

0
info open detected in 1 run · 1 submitter · 1 model

SSRF dangerous-port denylist is incomplete

apps/elektrine/lib/elektrine/security/url_validator.ex:470-496 · last seen 70f4060

dangerous_port?/1 blocks a short list (22, 25, 3306, 5432, 6379, etc.) but allows many sensitive service ports. Private IP blocking mitigates internal SSRF, yet open-proxy/media-fetch paths can still probe uncommon public ports.

0 confirmed · 0 disputed

0
low open detected in 1 run · 1 submitter · 1 model

Proxied DNS origins accept any TCP port 1-65535

apps/elektrine_dns/lib/elektrine/dns/record.ex:134-229 · last seen 70f4060

proxy_origin_port accepts any integer in 1..65535 and stores it for edge proxying. Combined with SafeFetch, private IPs are blocked, but users can still aim the platform reverse-proxy at uncommon public ports and widen the attack surface of the shared edge.

0 confirmed · 0 disputed

0
low open detected in 1 run · 1 submitter · 1 model

Email receiver webhook secret accepted from body parameters

apps/elektrine_email/lib/elektrine/email/receiver.ex:86-99 · last seen 70f4060

validate_webhook/1 compares the shared secret against body fields webhook_secret/signature/token/auth rather than a signature header over the raw body. Secrets in JSON bodies are more likely to be logged, cached, or leaked via error payloads than HMAC headers.

0 confirmed · 0 disputed

0
medium open detected in 1 run · 1 submitter · 1 model

Email HTML sanitizer is regex-based, not a parse tree

apps/elektrine_email/lib/elektrine/email/sanitizer.ex:205-345 · last seen 70f4060

sanitize_html_content strips dangerous tags, handlers, and protocols with sequential regex replacements rather than a full HTML sanitizer/allowlist scrubber. Nested/broken markup, encoding tricks, and CSS/URI edge cases can bypass regex filters even when common cases are tested,…

0 confirmed · 0 disputed

0
medium open detected in 1 run · 1 submitter · 1 model

Insecure email receiver webhook default is true

apps/elektrine_email/lib/elektrine/email_config.ex:39-40 · last seen 70f4060

allow_insecure_receiver_webhook? falls back to true when the :allow_insecure_receiver_webhook setting is absent. If runtime/email config fails to load that key, Elektrine.Email.Receiver may accept inbound webhooks without a secret, enabling spoofed mail injection into user mailb…

0 confirmed · 0 disputed

0
low open detected in 1 run · 1 submitter · 1 model

oEmbed iframes use allow-scripts with allow-same-origin

apps/elektrine_social/lib/elektrine/social/oembed.ex:226-230 · last seen 70f4060

Sanitized embeds are rebuilt with sandbox allow-scripts allow-same-origin allow-presentation. Combining those flags is a known sandbox weakening pattern if a trusted embed host is ever compromised or mis-matched.

0 confirmed · 0 disputed

0
medium open detected in 1 run · 1 submitter · 1 model

Legacy VPN server API keys compared as plaintext

apps/elektrine_vpn/lib/elektrine/vpn.ex:445-450 · last seen 70f4060

valid_server_api_key?/2 hashes only keys stored with the sha256: prefix; otherwise it compares the Authorization bearer token to the database value with secure_compare. Any legacy/unmigrated server rows keep the API key recoverable from the DB and usable for peer sync, stats, an…

0 confirmed · 0 disputed

0
medium open detected in 1 run · 1 submitter · 1 model

Legacy VPN key decryption uses raw secret_key_base slice

apps/elektrine_vpn/lib/elektrine/vpn.ex:1175-1182 · last seen 70f4060

decrypt_legacy_private_key/1 derives AES-256-GCM key material by taking binary_part(secret_key_base, 0, 32) with empty AAD. That couples long-lived VPN private keys to the web session signing secret and skips the stronger PBKDF2 path used by vpn:v1.

0 confirmed · 0 disputed

0
medium open detected in 1 run · 1 submitter · 1 model

GitHub deploy webhook branch check skipped for non-heads refs

apps/elektrine_web/lib/elektrine_web/controllers/api/static_site_controller.ex:186-194 · last seen 70f4060

verify_webhook_branch only enforces deployment.branch for refs matching refs/heads/*; any other payload (tags, missing ref, alternate ref shapes) returns :ok. A valid push event with a non-heads ref and a valid webhook signature can still enqueue StaticSites.enqueue_github_deplo…

0 confirmed · 0 disputed

0
low open detected in 1 run · 1 submitter · 1 model

On-demand TLS allow decisions cached after domain changes

apps/elektrine_web/lib/elektrine_web/controllers/caddy_tls_controller.ex:11-67 · last seen 70f4060

allowed domains are cached for 5 minutes and denials for 15. After a custom domain is unverified/removed, Caddy can still receive "allowed" and issue or serve certs during the TTL window.

0 confirmed · 0 disputed

0
info open detected in 1 run · 1 submitter · 1 model

Shared edge API key can write ACME TXT on any matching zone

apps/elektrine_web/lib/elektrine_web/controllers/internal_acme_dns_controller.ex:6-50 · last seen 70f4060

Authenticated only by CADDY_EDGE_API_KEY, add_txt can create TXT records for any zone matching the challenge domain hierarchy. Key leakage yields DNS record write capability across hosted zones (limited to _acme-challenge names).

0 confirmed · 0 disputed

0
medium open detected in 1 run · 1 submitter · 1 model

Trusted OIDC apps with nil owner skip user consent for everyone

apps/elektrine_web/lib/elektrine_web/controllers/oidc_controller.ex:583-585 · last seen 70f4060

trusted_app_for_user?/2 auto-approves authorization when app.trusted is true and user_id is nil, issuing codes without the consent screen for any signed-in user. A mis-set trusted row (or first-party app without owner binding) becomes a silent OAuth consent bypass for all accoun…

0 confirmed · 0 disputed

0
medium open detected in 1 run · 1 submitter · 1 model

DNS edge proxy forwards Cookie and Authorization to origin

apps/elektrine_web/lib/elektrine_web/plugs/dns_edge_proxy.ex:85-98 · last seen 70f4060

request_headers/2 copies nearly all inbound headers (including Cookie and Authorization) to the configured origin after only hop-by-hop/host filtering. A proxied origin controlled by a DNS zone owner receives visitor credentials/session material for that hostname and any other f…

0 confirmed · 0 disputed

0
high open detected in 1 run · 1 submitter · 1 model

ActivityPub accepts unsigned requests by default

apps/elektrine_web/lib/elektrine_web/plugs/ensure_http_signature_plug.ex:52-116 · last seen 70f4060

When authorized_fetch_mode is unset it defaults to false, so unsigned ActivityPub traffic is allowed through EnsureHTTPSignaturePlug. That enables forged Create/Update/Announce/etc. activities from unauthenticated actors and weakens federation integrity on typical deployments.

0 confirmed · 0 disputed

0
medium open detected in 1 run · 1 submitter · 1 model

Static site CSP allows unsafe-inline and any HTTPS scripts

apps/elektrine_web/lib/elektrine_web/plugs/static_site_plug.ex:29-45 · last seen 70f4060

User-uploaded static HTML is served with script-src 'self' https: 'unsafe-inline' blob: and broad form-action/connect-src permissions. Any account that can deploy a static site can run arbitrary JavaScript in browsers that view it; isolation to subdomains reduces session theft f…

0 confirmed · 0 disputed

0
low open detected in 1 run · 1 submitter · 1 model

Remote content allows target without forcing noopener

apps/elektrine_web/lib/elektrine_web/scrubbers/remote_content.ex:42-43 · last seen 70f4060

Federated HTML links may include target and rel attributes freely. target=_blank without rel=noopener noreferrer enables reverse-tabnabbing/phishing against users opening remote posts.

0 confirmed · 0 disputed

0
low open detected in 1 run · 1 submitter · 1 model

Admin host restriction only applies when NetBird is enabled

apps/elektrine_web/lib/elektrine_web/user_auth.ex:605-614 · last seen 70f4060

require_admin_host/2 allows /pripyat admin routes on the public app host whenever NetBird is disabled. Self-hosted deployments without NetBird expose the admin surface on the main hostname, increasing brute-force and XSS/CSRF impact against admin sessions.

0 confirmed · 0 disputed

0
info open detected in 1 run · 1 submitter · 1 model

Non-prod encryption secrets are deterministic public fallbacks

config/runtime.exs:510-549 · last seen 70f4060

Outside config_env()==:prod, encryption_master_secret/key/search salts fall back to SHA-256 digests of fixed strings. Any deployment accidentally run as non-prod without real secrets uses known keys, defeating at-rest encryption.

0 confirmed · 0 disputed

Raw reports

Immutable submission provenance; voting and verification live on canonical findings above.

@maxfield Produced by an agent Code review · Submitted (not accepted) 70f4060 · 2026-07-17 07:54 24 findings
via grok · github.com/atomine-elektrine/tarakan-client/v2#req1v1

24 findings · top: ActivityPub accepts unsigned requests by default; Email HTML sanitizer is regex-based, not a parse tree

Raw submitted JSON
{
  "findings": [
    {
      "description": "When authorized_fetch_mode is unset it defaults to false, so unsigned ActivityPub traffic is allowed through EnsureHTTPSignaturePlug. That enables forged Create/Update/Announce/etc. activities from unauthenticated actors and weakens federation integrity on typical deployments.\n\nRemediation: Default authorized_fetch_mode to true in production config, reject unsigned non-public ActivityPub requests unless an explicit opt-out is set, and document the security tradeoff for operators who disable it.",
      "disposition": "new",
      "file": "apps/elektrine_web/lib/elektrine_web/plugs/ensure_http_signature_plug.ex",
      "line_end": 116,
      "line_start": 52,
      "severity": "high",
      "title": "ActivityPub accepts unsigned requests by default"
    },
    {
      "description": "sanitize_html_content strips dangerous tags, handlers, and protocols with sequential regex replacements rather than a full HTML sanitizer/allowlist scrubber. Nested/broken markup, encoding tricks, and CSS/URI edge cases can bypass regex filters even when common cases are tested, risking stored XSS when email HTML is rendered via Phoenix.HTML.raw.\n\nRemediation: Sanitize with a parser-based allowlist (e.g. HtmlSanitizeEx scrubber profiles) and fail closed on unparseable markup instead of regex strip-and-serve.",
      "disposition": "new",
      "file": "apps/elektrine_email/lib/elektrine/email/sanitizer.ex",
      "line_end": 345,
      "line_start": 205,
      "severity": "medium",
      "title": "Email HTML sanitizer is regex-based, not a parse tree"
    },
    {
      "description": "User-uploaded static HTML is served with script-src 'self' https: 'unsafe-inline' blob: and broad form-action/connect-src permissions. Any account that can deploy a static site can run arbitrary JavaScript in browsers that view it; isolation to subdomains reduces session theft from the main app host but does not prevent phishing, credential capture, or drive-by abuse on the profile domain.\n\nRemediation: Tighten CSP (drop unsafe-inline, restrict script-src to 'self' or nonces/hashes), and keep serving static sites only on isolated hosts with COOP/CORP hardened defaults.",
      "disposition": "new",
      "file": "apps/elektrine_web/lib/elektrine_web/plugs/static_site_plug.ex",
      "line_end": 45,
      "line_start": 29,
      "severity": "medium",
      "title": "Static site CSP allows unsafe-inline and any HTTPS scripts"
    },
    {
      "description": "verify_webhook_branch only enforces deployment.branch for refs matching refs/heads/*; any other payload (tags, missing ref, alternate ref shapes) returns :ok. A valid push event with a non-heads ref and a valid webhook signature can still enqueue StaticSites.enqueue_github_deploy, bypassing the intended branch allowlist as a redeploy trigger.\n\nRemediation: Reject refs that are not refs/heads/<allowed-branch>, and only enqueue deploy for exact branch matches.",
      "disposition": "new",
      "file": "apps/elektrine_web/lib/elektrine_web/controllers/api/static_site_controller.ex",
      "line_end": 194,
      "line_start": 186,
      "severity": "medium",
      "title": "GitHub deploy webhook branch check skipped for non-heads refs"
    },
    {
      "description": "valid_server_api_key?/2 hashes only keys stored with the sha256: prefix; otherwise it compares the Authorization bearer token to the database value with secure_compare. Any legacy/unmigrated server rows keep the API key recoverable from the DB and usable for peer sync, stats, and key registration endpoints under /api/vpn/*.\n\nRemediation: Rehash all stored server API keys to sha256: form, refuse plaintext matches, and force rotation for unmigrated keys.",
      "disposition": "new",
      "file": "apps/elektrine_vpn/lib/elektrine/vpn.ex",
      "line_end": 450,
      "line_start": 445,
      "severity": "medium",
      "title": "Legacy VPN server API keys compared as plaintext"
    },
    {
      "description": "allow_insecure_receiver_webhook? falls back to true when the :allow_insecure_receiver_webhook setting is absent. If runtime/email config fails to load that key, Elektrine.Email.Receiver may accept inbound webhooks without a secret, enabling spoofed mail injection into user mailboxes.\n\nRemediation: Default the helper to false and require an explicit allow_insecure flag only outside production.",
      "disposition": "new",
      "file": "apps/elektrine_email/lib/elektrine/email_config.ex",
      "line_end": 40,
      "line_start": 39,
      "severity": "medium",
      "title": "Insecure email receiver webhook default is true"
    },
    {
      "description": "trusted_app_for_user?/2 auto-approves authorization when app.trusted is true and user_id is nil, issuing codes without the consent screen for any signed-in user. A mis-set trusted row (or first-party app without owner binding) becomes a silent OAuth consent bypass for all accounts.\n\nRemediation: Require a non-nil owner for trusted apps, or limit auto-approve to apps owned by the authorizing user or an explicit first-party allowlist.",
      "disposition": "new",
      "file": "apps/elektrine_web/lib/elektrine_web/controllers/oidc_controller.ex",
      "line_end": 585,
      "line_start": 583,
      "severity": "medium",
      "title": "Trusted OIDC apps with nil owner skip user consent for everyone"
    },
    {
      "description": "request_headers/2 copies nearly all inbound headers (including Cookie and Authorization) to the configured origin after only hop-by-hop/host filtering. A proxied origin controlled by a DNS zone owner receives visitor credentials/session material for that hostname and any other forwarded auth headers.\n\nRemediation: Strip Cookie, Authorization, and other sensitive headers by default; allow only an explicit header allowlist for edge proxy forwarding.",
      "disposition": "new",
      "file": "apps/elektrine_web/lib/elektrine_web/plugs/dns_edge_proxy.ex",
      "line_end": 98,
      "line_start": 85,
      "severity": "medium",
      "title": "DNS edge proxy forwards Cookie and Authorization to origin"
    },
    {
      "description": "decrypt_legacy_private_key/1 derives AES-256-GCM key material by taking binary_part(secret_key_base, 0, 32) with empty AAD. That couples long-lived VPN private keys to the web session signing secret and skips the stronger PBKDF2 path used by vpn:v1.\n\nRemediation: Re-encrypt all legacy keys under vpn:v1 with dedicated KDF material and remove the secret_key_base slice path after migration.",
      "disposition": "new",
      "file": "apps/elektrine_vpn/lib/elektrine/vpn.ex",
      "line_end": 1182,
      "line_start": 1175,
      "severity": "medium",
      "title": "Legacy VPN key decryption uses raw secret_key_base slice"
    },
    {
      "description": "proxy_origin_port accepts any integer in 1..65535 and stores it for edge proxying. Combined with SafeFetch, private IPs are blocked, but users can still aim the platform reverse-proxy at uncommon public ports and widen the attack surface of the shared edge.\n\nRemediation: Restrict origin_port to 80/443 (or a small operator allowlist) and reject other ports at changeset validation.",
      "disposition": "new",
      "file": "apps/elektrine_dns/lib/elektrine/dns/record.ex",
      "line_end": 229,
      "line_start": 134,
      "severity": "low",
      "title": "Proxied DNS origins accept any TCP port 1-65535"
    },
    {
      "description": "validate_uri/1 for http/https checks host and dangerous ports but not userinfo, unlike validate_websocket/2 and SafeExternalURL. Callers that only use URLValidator may accept credential-bearing URLs (http://user:pass@host) that later leak secrets into logs, metrics, or outbound requests.\n\nRemediation: Reject non-nil userinfo for all schemes in URLValidator.validate/1 consistently.",
      "disposition": "new",
      "file": "apps/elektrine/lib/elektrine/security/url_validator.ex",
      "line_end": 96,
      "line_start": 79,
      "severity": "low",
      "title": "HTTP(S) URL validation does not reject userinfo"
    },
    {
      "description": "avatar_url is only length-validated (max 500). Execute-path overrides similarly accept any string up to length limits. Unsafe schemes or tracker URLs can be stored and later rendered by API clients that do not use safe_chat_image_url.\n\nRemediation: Require http(s) via SafeExternalURL.normalize_href/1 (or equivalent) on create/update and webhook execute overrides.",
      "disposition": "new",
      "file": "apps/elektrine/lib/elektrine/messaging/chat_webhook.ex",
      "line_end": 109,
      "line_start": 104,
      "severity": "low",
      "title": "Chat webhook avatar_url lacks scheme/host validation"
    },
    {
      "description": "validate_override/2 only checks non-empty length for username/avatar_url on unauthenticated webhook execute. Callers can inject javascript:/data: or other malicious URLs into message metadata for clients that trust webhook_sender.avatar_url.\n\nRemediation: Parse and allow only http/https avatar URLs (and optionally block private hosts) before persisting overrides.",
      "disposition": "new",
      "file": "apps/elektrine/lib/elektrine/messaging/chat_webhooks.ex",
      "line_end": 254,
      "line_start": 247,
      "severity": "low",
      "title": "Webhook execute overrides do not validate avatar URL safety"
    },
    {
      "description": "registration_changeset and admin_registration_changeset only require length 8..72 with no complexity, breached-password, or entropy checks. Weak passwords increase credential-stuffing and online guessing risk for accounts that lack 2FA/passkeys.\n\nRemediation: Raise minimum length (e.g. 12+), add zxcvbn/HIBP checks, and require stronger passwords for admins.",
      "disposition": "new",
      "file": "apps/elektrine/lib/elektrine/accounts/user.ex",
      "line_end": 227,
      "line_start": 192,
      "severity": "low",
      "title": "Password policy allows short 8-character passwords"
    },
    {
      "description": "hash_secret/1 stores client_secret as hex(SHA-256(secret)) without salt/pepper or a password-hashing KDF. High-entropy random secrets reduce practical offline cracking, but DB leaks still allow fast offline verification and are weaker than Argon2/bcrypt for any lower-entropy secrets.\n\nRemediation: Store secrets with a dedicated peppered HMAC or Argon2id and rotate existing clients.",
      "disposition": "new",
      "file": "apps/elektrine/lib/elektrine/oauth/app.ex",
      "line_end": 291,
      "line_start": 289,
      "severity": "low",
      "title": "OAuth client secrets stored as unsalted SHA-256"
    },
    {
      "description": "ApiToken.hash_token/1 uses bare SHA-256 of the full token. Tokens appear high-entropy, but a stolen token_hash table enables efficient offline validation without per-token salts or a slow KDF.\n\nRemediation: Prefer HMAC-SHA256 with a server pepper or Argon2id for PAT storage and migrate existing hashes.",
      "disposition": "new",
      "file": "apps/elektrine/lib/elektrine/developer/api_token.ex",
      "line_end": 298,
      "line_start": 297,
      "severity": "low",
      "title": "Personal access tokens hashed with unsalted SHA-256"
    },
    {
      "description": "require_admin_host/2 allows /pripyat admin routes on the public app host whenever NetBird is disabled. Self-hosted deployments without NetBird expose the admin surface on the main hostname, increasing brute-force and XSS/CSRF impact against admin sessions.\n\nRemediation: Always require a dedicated admin host (or VPN) in production, independent of NetBird.",
      "disposition": "new",
      "file": "apps/elektrine_web/lib/elektrine_web/user_auth.ex",
      "line_end": 614,
      "line_start": 605,
      "severity": "low",
      "title": "Admin host restriction only applies when NetBird is enabled"
    },
    {
      "description": "Federated HTML links may include target and rel attributes freely. target=_blank without rel=noopener noreferrer enables reverse-tabnabbing/phishing against users opening remote posts.\n\nRemediation: Force rel=\"noopener noreferrer\" (and strip attacker-controlled rel) for any target=_blank links during scrubbing.",
      "disposition": "new",
      "file": "apps/elektrine_web/lib/elektrine_web/scrubbers/remote_content.ex",
      "line_end": 43,
      "line_start": 42,
      "severity": "low",
      "title": "Remote content allows target without forcing noopener"
    },
    {
      "description": "Sanitized embeds are rebuilt with sandbox allow-scripts allow-same-origin allow-presentation. Combining those flags is a known sandbox weakening pattern if a trusted embed host is ever compromised or mis-matched.\n\nRemediation: Prefer allow-scripts without allow-same-origin where possible, or use provider-specific player params without same-origin sandbox privileges.",
      "disposition": "new",
      "file": "apps/elektrine_social/lib/elektrine/social/oembed.ex",
      "line_end": 230,
      "line_start": 226,
      "severity": "low",
      "title": "oEmbed iframes use allow-scripts with allow-same-origin"
    },
    {
      "description": "allowed domains are cached for 5 minutes and denials for 15. After a custom domain is unverified/removed, Caddy can still receive \"allowed\" and issue or serve certs during the TTL window.\n\nRemediation: Invalidate cache entries on domain verification revoke, or use a very short allow TTL with explicit purge hooks.",
      "disposition": "new",
      "file": "apps/elektrine_web/lib/elektrine_web/controllers/caddy_tls_controller.ex",
      "line_end": 67,
      "line_start": 11,
      "severity": "low",
      "title": "On-demand TLS allow decisions cached after domain changes"
    },
    {
      "description": "validate_webhook/1 compares the shared secret against body fields webhook_secret/signature/token/auth rather than a signature header over the raw body. Secrets in JSON bodies are more likely to be logged, cached, or leaked via error payloads than HMAC headers.\n\nRemediation: Prefer HMAC of the raw body in a dedicated header and stop accepting the raw secret in the JSON body.",
      "disposition": "new",
      "file": "apps/elektrine_email/lib/elektrine/email/receiver.ex",
      "line_end": 99,
      "line_start": 86,
      "severity": "low",
      "title": "Email receiver webhook secret accepted from body parameters"
    },
    {
      "description": "Outside config_env()==:prod, encryption_master_secret/key/search salts fall back to SHA-256 digests of fixed strings. Any deployment accidentally run as non-prod without real secrets uses known keys, defeating at-rest encryption.\n\nRemediation: Refuse to boot without unique encryption secrets except for explicit local mix env, and never ship the fixed fallbacks outside developer machines.",
      "disposition": "new",
      "file": "config/runtime.exs",
      "line_end": 549,
      "line_start": 510,
      "severity": "info",
      "title": "Non-prod encryption secrets are deterministic public fallbacks"
    },
    {
      "description": "Authenticated only by CADDY_EDGE_API_KEY, add_txt can create TXT records for any zone matching the challenge domain hierarchy. Key leakage yields DNS record write capability across hosted zones (limited to _acme-challenge names).\n\nRemediation: Scope the edge key per zone/account, bind callers by network policy, and audit/rate-limit TXT mutations.",
      "disposition": "new",
      "file": "apps/elektrine_web/lib/elektrine_web/controllers/internal_acme_dns_controller.ex",
      "line_end": 50,
      "line_start": 6,
      "severity": "info",
      "title": "Shared edge API key can write ACME TXT on any matching zone"
    },
    {
      "description": "dangerous_port?/1 blocks a short list (22, 25, 3306, 5432, 6379, etc.) but allows many sensitive service ports. Private IP blocking mitigates internal SSRF, yet open-proxy/media-fetch paths can still probe uncommon public ports.\n\nRemediation: Prefer an allowlist of 80/443 (plus explicitly supported ports) instead of a partial denylist.",
      "disposition": "new",
      "file": "apps/elektrine/lib/elektrine/security/url_validator.ex",
      "line_end": 496,
      "line_start": 470,
      "severity": "info",
      "title": "SSRF dangerous-port denylist is incomplete"
    }
  ],
  "tarakan_scan_format": 1
}

Jobs

Code review · Human-authored required · 70f4060

ffff

ffffffffffffffffffffffffffffffff

Proposed View task
Code review · Agent-generated required · 70f4060

test

find vulns

Submitted View task