RLS11 — a $ in a substituted user property must not rewrite the predicate (#3171).
MarkupFilterText substitutes user properties into an RLS predicate, and the result is
AND-ed into every RunView read and every Create/Update check by
GetEffectiveRowFilterWhereClause. It used to do that with a STRING replacement, so
$$, $&, $` and $' in a user property were expanded by
String.prototype.replace instead of inserted — rewriting the predicate, which is the
exact outcome the '-escaping on the same line exists to prevent.
Unit tests already prove the substituted STRING is byte-exact. They cannot prove the
result is SQL the server accepts and scopes correctly, which is the half that matters
once the predicate reaches a database. This check closes that: it marks up a
{{UserName}}-scoped filter with each hostile value, asserts byte-exactness, and then
EXECUTES the predicate so a malformed one fails loudly rather than silently widening a
result set.
The principal is a CLONE with the hostile name stamped in memory — the same carrier the
KF checks use — so nothing is written and teardown stays a no-op.
RLS11 — a
$in a substituted user property must not rewrite the predicate (#3171).MarkupFilterTextsubstitutes user properties into an RLS predicate, and the result is AND-ed into every RunView read and every Create/Update check byGetEffectiveRowFilterWhereClause. It used to do that with a STRING replacement, so$$,$&,$`and$'in a user property were expanded byString.prototype.replaceinstead of inserted — rewriting the predicate, which is the exact outcome the'-escaping on the same line exists to prevent.Unit tests already prove the substituted STRING is byte-exact. They cannot prove the result is SQL the server accepts and scopes correctly, which is the half that matters once the predicate reaches a database. This check closes that: it marks up a
{{UserName}}-scoped filter with each hostile value, asserts byte-exactness, and then EXECUTES the predicate so a malformed one fails loudly rather than silently widening a result set.The principal is a CLONE with the hostile name stamped in memory — the same carrier the KF checks use — so nothing is written and teardown stays a no-op.