Laminas Escaper

repository·2.19.x·Indexed 42 days ago

https://github.com/laminas/laminas-escaper

A security-focused PHP component providing contextual escaping to protect applications against Cross-Site Scripting (XSS) vulnerabilities. It provides specialized methods for escaping data in HTML body, HTML attributes, JavaScript, CSS, and URL contexts via the Laminas\Escaper\Escaper class.

Tokens
4.4K
Snippets
19
Records
24
Agent score
48%

What's inside Laminas Escaper

  1. Overview of laminas-escaper

    2.19.x
    laminas-escaper is a security component designed to defend against Cross-Site Scripting (XSS) and related vulnerabilities. It provides contextual escaping based on peer-reviewed rules, allowing developers to safely escape output for different web contexts where standard PHP functions may be insufficient or misapplied.
  2. Ensure encoding consistency between Escaper and HTML document

    2.19.x

    A common security mistake is using a different encoding for the Escaper instance than the one declared in the HTML document. This mismatch can lead to incorrect escaping and potential vulnerabilities.

    Correct Pattern:

    1. Set the Escaper encoding (e.g., 'utf-8').
    2. Set the HTTP Content-Type header to match (e.g., text/html; charset=UTF-8).
    3. Set the HTML <meta> charset tag to match (e.g., <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">).
    // Good: Encodings match
    $escaper = new Laminas\Escaper\Escaper('utf-8');
    header('Content-Type: text/html; charset=UTF-8');
    
    echo $escaper->escapeHtml($input);
  3. Use Laminas\Escaper\Escaper for contextual escaping

    2.19.x

    The core of the component is the Laminas\Escaper\Escaper class. It provides five specific methods for escaping data based on the output context. To prevent Cross-Site Scripting (XSS), you must select the method that matches the specific context where the data will be rendered:

    • escapeHtml: Use for data being placed inside an HTML body.
    • escapeHtmlAttr: Use for data being placed inside an HTML attribute.
    • escapeJs: Use for data being placed inside a JavaScript context.
    • escapeCss: Use for data being placed inside a CSS context.
    • escapeUrl: Use for data being placed inside a URI or URI parameter.

    Note: It is the developer's responsibility to ensure the correct method is used for the intended context.

    use Laminas\Escaper\Escaper;
    
    $escaper = new Escaper();
    // Example usage:
    $safeHtml = $escaper->escapeHtml($unsafeString);
  4. Why standard HTML escaping is insufficient for HTML attributes

    2.19.x

    Standard HTML escaping (e.g., htmlspecialchars()) is only safe for HTML attributes if you can guarantee the attribute is properly quoted.

    There are two primary risks when using standard escaping instead of escapeHtmlAttr():

    1. Single Quoted Attributes: By default, htmlspecialchars() uses the ENT_COMPAT flag, which does not escape single quotes ('). An attacker can use a single quote to break out of a single-quoted attribute and inject new attributes like onmouseover.
    2. Unquoted Attributes: In HTML5, attributes do not require quotes. Standard escaping does not account for characters like spaces or equals signs that allow an attacker to break out of an unquoted attribute context.

    Always use escapeHtmlAttr() to handle these edge cases automatically.

  5. Why json_encode() is insufficient for Javascript in HTML

    2.19.x

    Using json_encode() to escape data intended for JavaScript literals inside an HTML document is unsafe. json_encode() does not escape characters that might be interpreted as HTML entities or structural HTML tags, which can allow an attacker to break out of the JavaScript string and execute arbitrary code (XSS).

    Always use Laminas\Escaper\Escaper::escapeJs() instead of json_encode() when the output is being placed inside a <script> block in an HTML document.

    <?php
    // BAD: Vulnerable to XSS in HTML context
    $input = 'bar&quot;; alert(&quot;Meow!&quot;);';
    $output = json_encode($input);
    ?>
    <script>
        var foo = <?= $output ?>;
    </script>
    
    <?php
    // GOOD: Safe against XSS
    $escaper = new Laminas\Escaper\Escaper('utf-8');
    $output = $escaper->escapeJs($input);
    ?>
    <script>
        var foo = "<?= $output ?>";
    </script>
  6. How contextual escaping works in laminas-escaper

    2.19.x

    laminas-escaper provides specialized methods for escaping data based on the specific context in which the data will be rendered. This is necessary because a single escaping strategy (like HTML entity encoding) is insufficient for all web contexts (like JavaScript, CSS, or URLs) and can be bypassed if the wrong method is used.

    To use the library, you instantiate the Laminas\Escaper\Escaper class with the target character encoding (typically 'utf-8'). The escaper then performs the following lifecycle for every method call:

    1. Ensures the input data is UTF-8 encoded.
    2. Performs context-specific escaping based on peer-reviewed OWASP rules.
    3. Encodes the escaped data back to the original encoding.
    4. Returns the safe string to the caller.

    Supported Contexts:

    • HTML Body: For content placed between HTML tags.
    • HTML Attribute: For content placed inside HTML attributes (e.g., value="...").
    • Javascript: For data being placed inside <script> blocks or JS variables.
    • CSS: For data being placed inside <style> blocks or inline style attributes.
    • URL/URI: For data being placed in URL parameters or paths.
    $escaper = new Laminas\Escaper\Escaper('utf-8');
    
    // Example of how the same input is escaped differently per context
    $input = '<script>alert("laminas")</script>';
    
    echo $escaper->escapeHtml($input);
    echo $escaper->escapeHtmlAttr($input);
    echo $escaper->escapeJs($input);
    echo $escaper->escapeCss($input);
    echo $escaper->escapeUrl($input);
  7. Distinguish between escaping output and filtering input

    2.19.x

    A critical distinction in using laminas-escaper is its purpose: it is strictly for escaping data for output to prevent XSS.

    Do not use laminas-escaper for filtering input data. For input sanitization and filtering, use alternative tools such as:

    • laminas-filter
    • HTMLPurifier
    • PHP's built-in Filter functionality
  8. Escape data for URLs using escapeUrl()

    2.19.x

    To prevent XSS attacks when inserting dynamic data into a URL, use the escapeUrl() method.

    Important: URL escaping should only be applied to the specific data being inserted into a URL parameter or path, not to the entire URL string itself.

    Internally, escapeUrl() acts as an alias for PHP's rawurlencode(), adhering to RFC 3986.

    $input = '" onmouseover="alert(\'laminas\')';
    $escaper = new Laminas\Escaper\Escaper('utf-8');
    $output = $escaper->escapeUrl($input);
    
    // Use $output when building your URL
    $url = "http://example.com/?name=" . $output;
  9. Handle nested contexts and DOM-based XSS

    2.19.x

    When dealing with DOM-based XSS—where JavaScript in a template inserts data into the DOM—a single layer of escaping is often insufficient. If you only escape for HTML, the string might still contain malicious JavaScript. If you only escape for JavaScript, the string might contain HTML markup that gets parsed when injected.

    Best Practice: Use multiple levels of escaping for nested contexts. For example, if you are placing a string inside a JavaScript variable that will eventually be inserted into the HTML DOM, you should escape the string for HTML first (to make it safe for DOM insertion), and then escape it for JavaScript (to make it safe for the current JavaScript context).

  10. Escape data for the Javascript context

    2.19.x

    When embedding data within JavaScript string literals in HTML, standard ECMAScript or JSON escaping (like json_encode()) is insufficient because it does not account for how browsers interpret JavaScript as HTML. To prevent XSS vulnerabilities, use Laminas\Escaper\Escaper::escapeJs().

    This method applies an extended set of escaping rules that converts potentially dangerous characters into hexadecimal or Unicode escapes, leaving only basic alphanumeric characters, commas, periods, and underscores unescaped. This prevents the browser from misinterpreting JavaScript markup as HTML entities or special characters.

    <?php
    $input = 'bar&quot;; alert(&quot;Meow!&quot;); var xss=&quot;true';
    
    $escaper = new Laminas\Escaper\Escaper('utf-8');
    $output = $escaper->escapeJs($input);
    ?>
    
    <script type="text/javascript">
        // The output is safely escaped for use in a JS literal
        var foo = "<?= $output ?>";
    </script>