Security Advisories (10)
CPANSA-Mojolicious-2022-03 (2022-12-10)

Mojo::DOM did not correctly parse <script> tags.

CPANSA-Mojolicious-2021-02 (2021-06-01)

Small sessions could be used as part of a brute-force attack to decode the session secret.

CVE-2021-47208 (2021-03-16)

A bug in format detection can potentially be exploited for a DoS attack.

CVE-2018-25100 (2018-02-13)

Mojo::UserAgent::CookieJar leaks old cookies because of the missing host_only flag on empty domain.

CPANSA-Mojolicious-2015-01 (2015-02-02)

Directory traversal on Windows

CPANSA-Mojolicious-2018-03 (2018-05-19)

Mojo::UserAgent was not checking peer SSL certificates by default.

CVE-2020-36829 (2020-11-10)

Mojo::Util secure_compare can leak the string length. By immediately returning when the two strings are not the same length, the function allows an attacker to guess the length of the secret string using timing attacks.

CPANSA-Mojolicious-2018-02 (2018-05-11)

GET requests with embedded backslashes can be used to access local files on Windows hosts

CPANSA-Mojolicious-2014-01 (2014-10-07)

Context sensitivity of method param could lead to parameter injection attacks.

CVE-2024-58134 (2025-05-03)

Mojolicious versions from 0.999922 for Perl uses a hard coded string, or the application's class name, as a HMAC session secret by default. These predictable default secrets can be exploited to forge session cookies. An attacker who knows or guesses the secret could compute valid HMAC signatures for the session cookie, allowing them to tamper with or hijack another user's session.

NAME

Mojo::UserAgent - Non-blocking I/O HTTP 1.1 and WebSocket user agent

SYNOPSIS

use Mojo::UserAgent;
my $ua = Mojo::UserAgent->new;

# Say hello to the unicode snowman
say $ua->get('www.☃.net?hello=there')->res->body;

# Quick JSON API request with Basic authentication
say $ua->get('https://sri:s3cret@api.twitter.com/1/trends.json')
  ->res->json->{trends}->[0]->{name};

# Extract data from HTML and XML resources
say $ua->get('mojolicio.us')->res->dom->html->head->title->text;

# Scrape the latest headlines from a news site
$ua->max_redirects(5)->get('www.reddit.com/r/perl/')
  ->res->dom('p.title > a.title')->each(sub { say $_->text });

# Form POST with exception handling
my $tx = $ua->post_form('search.cpan.org/search' => {q => 'mojo'});
if (my $res = $tx->success) { say $res->body }
else {
  my ($message, $code) = $tx->error;
  say "Error: $message";
}

# PUT request with content
my $tx = $ua->put(
  'mojolicio.us' => {'Content-Type' => 'text/plain'} => 'Hello World!');

# Grab the latest Mojolicious release :)
$ua->max_redirects(5)->get('latest.mojolicio.us')
  ->res->content->asset->move_to('/Users/sri/mojo.tar.gz');

# Parallel requests
my $delay = Mojo::IOLoop->delay;
for my $url ('mojolicio.us', 'cpan.org') {
  $delay->begin;
  $ua->get($url => sub {
    my ($ua, $tx) = @_;
    $delay->end($tx->res->dom->at('title')->text);
  });
}
my @titles = $delay->wait;

# TLS certificate authentication
my $tx = $ua->cert('tls.crt')->key('tls.key')->get('https://mojolicio.us');

# WebSocket request
$ua->websocket('ws://websockets.org:8787' => sub {
  my ($ua, $tx) = @_;
  $tx->on(finish  => sub { Mojo::IOLoop->stop });
  $tx->on(message => sub {
    my ($tx, $message) = @_;
    say $message;
    $tx->finish;
  });
  $tx->send_message('hi there!');
});
Mojo::IOLoop->start;

DESCRIPTION

Mojo::UserAgent is a full featured non-blocking I/O HTTP 1.1 and WebSocket user agent with IPv6, TLS and libev support.

Optional modules EV, IO::Socket::IP and IO::Socket::SSL are supported transparently and used if installed.

EVENTS

Mojo::UserAgent can emit the following events.

start

$ua->on(start => sub {
  my ($ua, $tx) = @_;
});

Emitted whenever a new transaction is about to start, this includes automatically prepared proxy CONNECT requests and followed redirects.

