Security Advisories (4)
CVE-2026-57079 (2026-06-30)

Net::BitTorrent versions through 2.0.1 for Perl write files outside the download directory via path traversal in peer-supplied metadata. Net::BitTorrent validates file path components only on the .torrent-file ingest path. The peer and magnet metadata path (_on_metadata_received, reached from the BEP09 ut_metadata extension) passes attacker-supplied file names straight to Storage::add_file and Storage::_parse_file_tree, where Path::Tiny's child() does not collapse "..". A v2 file tree key, a v1 files[].path element, or a single-file name containing ".." segments therefore resolves outside the download directory. Because the peer also controls the piece hashes and the served bytes, content verification passes, so a malicious magnet or peer writes attacker-chosen content to an attacker-chosen path on the downloading host.

CVE-2026-57080 (2026-06-30)

Net::BitTorrent versions through 2.0.1 for Perl allow remote memory exhaustion via an uncapped peer-wire message-length prefix. The peer-wire framing in _process_messages trusts the 4-byte length prefix sent by a connected peer with no upper bound, while receive_data appends every inbound byte to the input buffer. A peer announces a length prefix of up to about 4 GiB and then streams bytes; the decoder waits until the buffer holds the full message before processing it, so the buffer grows without limit. Peer connections are unauthenticated, so any peer in the swarm exhausts the downloading process's memory. The largest legitimate message is a 16 KiB piece block, so any announced length far above that is anomalous.

CVE-2026-57081 (2026-06-30)

Net::BitTorrent versions through 2.0.1 for Perl allow remote memory exhaustion via deeply nested bencoded input. bdecode recurses once per nested list or dictionary level with no depth cap, and each recursive call receives the remaining buffer by value while the list and dictionary branches capture the whole remainder, so every live recursion frame keeps its own copy of the shrinking buffer (O(N^2) bytes for an N-deep input). The decoder runs on every untrusted bencode source: .torrent files, BEP09 metadata fetched from peers, DHT messages, and tracker responses. A bencoded input of roughly 150,000 nested lists (about 150 KB on the wire) drives multi-gigabyte peak memory, so one short message from any peer, or one crafted .torrent file or magnet link, terminates the client.

CVE-2026-57082 (2026-06-30)

Net::BitTorrent versions through 2.0.1 for Perl generate the MSE Diffie-Hellman private key with a non-cryptographic PRNG. The MSE (Message Stream Encryption) handshake derives its 160-bit Diffie-Hellman private key from Perl's rand(), a non-cryptographic drand48-class generator seeded once per process, in KeyExchange.pm. The shared secret and the RC4 keys derived from it (the SHA-1 of "keyA" or "keyB", the shared secret, and the infohash) therefore depend entirely on a predictable PRNG. The same handshake sends, in cleartext, random padding drawn from the same rand() sequence in _random_pad, immediately after the public key and the private-key draw. A passive observer of the handshake recovers the PRNG state from the cleartext padding, reconstructs the private key, computes the shared secret from the peer's public key on the wire, derives the RC4 keys, and decrypts the connection, defeating the passive-observation obfuscation MSE provides.

NAME

Net::BitTorrent::Torrent::Generator - .torrent metadata generator

Synopsis

# Generate a single file .torrent to seed file.avi
my $t1 = Net::BitTorrent::Torrent::Generator->new( path => 'file.avi' );

# Add everything in the current directory accept .torrent files
my $t2 = Net::BitTorrent::Torrent::Generator->new(
    path      => '../',
    path_skip => qr[.*torrent$]
);

# Now, let's write the metadata to disk
print 'Saving ' .  $t2->info_hash->to_Hex . '...';
open my($torrent), '>', 'test.torrent' || die 'FAIL!';
syswrite $torrent, $t2->raw_data;
close $torrent;

Description

TODO

Methods

Creating a new .torrent is simple. As is this API.

my $torrent = Net::BitTorrent::Torrent::Generator->new( path => ..., [ ... ] )

Creates a new generator object.

This constructor requires the following arguments:

path

See path.

This constructor also supports the following optional arguments:

announce

See announce.

announce_list

See announce_list.

path_skip

See path_skip.

comment

See comment.

merge

This is an advanced argument containing a hashref which will be merged with the final metadata when generated.

Don't use this.

piece_length

See "$torrent->piece_length( )" in piece_length.

private

See private.

$torrent->announce( )

The announce URL of the tracker. With the advent and current popularity of DHT, PEX, and other alternate means of learning about peers, this value may be considered optional.

Use $torrent->_set_piece_length to set this value.

$torrent->announce_list( )

Optional list of URLs.

Use $torrent->_set_announce_list( [ [url, url], [url] ] ) to set this value. To add a single tier, use $torrent->_add_tier( [ url, url ] ) >.

See also BEP12.

$torrent->comment( )

This is an optional, free-form textual comment.

$torrent->files( )

Returns the list of files contained in this torrent.

$torrent->info_hash( )

Returns the 160bit hex string used to identify this torrent as a Bit::Vector object.

$torrent->metadata( )

This method generates and returns the metadata.

For raw data ready to write to disk, see raw_data.

$torrent->path( )

This is a string contining either a directory or a single file.

If this is a directory, a multi-file torrent is generated.

Use $torrent->_set_path( $path ) to set this value later.

$torrent->path_skip( )

This is a regular expression. If pathpath( )"> is a directory, found files are checked against this regex. If they match, they're ignored when generating <metadata|/"$torrent->metadata( )">.

Use $torrent->_set_path_skip( qr[...] ) to set this value later and $torrent->_clear_path_skip( ) to clear it.

$torrent->piece_length( )

For the purposes of transfer, files are split into fixed-size pieces which are all the same length except for possibly the last one which may be truncated. piece_length is almost always a power of two, most commonly 2**18 (256KB). This is also our default value.

Use $torrent->_set_piece_length to set this value.

$torrent->private( )

A boolean value for cheap DRM behaviour.

Use $torrent->_set_private to set this on and $torrent->_unset_private to turn it back off.

See also BEP27.

$torrent->raw_data( )

Generates metadata and returns it as a bencoded string. This is what you'd write to disk.

$torrent->total_size( )

Returns the total size of all the files related to this torrent.

Notes

This class may be renamed. Suggestions welcome.

See Also

BEP03

Net::BitTorrent::File

TODO

Optional, user-defined/smart file sorting

Author

Sanko Robinson <sanko@cpan.org> - http://sankorobinson.com/

CPAN ID: SANKO

License and Legal

Copyright (C) 2008-2010 by Sanko Robinson <sanko@cpan.org>

This program is free software; you can redistribute it and/or modify it under the terms of The Artistic License 2.0. See the LICENSE file included with this distribution or notes on the Artistic License 2.0 for clarification.

When separated from the distribution, all original POD documentation is covered by the Creative Commons Attribution-Share Alike 3.0 License. See the clarification of the CCA-SA3.0.

Neither this module nor the Author is affiliated with BitTorrent, Inc.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 299:

Unterminated C< ... > sequence