boxlang-templating — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited boxlang-templating (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
BoxLang is the AI-native software productivity platform for building, modernizing and running applications, with developers and AI agents working together.
BoxLang's templating language uses .bxm files (BoxLang Markup) to mix HTML with dynamic server-side code. The default mode in .bxm files is HTML output — you embed BoxLang logic using <bx:*> tags and output expressions with #expression#.
| Extension | Default mode | Primary use |
|---|---|---|
.bx | Script | Classes, services, models |
.bxs | Script | Standalone scripts, CLI tools |
.bxm | Tag/markup | Templates, views, HTML pages |
Use #expression# to interpolate values. The expression is evaluated and output is HTML-escaped automatically inside <bx:output>:
<bx:output>
<h1>Hello, #user.name#!</h1>
<p>Today is #dateFormat( now(), "long" )#</p>
<p>Items: #order.items.len()#</p>
</bx:output>Always wrap output in `<bx:output>` — without it, #variable# is treated as a literal string and not evaluated:
<!-- BAD: #name# is printed as literal text, not evaluated -->
<p>#name#</p>
<!-- GOOD: #name# is evaluated and output -->
<bx:output><p>#name#</p></bx:output>For reusable partial templates (app/views/partials/*.bxm), make <bx:output> the wrapper around the rendered HTML block whenever interpolation appears in that block. Keep bx:param and bx:set declarations outside the output block.
<bx:output> — Render Dynamic Content<bx:output>
<p>User: #user.firstName# #user.lastName#</p>
<p>Email: #encodeForHTML( user.email )#</p>
</bx:output>Options:
encodeFor="html" — auto-encode all expressions (recommended for untrusted data)<!-- Auto-encode all output in this block -->
<bx:output encodeFor="html">
<p>#userSuppliedContent#</p>
</bx:output><bx:set> — Declare Variables<bx:set var="greeting" value="Hello, #user.name#!">
<bx:set var="items" value="#productService.getFeatured()#">
<bx:set var="count" value="#items.len()#"><bx:if> / <bx:elseif> / <bx:else> — Conditionals<bx:if condition="#user.isLoggedIn#">
<p>Welcome back, #encodeForHTML( user.name )#!</p>
<bx:elseif condition="#session.hasGuideToken#">
<p>Continue as guest</p>
<bx:else>
<a href="/login">Please log in</a>
</bx:if><bx:loop> — IterationArray loop:
<bx:loop array="#products#" item="product">
<div class="product">
<h3><bx:output>#encodeForHTML( product.name )#</bx:output></h3>
<p><bx:output>$#numberFormat( product.price, "0.00" )#</bx:output></p>
</div>
</bx:loop>Struct loop:
<bx:loop struct="#config#" item="value" key="key">
<bx:output><p>#key#: #value#</p></bx:output>
</bx:loop>Query loop:
<bx:loop query="#users#">
<bx:output>
<tr>
<td>#users.id#</td>
<td>#encodeForHTML( users.name )#</td>
<td>#encodeForHTML( users.email )#</td>
</tr>
</bx:output>
</bx:loop>Index / count loop:
<bx:loop from="1" to="#items.len()#" index="i">
<bx:output><li>#i#. #items[ i ].name#</li></bx:output>
</bx:loop><bx:include> — Include Partial Templates<!-- Reuse header and footer partials -->
<bx:include template="/includes/header.bxm">
<main>
<!-- page content -->
</main>
<bx:include template="/includes/footer.bxm">Pass variables to the included template via the current scope (variables are inherited by default in includes).
<bx:script> — Inline Script BlocksSwitch to script mode within a template:
<bx:script>
var products = productService.getFeatured( limit=6 )
var totalPages = ceiling( products.recordCount / 10 )
</bx:script>
<bx:loop array="#products#" item="p">
<bx:output><div>#p.name#</div></bx:output>
</bx:loop><bx:switch> / <bx:case> — Switch Statements<bx:switch expression="#user.role#">
<bx:case value="admin">
<bx:include template="/views/admin-dashboard.bxm">
</bx:case>
<bx:case value="editor">
<bx:include template="/views/editor-dashboard.bxm">
</bx:case>
<bx:defaultcase>
<bx:include template="/views/user-dashboard.bxm">
</bx:defaultcase>
</bx:switch><bx:try> / <bx:catch> — Error Handling in Templates<bx:try>
<bx:set var="data" value="#remoteService.getData()#">
<bx:output><p>#data.message#</p></bx:output>
<bx:catch type="any" variable="e">
<p class="error">Could not load data: <bx:output>#encodeForHTML( e.message )#</bx:output></p>
</bx:catch>
</bx:try>You can freely mix script blocks and tag components in .bxm files:
<bx:script>
// Load data using script syntax
var pageTitle = "Product Catalog"
var categories = categoryService.getAll()
var featuredIds = url.keyExists( "cat" ) ? [ url.cat ] : []
</bx:script>
<!DOCTYPE html>
<html lang="en">
<head>
<bx:output><title>#encodeForHTML( pageTitle )#</title></bx:output>
</head>
<body>
<nav>
<bx:loop array="#categories#" item="cat">
<bx:output>
<a href="/catalog?cat=#encodeForURL( cat.slug )#"
class="#featuredIds.contains( cat.id ) ? 'active' : ''#">
#encodeForHTML( cat.name )#
</a>
</bx:output>
</bx:loop>
</nav>
</body>
</html><!-- views/layout.bxm -->
<!DOCTYPE html>
<html lang="en">
<head>
<bx:output><title>#pageTitle ?: "My App"#</title></bx:output>
<link rel="stylesheet" href="/css/app.css">
</head>
<body>
<bx:include template="/views/partials/nav.bxm">
<main>
<bx:include template="#contentTemplate#">
</main>
<bx:include template="/views/partials/footer.bxm">
</body>
</html><!-- In a page handler/template -->
<bx:set var="pageTitle" value="Dashboard">
<bx:set var="contentTemplate" value="/views/dashboard-content.bxm">
<bx:include template="/views/layout.bxm">Always encode user-supplied data before rendering:
<bx:output>
<!-- HTML context — encode entities -->
<p>#encodeForHTML( userBio )#</p>
<!-- Attribute context -->
<input value="#encodeForHTMLAttribute( formValue )#">
<!-- URL context -->
<a href="/profile?u=#encodeForURL( username )#">View Profile</a>
<!-- JavaScript context -->
<script>
const name = "#encodeForJavaScript( displayName )#";
</script>
</bx:output>Use <bx:query> for database queries directly in templates (acceptable for simple templates; prefer service layer for complex logic):
<bx:script>
var users = queryExecute(
"SELECT id, name, email FROM users WHERE active = :active ORDER BY name",
{ active: { value: true, cfsqltype: "cf_sql_bit" } }
)
</bx:script>
<table>
<thead><tr><th>Name</th><th>Email</th></tr></thead>
<tbody>
<bx:loop query="#users#">
<bx:output>
<tr>
<td>#encodeForHTML( users.name )#</td>
<td>#encodeForHTML( users.email )#</td>
</tr>
</bx:output>
</bx:loop>
</tbody>
</table>| Mistake | Fix |
|---|---|
#var# outside <bx:output> | Wrap in <bx:output> |
| Raw user data in output | Use encodeForHTML() or encodeFor="html" |
| Logic-heavy templates | Move to service layer; keep templates presentational |
| Missing closing tags | <bx:if> requires </bx:if>, <bx:loop> requires </bx:loop> |
| Unscoped variables | Declare with <bx:set> or <bx:script> var statements |
| Including with absolute OS paths | Use web-root-relative paths: /views/... |
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.