Version: v0.7.1 - Beta.  We welcome contributors & feedback.

TypeStrings

Background 

TypeStrings are THT's approach to preventing injection attacks.

What Are Injection Attacks?

Injection attacks are the #1 security vulnerability on the web.

This occurs when an attacker sends input containing meta-characters (e.g. quotes) that trick the app into executing something different from what was intended.

For example, here is a SQL query to check a login attempt:

// Login query
select * from users
where user = 'admin'
and password = 'knockknock'

An attacker could enter a malicious password that contains a quote, followed by some SQL code, like this:

// ✕ Malicious Input
knockknock' or 1='1
          ^--------

Here is what the query looks like with the new password. It allows the attacker to log in as any user in the system, because the query will always be true.

// ✕ Injection!
select * from users
where user = 'admin'
and password = 'knockknock' or 1='1'
                          ^--------

Attack Targets

Any subsystem is vulnerable to attack if it accepts strings that use meta-characters to embed data.

The most common targets are:

Sidebar: “Just Be Careful” is Not Enough

Unfortunately, it’s not enough to “just be careful and escape everything manually”, for a few reasons:

In short, in thousands of lines of code, there are too many chances for even experienced programmers to overlook something.

How TypeStrings Work 

To prevent injection attacks, THT introduces TypeStrings.

A TypeString is a literal string that is prefixed with a type identifier.

$query = sql'select * from table where userId = {}'
         ^^^

Placeholders

TypeStrings can ONLY be combined with plain, unprotected strings via the use of placeholders ({}).

Placeholders (also known as parameterized queries) are an industry best practice for securing SQL queries by ensuring that all inserted data is safely escaped.

TypeStrings expand this tactic to cover all types of sensitive strings, like URLs, system commands, and HTML.

Why It Works

This approach is effective because:

Altogether, it removes human error from the equation, leading to more consistent protection with less effort.

How to Use TypeStrings 

Just prepend the type to any literal string to mark it as a TypeString.

This tells THT to keep it separate from all other dynamic strings, which often come from outside (untrusted) sources.

Example:

$query = sql'select * from users'

Supported types:

Prefix Description Example
sql SQL query sql'select * from posts'
html HTML markup html'<b>user123</b>'
url URL url'/posts?sort=desc'
cmd System command cmd'ls -l /some/path'
js JavaScript code js'var id = 123;'
css CSS code css'body { color: #333 }'
lm Litemark markup lm'# Contact Info'

Filling Placeholder Values 

You can attach dynamic values to a TypeString via the fill method.

These will be inserted into placeholders (e.g. {}), which will be safely escaped by the TypeString class.

$query = sql'select * from users where userId = {}'

$query.fill($userId)

// The Db module only accepts TypeStrings
$row = Db.selectRow($query)

Combining TypeStrings 

Embedded TypeStrings

If you insert a TypeString into another TypeString of the same type, it will be inserted verbatim.

$name = html'<b>Admin</b>'

html'Posted by: {}'.fill($name)

//= 'Posted by: <b>Admin</b>'

Appending TypeStrings

You can join two TypeStrings together using the stringy ~ operator.

Placeholder values must be filled separately before they are merged.

$query = sql'select title from posts where postDate > {}'

$monthAgo = Date.create('30 days ago')
$query.fill($monthAgo)

// Append a dynamic 'limit' value
$rowsPerPage = 20
$query ~= sql' limit {}'.fill($rowsPerPage)

Templates 

Most TypeStrings have corresponding Template Functions that make it easy to create blocks of content that are safely and parsed and escaped.

// Returns an HTML TypeString

tm headerHtml($userName) {

    <.welcome-banner>
        Welcome back, {{ $userName }}!
    </>
}

Methods 

See the TypeString class for a full list of methods.