Attached is a patch against SVN, which closes a number of possible
XSS holes where data is displayed directly to the browser from the
database. In the case where one user can see another's data input into
a database, you run the risk of having sessions stolen or other badness.
Short version: if it didn't come from a trusted place, you better
push all strings through the TT "html" filter before displaying it to a
browser.
diff -uNr maypole/templates/factory/addnew maypole-kees/templates/factory/addnew
--- maypole/templates/factory/addnew 2005-11-12 17:50:29.000000000 -0800
+++ maypole-kees/templates/factory/addnew 2005-11-12 18:01:54.000000000 -0800
@@ -30,7 +30,7 @@
elem.as_XML; %]
</label>
[% IF errors.$col %]
- <span class="error">[% errors.$col %]</span>
+ <span class="error">[% errors.$col | html %]</span>
[% END %]
[% END; %]
diff -uNr maypole/templates/factory/login maypole-kees/templates/factory/login
--- maypole/templates/factory/login 2005-11-12 17:50:29.000000000 -0800
+++ maypole-kees/templates/factory/login 2005-11-12 18:02:27.000000000 -0800
@@ -1,18 +1,20 @@
[% PROCESS macros %]
[% INCLUDE header %]
[% INCLUDE title %]
+[% user_field = config.auth.user_field || "user" %]
+
<div id="title">You need to log in</div>
<div id="login">
[% IF login_error %]
- <div class="error"> [% login_error %] </div>
+ <div class="error"> [% login_error | html %] </div>
[% END %]
<form method="post" action="[% base %]/[% request.path %]">
<fieldset>
<legend>Login</legend>
<label>
<span class="field">Username:</span>
- <input name="[% config.auth.user_field || "user" %]" type="text" />
+ <input name="[% user_field %]" type="text" value="[% cgi_params.$user_field | html %]" />
</label>
<label>
<span class="field">Password:</span>
diff -uNr maypole/templates/factory/macros maypole-kees/templates/factory/macros
--- maypole/templates/factory/macros 2005-11-12 17:50:29.000000000 -0800
+++ maypole-kees/templates/factory/macros 2005-11-12 17:58:19.000000000 -0800
@@ -16,7 +16,7 @@
SET lnk = base _ "/" _ table _ "/" _ command _ "/" _ additional;
lnk = lnk | uri | html;
'<a href="' _ lnk _ '">';
- label;
+ label | html;
"</a>";
END;
%]
@@ -37,7 +37,7 @@
IF object.isa('Maypole::Model::Base');
link(object.table, "view", object.id.join('/'), object);
ELSE;
- object;
+ object | html;
END;
END;
%]
@@ -58,7 +58,7 @@
NEXT IF col == "id";
"<td>";
IF col == "url" AND item.url;
- '<a href="'; item.url; '"> '; item.url; '</a>';
+ '<a href="'; item.url | html; '"> '; item.url | html; '</a>';
ELSIF col == classmetadata.stringify_column;
maybe_link_view(item);
ELSE;
@@ -134,7 +134,7 @@
<table class="view">
<tr>
<td class="field">[% classmetadata.colnames.$string %]</td>
- <td>[% item.$string %]</td>
+ <td>[% item.$string | html %]</td>
</tr>
[% FOR col = classmetadata.columns.list;
NEXT IF col == "id" OR col == string;
@@ -152,7 +152,7 @@
<td class="field">[% classmetadata.colnames.$col; %]</td>
<td>
[% IF col == "url" && item.url; # Possibly too much magic.
- '<a href="'; item.url; '"> '; item.url; '</a>';
+ '<a href="'; item.url | html; '"> '; item.url | html; '</a>';
ELSE;
maybe_link_view(item.$col);
END; %]