Skip to content

Conversation

@munishchouhan
Copy link
Member

Summary

Fixed Content Security Policy (CSP) violations preventing copy and download functionality in Wave UI by replacing all inline event handlers with data attributes and external JavaScript event listeners.

Problem

Users encountered CSP violations when clicking copy and download buttons:

Executing inline event handler violates the following Content Security Policy directive
'default-src 'self''. Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a
nonce ('nonce-...') is required to enable inline execution.

This error blocked all copy and download functionality across Wave view pages (builds, scans, containers, mirrors, inspect).

Root Cause

The application has a strict CSP policy configured in src/main/resources/application.yml:63:

content-security-policy: "default-src 'self'; frame-ancestors 'none'"

This policy blocks all inline JavaScript execution, including inline event handlers like onclick="...". All HBS template files were using inline event handlers, which violated this security policy.

Solution

Replaced all inline event handlers with data attributes and attached event listeners via external JavaScript.

Before (Insecure - CSP Violation)

<button onclick="copyToClipboard('{{digest}}', this)" title="Copy digest">
    <svg>...</svg>
</button>
<button onclick="window.location.href='{{url}}'" title="Download">
    <svg>...</svg>
</button>

After (Secure - CSP Compliant)

<button data-copy="{{digest}}" title="Copy digest">
    <svg>...</svg>
</button>
<button data-download-url="{{url}}" title="Download">
    <svg>...</svg>
</button>

Changes

JavaScript Changes

File: src/main/resources/io/seqera/wave/assets/copy.js

Added Event Listener Initialization

document.addEventListener('DOMContentLoaded', function() {
    // Handle copy buttons with data-copy attribute
    document.querySelectorAll('[data-copy]').forEach(button => {
        button.addEventListener('click', function() {
            const textToCopy = this.getAttribute('data-copy');
            copyToClipboard(textToCopy, this);
        });
    });

    // Handle copy buttons with data-copy-from-element attribute
    document.querySelectorAll('[data-copy-from-element]').forEach(button => {
        button.addEventListener('click', function() {
            const elementId = this.getAttribute('data-copy-from-element');
            const element = document.getElementById(elementId);
            if (element) {
                copyToClipboard(element.textContent, this);
            }
        });
    });

    // Handle download buttons with data-download-url attribute
    document.querySelectorAll('[data-download-url]').forEach(button => {
        button.addEventListener('click', function() {
            const url = this.getAttribute('data-download-url');
            if (url) {
                window.open(url, '_blank');
            }
        });
    });

    // Handle evict from cache button
    const evictButton = document.getElementById('evictFromCacheBtn');
    if (evictButton) {
        evictButton.addEventListener('click', evictFromCache);
    }
});

Fixed evictFromCache Function

  • Moved from inline <script> in container-view.hbs to copy.js
  • Updated to retrieve button reference internally instead of relying on global scope

Checklist

  • All inline onclick handlers removed from HBS files
  • Event listeners properly attached in copy.js
  • Copy functionality tested across all views
  • Download functionality tested across all views
  • Cache eviction tested
  • No CSP errors in browser console
  • Browser compatibility verified
  • Code follows existing patterns and conventions
  • No breaking changes introduced

Signed-off-by: munishchouhan <hrma017@gmail.com>
@munishchouhan munishchouhan linked an issue Jan 20, 2026 that may be closed by this pull request
@munishchouhan munishchouhan self-assigned this Jan 20, 2026
Signed-off-by: munishchouhan <hrma017@gmail.com>
@munishchouhan
Copy link
Member Author

tested in dev

Screen.Recording.2026-01-20.at.08.12.20.mov

Replace multiple querySelectorAll loops with a single click
event listener using event delegation pattern. This simplifies
the code and removes the need for DOMContentLoaded.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@pditommaso
Copy link
Collaborator

Well done. I've trimmed down the JS to a more compact solution replacing multiple querySelectorAll loops with a single click event listener using event delegation pattern. This simplifies the code and removes the need for DOMContentLoaded.

Please give it a try

@munishchouhan
Copy link
Member Author

Well done. I've trimmed down the JS to a more compact solution replacing multiple querySelectorAll loops with a single click event listener using event delegation pattern. This simplifies the code and removes the need for DOMContentLoaded.

Please give it a try

yes its working

@munishchouhan
Copy link
Member Author

Screen.Recording.2026-01-20.at.11.09.53.mov

@munishchouhan
Copy link
Member Author

munishchouhan commented Jan 20, 2026

@pditommaso I cannot merge it because it contains unverified commits

@pditommaso
Copy link
Collaborator

Opps

@pditommaso pditommaso merged commit 22601f1 into master Jan 20, 2026
1 check passed
@pditommaso pditommaso deleted the 968-bug-copy-is-not-working-reports branch January 20, 2026 10:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Copy and download is not working reports

3 participants