$ua->on(start => sub {
  my ($ua, $tx) = @_;
  $tx->req->headers->header('X-Bender', 'Bite my shiny metal ass!');
});

ATTRIBUTES

Mojo::UserAgent implements the following attributes.

cert

my $cert = $ua->cert;
$ua      = $ua->cert('tls.crt');

Path to TLS certificate file, defaults to the value of the MOJO_CERT_FILE environment variable.

my $cookie_jar = $ua->cookie_jar;
$ua            = $ua->cookie_jar(Mojo::CookieJar->new);

Cookie jar to use for this user agents requests, defaults to a Mojo::CookieJar object.

http_proxy

my $proxy = $ua->http_proxy;
$ua       = $ua->http_proxy('http://sri:secret@127.0.0.1:8080');

Proxy server to use for HTTP and WebSocket requests.

https_proxy

my $proxy = $ua->https_proxy;
$ua       = $ua->https_proxy('http://sri:secret@127.0.0.1:8080');

Proxy server to use for HTTPS and WebSocket requests.

ioloop

my $loop = $ua->ioloop;
$ua      = $ua->ioloop(Mojo::IOLoop->new);

Loop object to use for blocking I/O operations, defaults to a Mojo::IOLoop object.

keep_alive_timeout

my $keep_alive_timeout = $ua->keep_alive_timeout;
$ua                    = $ua->keep_alive_timeout(15);

Maximum amount of time in seconds a connection can be inactive before being dropped, defaults to 15.

key

my $key = $ua->key;
$ua     = $ua->key('tls.crt');

Path to TLS key file, defaults to the value of the MOJO_KEY_FILE environment variable.

log

my $log = $ua->log;
$ua     = $ua->log(Mojo::Log->new);

A Mojo::Log object used for logging, defaults to the application log or a Mojo::Log object.

max_connections

my $max_connections = $ua->max_connections;
$ua                 = $ua->max_connections(5);

Maximum number of keep alive connections that the user agent will retain before it starts closing the oldest cached ones, defaults to 5.

max_redirects

my $max_redirects = $ua->max_redirects;
$ua               = $ua->max_redirects(3);

Maximum number of redirects the user agent will follow before it fails, defaults to the value of the MOJO_MAX_REDIRECTS environment variable or 0.

name

my $name = $ua->name;
$ua      = $ua->name('Mojolicious');

Value for User-Agent request header, defaults to Mojolicious (Perl).

no_proxy

my $no_proxy = $ua->no_proxy;
$ua          = $ua->no_proxy(['localhost', 'intranet.mojolicio.us']);

Domains that don't require a proxy server to be used.

transactor

my $t = $ua->transactor;
$ua   = $ua->transactor(Mojo::UserAgent::Transactor->new);

Transaction builder, defaults to a Mojo::UserAgent::Transactor object. Note that this attribute is EXPERIMENTAL and might change without warning!

websocket_timeout

my $websocket_timeout = $ua->websocket_timeout;
$ua                   = $ua->websocket_timeout(300);

Maximum amount of time in seconds a WebSocket connection can be inactive before being dropped, defaults to 300.

METHODS

Mojo::UserAgent inherits all methods from Mojo::EventEmitter and implements the following new ones.

app

my $app = $ua->app;
$ua     = $ua->app('MyApp');
$ua     = $ua->app(MyApp->new);

Application relative URLs will be processed with, defaults to the value of the MOJO_APP environment variable.

say $ua->app->secret;
$ua->app->log->level('fatal');
$ua->app->defaults(testing => 'oh yea!');

build_form_tx

my $tx = $ua->build_form_tx('http://kraih.com/foo' => {test => 123});

Alias for "form" in Mojo::UserAgent::Transactor.

build_tx

my $tx = $ua->build_tx(GET => 'mojolicio.us');

Alias for "tx" in Mojo::UserAgent::Transactor.

build_websocket_tx

my $tx = $ua->build_websocket_tx('ws://localhost:3000');

Alias for "websocket" in Mojo::UserAgent::Transactor.

delete

my $tx = $ua->delete('http://kraih.com');

Perform blocking HTTP DELETE request and return resulting Mojo::Transaction::HTTP object, takes the exact same arguments as "tx" in Mojo::UserAgent::Transactor (except for the method). You can also append a callback to perform requests non-blocking.

