Add a CSP provider class, which allows the users to define CSPs and provide a nonce used for strict-dynamic support

XMLWordPrintable

    • Type: New Feature
    • Resolution: Unresolved
    • Priority: Critical
    • None
    • Affects Version/s: 9.6.2
    • Component/s: None
    • Security Level: Jimmy
    • None

      User Story

      As a webmaster, I want to use CSP to secure my application against attacks.

      Currently, ZK's client-engine requires the following CSP headers: unsafe-inline, unsafe-eval

      These CSP rules are necessary for the Client engine to execute scripts dynamically by creating new script elements in the page, and by creating new Functions for JSON eval and Widget $define instantiation

      The goal is to allow the developer to set stricter CSP, which do not allow all sources unsafe-eval or unsafe-inline.

      Acceptance Criteria

      1. CSP Configuration & Policy

      AC-1.1: Default Behavior (Backward Compatibility)

      1. By default, CSP is disabled
      2. Without configuration, ZK outputs the same headers and scripts as current implementation
      3. Existing applications must work without any code changes when upgrading
      4. CSP feature is opt-in only

      AC-1.2: Enable Basic CSP with Default Policy (HIGH PRIORITY)

      1. Provide simple boolean flag to enable CSP
        <system-config>
            <csp-enabled>true</csp-enabled>
        </system-config>
        
      2. Default policy: script-src 'self' 'unsafe-inline' 'unsafe-eval'
      3. This allows ZK's client-engine to function without code changes
      4. Provides basic CSP protection while maintaining full backward compatibility
      5. Reference: https://docs.zkoss.org/zk_dev_ref/security_tips/content_security_policy

      AC-1.3: Enable Strict-Dynamic Mode (HIGH PRIORITY)

      1. Additional property to enable nonce-based strict CSP
        <system-config>
            <csp-enabled>true</csp-enabled>
            <csp-strict-dynamic-enabled>true</csp-strict-dynamic-enabled>
        </system-config>
        
      2. Strict-dynamic policy: script-src 'self' 'strict-dynamic' 'nonce-{generated}'
      3. Removes 'unsafe-inline' and 'unsafe-eval' from policy
      4. Automatically generates and applies nonces to all ZK scripts
      5. More secure but may require application code review
      6. Disabled by default (CSP3 feature, opt-in)

      AC-1.4: Custom Policy Override (HIGH PRIORITY)

      1. Allow developers to override default policy via XML configuration
      2. Example for default mode:
        <system-config>
            <csp-enabled>true</csp-enabled>
            <csp-policy>script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.google-analytics.com</csp-policy>
        </system-config>
        
      3. Example for strict-dynamic mode:
        <system-config>
            <csp-enabled>true</csp-enabled>
            <csp-strict-dynamic-enabled>true</csp-strict-dynamic-enabled>
            <csp-policy>script-src 'self' 'nonce-{nonce}' 'strict-dynamic' https://www.google-analytics.com</csp-policy>
        </system-config>
        
      4. ZK replaces 'nonce-{nonce}' placeholder with actual generated nonce at runtime
      5. Custom policy completely replaces the default policy
      6. Developer is responsible for ensuring policy allows ZK scripts to execute

      AC-1.5: Multiple CSP Directives Support (MEDIUM PRIORITY)

      1. Support multiple CSP directives beyond script-src
      2. Example with strict-dynamic:
        <csp-policy>
        script-src 'self' 'nonce-{nonce}' 'strict-dynamic';
        style-src 'self' 'unsafe-inline';
        img-src 'self' data: https:;
        font-src 'self';
        connect-src 'self';
        frame-ancestors 'none'
        </csp-policy>
        
      3. Example with default mode:
        <csp-policy>
        script-src 'self' 'unsafe-inline' 'unsafe-eval';
        style-src 'self' 'unsafe-inline';
        img-src 'self' data: https:;
        font-src 'self';
        connect-src 'self';
        frame-ancestors 'none'
        </csp-policy>
        
      4. Support style-src, img-src, font-src, connect-src, frame-ancestors, etc.
      5. Each directive should be configurable independently

      AC-1.6: Advanced Custom Generator Configuration (MEDIUM PRIORITY)

      1. Support advanced use cases with custom CSP header generator class
        <system-config>
            <csp-header-generator-class>my.company.CustomCspGenerator</csp-header-generator-class>
        </system-config>
        
      2. Custom generator class is optional for advanced scenarios
      3. When custom generator is provided, it overrides the default implementation
      4. Can be used with either default CSP or strict-dynamic mode
      5. Provides full control over CSP header generation and nonce management

      AC-1.7: Report-Only Mode (HIGH PRIORITY)

      1. Support CSP report-only mode for testing without breaking application
        <system-config>
            <csp-enabled>true</csp-enabled>
            <csp-strict-dynamic-enabled>true</csp-strict-dynamic-enabled>
            <csp-report-only>true</csp-report-only>
            <csp-report-uri>/csp-violations</csp-report-uri>
        </system-config>
        
      2. In report-only mode, violations are reported but not blocked
      3. Sends Content-Security-Policy-Report-Only header instead of Content-Security-Policy
      4. Essential for testing strict-dynamic mode before enforcing it
      5. Allows developers to identify violations without breaking application

      2. Nonce Generation & Application

      AC-2.1: Default Nonce Generator

      1. ZK provides default nonce generator implementation when strict-dynamic is enabled
      2. Nonce is only generated when csp-strict-dynamic-enabled=true
      3. When strict-dynamic is disabled, no nonce is generated (not needed for unsafe-inline/unsafe-eval mode)
      4. Nonce must be generated per page request (not reused between documents)
      5. Nonce must use cryptographically secure random number generator
      6. Nonce format requirements:
        1. Base64-encoded
        2. Minimum 128-bit entropy (recommended: 256-bit)
        3. Unique across concurrent requests

      AC-2.2: Nonce Application Scope (HIGH PRIORITY)

      When strict-dynamic is enabled (csp-strict-dynamic-enabled=true), ALL ZK-generated scripts must include nonce attribute:

      1. <zk:script> component
      2. <script> directive in ZUL
      3. Scripts from load-addon.xml
      4. <embed> in zk.xml
      5. Server-side generated scripts
      6. Client-side AU (AJAX Update) response scripts
      7. Widget instantiation scripts ($define)
      8. Event listener scripts
      9. Data binding scripts
      10. Dynamically created scripts via WebSocket/Server Push

      When strict-dynamic is disabled (default mode), nonce attributes should not be added to scripts

      AC-2.3: Developer API for Nonce Access (HIGH PRIORITY)

      1. Provide API for developers to access current nonce for their own script tags
      2. API should return null or empty string when strict-dynamic is disabled
      3. Java API:
        String nonce = Executions.getCurrent().getNonce();
        // or
        String nonce = CSPUtil.getNonce(execution);
        // Returns null when csp-strict-dynamic-enabled=false
        
      4. EL Expression support:
        <script nonce="${execution.cspNonce}">
            // custom script
        </script>
        
      5. Developer must only use nonce when strict-dynamic is enabled

      Details

      Another idea

      PageRenderer --> HtmlPageRenders
      Because PageRender is defined in lang.xml and cannot be changed.
      Provide a config to change HtmlPageRenders

            Assignee:
            Unassigned
            Reporter:
            MDuchemin
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: