Back to skill

Security audit

Oban

Security checks for vulnerabilities and agentic risk

Overview

This Oban worker skill is coherent, but some reusable examples could lead an agent to create unsafe background jobs that send data to arbitrary URLs or read arbitrary local files.

Review the worker examples before installing or using this skill as code-generation guidance. Treat webhook URLs, email/SMS recipients, file paths, cron cleanup jobs, and bulk database writes as sensitive operations that need explicit authorization, allowlists, tenant checks, path or storage scoping, bounded logging, and tests before production use.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
references/worker-patterns.md:59
Finding

Unrestricted Webhook Destination Enables Server-Side Request Forgery

Content
View full analysis

Vulnerability Details

File Location: references/worker-patterns.md, lines 59–78
Vulnerability Type: Server-Side Request Forgery (SSRF)
Risk Level: High

elixir
def perform(%Oban.Job{args: args, attempt: attempt}) do
  %{"url" => url, "event" => event, "payload" => payload} = args
  headers = build_headers(args)

  case Req.post(url, json: payload, headers: headers, receive_timeout: 25_000) do
    {:ok, %{status: status}} when status in 200..299 ->
      :ok

    {:ok, %{status: 410}} ->
      Logger.info("Webhook endpoint gone: #{url}")
      {:cancel, "endpoint returned 410 Gone"}

    {:ok, %{status: status, body: body}} ->
      Logger.warning("Webhook failed: #{status} - #{inspect(body)}")
      {:error, "HTTP #{status}"}

    {:error, %Req.TransportError{reason: reason}} ->
      {:error, "transport: #{inspect(reason)}"}
  end
end

Technical Analysis

The worker obtains the request destination directly from persistent job arguments and passes it to Req.post/2. It does not validate the URL scheme, hostname, resolved IP address, port, or redirect destination.

If an untrusted user can directly enqueue jobs or indirectly control webhook configuration used to create these arguments, the worker can be induced to send requests from the application server to otherwise inaccessible destinations. Potential targets include loopback services, private network addresses, container infrastructure, and cloud instance metadata services.

The error path also logs the remote response body. This may disclose internal response content to anyone with access to application logs and can allow untrusted endpoints to inject large or sensitive content into those logs.

Attack Path

  1. An attacker gains control over a webhook URL that is serialized into an Oban job.
  2. The attacker supplies a URL targeting an internal service, loopback address, private network host, or cloud metadata endpoint.

...[truncated 999 chars]

Remediation
View remediation

Remediation Suggestions

  • Do not accept a request URL directly from job arguments. Store a trusted webhook subscription identifier and resolve its destination from an authorized database record when the job executes.
  • Permit only explicitly supported schemes, preferably HTTPS.
  • Enforce an allowlist of approved hostnames or domains where the business model permits it.
  • Resolve the hostname and reject loopback, link-local, private, multicast, reserved, and metadata-service addresses for both IPv4 and IPv6.
  • Protect against DNS rebinding by verifying the address used for the actual connection, not only an earlier DNS lookup.
  • Disable redirects or validate the scheme, hostname, port, and resolved destination after every redirect.
  • Apply outbound firewall or proxy rules so the worker cannot access infrastructure management networks or metadata services.
  • Limit response sizes and avoid logging complete untrusted response bodies. Log a bounded, sanitized diagnostic value instead.
  • Authorize webhook creation and job insertion, and validate that the referenced webhook belongs to the appropriate tenant.

T09 · Insecure Skill Coding Practices

Warning
Location
references/worker-patterns.md:168
Finding

Unvalidated Import Path Enables Arbitrary Local-File Access

Content
View full analysis

Vulnerability Details

File Location: references/worker-patterns.md, lines 168–182
Vulnerability Type: Path Traversal and Arbitrary Local-File Read
Risk Level: Medium

elixir
def perform(%Oban.Job{args: %{"file_path" => path, "tenant_id" => tenant_id}}) do
  path
  |> File.stream!()
  |> CSV.decode!(headers: true)
  |> Stream.chunk_every(500)
  |> Enum.each(fn batch ->
    entries = Enum.map(batch, &build_entry(&1, tenant_id))
    MyApp.Repo.insert_all(MyApp.Items.Item, entries,
      on_conflict: :replace_all,
      conflict_target: [:tenant_id, :external_id]
    )
  end)

  :ok
end

Technical Analysis

The import worker takes file_path directly from persistent Oban job arguments and opens it with File.stream!/1. The example does not canonicalize the path, restrict it to a dedicated import directory, verify ownership, reject symbolic links, or require a server-generated upload identifier.

A user who can influence the argument may therefore provide an absolute path or traversal path referencing any file readable by the application service account. Special files, named pipes, or extremely large files may also cause blocking or resource exhaustion.

Although the worker expects CSV content, a target file that is CSV-compatible may be parsed and written into application records. Other files may reveal existence, formatting, or content through parsing errors and logs.

Attack Path

  1. An attacker obtains the ability to initiate an import or otherwise influence the Oban job's file_path argument.
  2. The attacker supplies an absolute path, traversal sequence, symbolic-link path, or special-file path.
  3. The background worker opens the target using the filesystem privileges of the application service account.
  4. The file is streamed into the CSV decoder.
  5. Compatible content is transformed and persisted into tenant-scoped database records; incompatible content may be ...[truncated 726 chars]
Remediation
View remediation

Remediation Suggestions

  • Put a server-generated upload or storage-object identifier in the job rather than a caller-provided filesystem path.
  • Resolve that identifier through an authorized storage layer and verify that the object belongs to the specified tenant.
  • If local paths are necessary, canonicalize both the configured import root and candidate path, then require the candidate to remain beneath that root.
  • Reject absolute paths, traversal components, symbolic links, named pipes, device files, sockets, and other non-regular files.
  • Open files in a way that mitigates time-of-check/time-of-use and symbolic-link races.
  • Run the worker under a dedicated service account with access only to the required import directory.
  • Enforce file size, row count, processing-time, and field-length limits before and during parsing.
  • Sanitize parsing errors and avoid placing local paths or file contents in user-visible responses and logs.
  • Add authorization tests covering cross-tenant identifiers, traversal attempts, symbolic links, and oversized files.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (5)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

This markdown file includes examples for email delivery and webhook delivery, which inherently involve sending data outside the application boundary. The skill description and surrounding documentation do not include any warning about privacy, sensitive data handling, or the need to validate outbound recipients/endpoints.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The webhook worker posts job-supplied payloads to a job-supplied URL with no allowlist, destination validation, or warning about the risks of arbitrary outbound requests. In practice, this pattern can enable SSRF, exfiltration of sensitive data to attacker-controlled endpoints, and delivery to internal services if untrusted users can enqueue or influence jobs.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest says this skill is for designing and implementing Oban workers, queue config, retry strategies, uniqueness, cron scheduling, error handling, and test setups. This reference file goes beyond Oban-specific design guidance by providing full examples for destructive data cleanup, bulk database import/upsert workflows, and push/email/SMS notification routing, which are substantive business capabilities not justified merely by 'design Oban workers'.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The import worker consumes an arbitrary file path from job arguments and performs bulk database writes with upsert-style replacement, without validation or any warning about destructive data modification. If an attacker can influence job args, this can expose local file contents, import unauthorized data, or overwrite records at scale, making the pattern dangerous in a reusable reference.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The manifest frames the skill around background-job infrastructure for Elixir using Oban, not around implementing domain-specific communication channels. Including direct push/email/SMS routing logic introduces notification-delivery capability that is orthogonal to queueing, retries, scheduling, and worker setup.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.