$ua->delete('http://kraih.com' => sub {
  my ($ua, $tx) = @_;
  say $tx->res->body;
  Mojo::IOLoop->stop;
});
Mojo::IOLoop->start;

detect_proxy

$ua = $ua->detect_proxy;

Check environment variables HTTP_PROXY, http_proxy, HTTPS_PROXY, https_proxy, NO_PROXY and no_proxy for proxy information.

get

my $tx = $ua->get('http://kraih.com');

Perform blocking HTTP GET request and return resulting Mojo::Transaction::HTTP object, takes the exact same arguments as "tx" in Mojo::UserAgent::Transactor (except for the method). You can also append a callback to perform requests non-blocking.

$ua->get('http://kraih.com' => sub {
  my ($ua, $tx) = @_;
  say $tx->res->body;
  Mojo::IOLoop->stop;
});
Mojo::IOLoop->start;
my $tx = $ua->head('http://kraih.com');

Perform blocking HTTP HEAD request and return resulting Mojo::Transaction::HTTP object, takes the exact same arguments as "tx" in Mojo::UserAgent::Transactor (except for the method). You can also append a callback to perform requests non-blocking.

$ua->head('http://kraih.com' => sub {
  my ($ua, $tx) = @_;
  say $tx->res->body;
  Mojo::IOLoop->stop;
});
Mojo::IOLoop->start;

need_proxy

my $success = $ua->need_proxy('intranet.mojolicio.us');

Check if request for domain would use a proxy server.

post

my $tx = $ua->post('http://kraih.com');

Perform blocking HTTP POST request and return resulting Mojo::Transaction::HTTP object, takes the exact same arguments as "tx" in Mojo::UserAgent::Transactor (except for the method). You can also append a callback to perform requests non-blocking.

$ua->post('http://kraih.com' => sub {
  my ($ua, $tx) = @_;
  say $tx->res->body;
  Mojo::IOLoop->stop;
});
Mojo::IOLoop->start;

post_form

my $tx = $ua->post_form('http://kraih.com/foo' => {test => 123});

Perform blocking HTTP POST request with form data and return resulting Mojo::Transaction::HTTP object, takes the exact same arguments as "form" in Mojo::UserAgent::Transactor. You can also append a callback to perform requests non-blocking.

$ua->post_form('http://kraih.com' => {q => 'test'} => sub {
  my ($ua, $tx) = @_;
  say $tx->res->body;
  Mojo::IOLoop->stop;
});
Mojo::IOLoop->start;

put

my $tx = $ua->put('http://kraih.com');

Perform blocking HTTP PUT request and return resulting Mojo::Transaction::HTTP object, takes the exact same arguments as "tx" in Mojo::UserAgent::Transactor (except for the method). You can also append a callback to perform requests non-blocking.

$ua->put('http://kraih.com' => sub {
  my ($ua, $tx) = @_;
  say $tx->res->body;
  Mojo::IOLoop->stop;
});
Mojo::IOLoop->start;

start

$ua = $ua->start($tx);

Process blocking transaction. You can also append a callback to perform transactions non-blocking.

$ua->start($tx => sub {
  my ($ua, $tx) = @_;
  say $tx->res->body;
  Mojo::IOLoop->stop;
});
Mojo::IOLoop->start;

test_server

my $url = $ua->test_server;
my $url = $ua->test_server('http');
my $url = $ua->test_server('https');

Starts a test server for app if necessary and returns absolute Mojo::URL object for it. Note that this method is EXPERIMENTAL and might change without warning!

websocket

$ua->websocket('ws://localhost:3000' => sub {...});

Open a non-blocking WebSocket connection with transparent handshake, takes the exact same arguments as "websocket" in Mojo::UserAgent::Transactor. Note that this method is EXPERIMENTAL and might change without warning!

$ua->websocket('ws://localhost:3000/echo' => sub {
  my ($ua, $tx) = @_;
  $tx->on(finish  => sub { Mojo::IOLoop->stop });
  $tx->on(message => sub {
    my ($tx, $message) = @_;
    say "$message\n";
  });
  $tx->send_message('Hi!');
});
Mojo::IOLoop->start;

DEBUGGING

You can set the MOJO_USERAGENT_DEBUG environment variable to get some advanced diagnostics information printed to STDERR.

MOJO_USERAGENT_DEBUG=1

SEE ALSO

Mojolicious, Mojolicious::Guides, http://mojolicio.us.