HOWTO: Create a Warrant Canary, or NSL Dead Man’s Switch

Monday, September 9th, 2013 at 8:52 am | 7,713 views | trackback url

Warrant Canary

Thanks Slashdot for carrying your users over to my blog this morning!

The rsync team has been doing this for quite awhile, and I had an idea. Why not share this more broadly?

So I created a quick little script to generate my own “warrant canary”. Instructions follow below.

Note: Based on the direct emails from Slashdot users, I’ll update this post with more information in the coming days/weeks to keep this current.


use warnings;
use strict;
use LWP::Simple;   # Fetch the remote feed via HTTP
use XML::RSS;      # Parse the RSS feed into tree and DOM elements
use HTML::Strip;   # Clean up bad tags, HTML, CDATA in RSS feeds
use File::Slurp;   # Easily read/write files to the filesystem
use Crypt::GPG;    # Call out to gpg for signing the canary

# Pick an RSS news source that is current, updated, and neutral if possible:
my $url           = "";
# my $url         = '';

binmode(STDOUT, ":utf8");

my $hs            = HTML::Strip->new();
my $gpg           = new Crypt::GPG;
my @newscanary = '';

my $rss           = XML::RSS->new();
my $data          = get($url);

my $channel       = $rss->{channel};

foreach my $item (@{ $rss->{items}}) {
	my $title = $item->{title};
	my $date  = $item->{pubDate};
	my $desc  = $hs->parse($item->{description});

	# Word wrap the output at 70 characters
	$desc =~ s/(.{70}[^\s]*)\s+/$1\n/xg;

	push @newscanary, "$title\n$date\n" . "-"x70 . "\n$desc\n\n\n";

write_file('canary.txt', @newscanary) ;

my $boilerplate = read_file('boilerplate.txt', {binmode => ':raw'});
my $newscanary = read_file('canary.txt', {binmode => ':raw'});

print $boilerplate, $newscanary;


Now you create a file called ‘boilerplate.txt’, which includes the header you want to show up at the top of your canary, such as this example (nicked and modified from the rsync canary):

Existing and proposed laws, especially as relate to the US Patriot Act,
etc., provide for secret warrants, searches and seizures of data, such as
library records.

Some such laws provide for criminal penalties for revealing the warrant,
search or seizure, disallowing the disclosure of events that would
materially affect the users of a service such as those provided by
YOUR_COMPANY and subsidiary domains and services.

YOUR_COMPANY and its principals and employees will in fact comply with
such warrants and their provisions for secrecy as legally prescribed by US

YOUR_COMPANY will also make available, hourly, a "warrant canary" in
the form of a cryptographically signed message containing the following:

	- a declaration that, up to that point, no warrants have been
	  served, nor have any searches or seizures taken place

	- a cut and paste headline from a major news source, establishing

Special note should be taken if these messages ever cease being updated, or
are removed from this page.
The current message is here:

I’ll leave it as an exercise to the reader how to sign the output of that with GNU Privacy Guard (hint: gpg –clearsign), and how to protect that key and copy the completed canary.txt over to your webserver (hint: use rsync).

Set that up in an hourly cron job, and you should be all set.

Last Modified: Sunday, March 6th, 2016 @ 04:38

Leave a Reply

You must be logged in to post a comment.

Bad Behavior has blocked 3661 access attempts in the last 7 days.