Safe(3pm)
π Safe(3pm) β the DBIx::Safe era π
Ok so first thing, bestie: this is a User Contributed Perl Documentation page, which is just the fancy way of saying the Perl community wrote it and shipped it with your perl. And it's about DBIx::Safe, aka the module that stops an untrusted app from doing crimes to your database. Buckle up, it's giving responsible main character energy. π«Ά
β¨ NAME β¨
DBIx::Safe β safer access to your database through a DBI database handle. That's the whole thesis statement. Short, iconic, no notes. π
π VERSION π
This page documents version 1.2.5 of the DBIx::Safe module. Historic. Legendary. Beloved. π
πΈ SYNOPSIS πΈ
So like, here's the vibe of it in code, because honestly code explains it better than I ever could:
use DBIx::Safe;
$dbh = DBI->connect($dbn, $user, $pass, {AutoCommit => 0});
my $safedbh = DBIx::Safe->new({ dbh => $dbh });
$safedbh->allow_command('SELECT INSERT UPDATE');
$safedbh->allow_regex(qr{LOCK TABLE \w+ IN EXCLUSIVE MODE});
$safedbh->deny_regex(qr{LOCK TABLE pg_});
$safedbh->allow_attribute('PrintError RaiseError');
Look at that. Clean. Composed. A whole lock-and-key situation. π
π¦ DESCRIPTION π¦
So the whole point of this module is that you give your application controlled, limited access to the database instead of just, like, handing it a raw database handle through DBI and praying π. DBIx::Safe acts as a wrapper to the database by only letting through the commands you tell it to. It filters all things related to the database handle β the methods AND the attributes. No crumbs left.
The typical usage, ok so picture this: your application makes a database handle through a normal DBI call to new(), then passes that to DBIx::Safe->new(), which hands you back a DBIx::Safe object. Then you specify exactly what is and what is not allowed, and then you pass the object to the untrusted application. The object acts very similar to a DBI database handle, and in most cases you can use them interchangeably. It's lowkey a body double. π«Ά
By default, nothing is allowed to run at all. Absolutely nothing. Zero. A locked door. And there are so many things you can control:
- which SQL commands are allowed β you do this by indicating the first word in the SQL statement (e.g.
'SELECT') π - which database methods are allowed to run (e.g.
'ping') π - a regular expression that allows matching SQL statements to run (e.g.
'qr{SET TIMEZONE}') β¨ - a regular expression that is NOT allowed to run (e.g.
qr(UPDATE xxx}) π« - which database attributes are allowed to be read and changed (e.g.
'PrintError') π
And for literally every single one of the above, there are matching methods to remove them as well. Symmetry, bestie. We love it here.
π Deciding what statements to allow π
Anytime a statement gets sent to the server via the DBIx::Safe database handle, it gets examined first to see if it's allowed to run or not. There are three major checks that happen when a statement is sent:
- the initial word of the statement, known as the command, gets extracted π΅οΈ
- the entire statement gets checked against the list of denied regular expressions
- the command gets checked against the list of allowed commands
And if there's no match, the statement gets checked against the list of allowed regular expressions. Chain of custody, but make it cute. π
Each DBD may implement additional or slightly different checks. For example, if you're using Postgres, no semi-colons are allowed unless the command is one of SELECT, INSERT, UPDATE, or DELETE, and that's specifically to prevent multiple commands from running. (Those four listed commands can be checked in another way for multiple commands, so they are allowed to have semicolons. Special treatment, deserved.) β¨
π Deciding what attributes to allow π
Database handle attributes are controlled by a single list of allowed keys. If the key is allowed, the underlying database handle value is returned or changed (or both β overachiever behaviour). π«Ά
Heads up bestie: the attribute AutoCommit is never allowed to be changed. Ever. Don't try it.
π Methods π
new()β creates a newDBIx::Safeobject. Requires a mandatorydbhargument containing an active database handle. The optional arguments areallow_command,allow_regex,deny_regex, andallow_attribute. It's giving customizable. πΈallow_command()β specifies which commands are allowed to be used. Can be a whitespace-separated list of words in a string, or an arrayref of such strings. Returns the current list of allowed commands. Duplicate commands will throw an error β no repeats, we're not doing that. πunallow_command()β same asallow_command, but it will remove words from the list. The undo button of your dreams. β©οΈallow_regex()β specifies regular expressions which are allowed to run. The argument must be a regular expression, or an arrayref of regular expressions. Returns the current list. β¨unallow_regex()β same asallow_regex, but it will remove regexes from the list.deny_regex()β specifies regular expressions which are NOT allowed to run. Arguments and return are the same asallow_regex(). The blocklist. π«undeny regex()β same asdeny_regex, but it will remove regexes from the list.allow_attribute()β specifies database handle attributes that are allowed to be changed. By default, nothing can be read. The argument is a whitespace-separated list of words in a string, or an arrayref of such strings. Returns the current list. πunallow_attribute()β same asallow_attributes, but removes attributes from the list.
π¦ Testing π¦
DBIx::Safe has a very comprehensive test suite, so please use it! Bestie, use it. π₯Ί The only thing you should need is a database connection, which you get by setting the environment variables DBI_DSN and DBI_USER (and DBI_PASS if needed).
You can optionally run the module through Perl::Critic by setting the TEST_AUTHOR environment variable. For that you'll need the modules Perl::Critic and Test::Perl::Critic installed. Fancy. π
Please report any test failures to the author or bucardo-general@bucardo.org. π§
πΈ Supported Databases πΈ
Due to the difficulty of ensuring safe access to the database, each type of database must be specifically written into DBIx::Safe. Current databases supported are: Postgres (DBD::Pg). That's the list. It's a short list. It's a curated list. π
β WEBSITE β
The latest version and other information about DBIx::Safe can be found at: http://bucardo.org/dbix_safe/ π
π§ DEVELOPMENT π§
The latest development version can be checked out by using git:
git clone http://bucardo.org/dbixsafe.git/
Go off, clone it, contribute, be the change. π₯
π BUGS π
Bugs should be reported to the author or bucardo-general@bucardo.org. Spill the tea, we're listening. π
π AUTHOR π
Greg Sabino Mullane <greg@endpoint.com> β the icon, the moment, the legend. π
π LICENSE AND COPYRIGHT π
Copyright 2006-2007 Greg Sabino Mullane <greg@endpoint.com>.
This software is free to use: see the LICENSE file for details. π«Ά
And that's the whole page, bestie! β¨ One last lil housekeeping note so you know exactly what you're looking at: this was documented as part of perl v5.38.2, dated 2024-03-04. Slay, go forth, and lock down that database. πππ¦
π¦ where this page comes from
- debian trixie: libdbix-safe-perl 1.2.5-4 Β· BSD-2-Clause OR Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu noble: libdbix-safe-perl 1.2.5-4 Β· BSD-2-Clause OR Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu resolute: libdbix-safe-perl 1.2.5-4 Β· BSD-2-Clause OR Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu stonking: libdbix-safe-perl 1.2.5-4 Β· BSD-2-Clause OR Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms