[GH-ISSUE #1977] BUG: Full page archives no longer render correctly after the CSP blocklist #1229

Open
opened 2026-03-02 11:55:55 +03:00 by kerem · 7 comments
Owner

Originally created by @dvshenry on GitHub (Sep 24, 2025).
Original GitHub issue: https://github.com/karakeep-app/karakeep/issues/1977

Describe the Bug

When saving a page previously to Karakeep, the page would be saved and if you were to view it as the archived version would format as per the actual page archived. Now it doesn't, not sure why but examples added to the images here.

Image

The above is how it now appears in Karakeep (Archive version) - chosen from the expand arrows on the dashboard.

Image

The above is how it used to look in archive, but now only the screenshot renders as the page was.

Steps to Reproduce

  1. Save website URL
  2. Select options (3 dots)
  3. Select download full page archive
  4. View archived page via three arrows on the saved tile, having selected archived on the menu where default is reader view
  5. Cry in a corner, and put a message on Reddit
  6. Be blown away at the response speed of the creator. Amazing

Expected Behaviour

Page should look like the website itself when you view it as an archive, but it no longer does. The page now is formatted very oddly and is actually unreadable due to the rendering font and colour.

Screenshots or Additional Context

No response

Device Details

Windows 10 & iPhone app

Exact Karakeep Version

vv0.27.1

Have you checked the troubleshooting guide?

  • I have checked the troubleshooting guide and I haven't found a solution to my problem
Originally created by @dvshenry on GitHub (Sep 24, 2025). Original GitHub issue: https://github.com/karakeep-app/karakeep/issues/1977 ### Describe the Bug When saving a page previously to Karakeep, the page would be saved and if you were to view it as the archived version would format as per the actual page archived. Now it doesn't, not sure why but examples added to the images here. ![Image](https://github.com/user-attachments/assets/40529daa-e640-4c9e-88b2-d233515da8ef) The above is how it now appears in Karakeep (Archive version) - chosen from the expand arrows on the dashboard. ![Image](https://github.com/user-attachments/assets/6c523824-337e-4cbf-813d-95afe5ebb067) The above is how it used to look in archive, but now only the screenshot renders as the page was. ### Steps to Reproduce 1) Save website URL 2) Select options (3 dots) 3) Select download full page archive 4) View archived page via three arrows on the saved tile, having selected archived on the menu where default is reader view 5) Cry in a corner, and put a message on Reddit 6) Be blown away at the response speed of the creator. Amazing ### Expected Behaviour Page should look like the website itself when you view it as an archive, but it no longer does. The page now is formatted very oddly and is actually unreadable due to the rendering font and colour. ### Screenshots or Additional Context _No response_ ### Device Details Windows 10 & iPhone app ### Exact Karakeep Version vv0.27.1 ### Have you checked the troubleshooting guide? - [x] I have checked the troubleshooting guide and I haven't found a solution to my problem
Author
Owner

@MohamedBassem commented on GitHub (Sep 28, 2025):

Ok, so this is a side effect of the security fix that I pushed in the last release where we blocked rendering javascript in those archives. If you download the archive itself (from the attachment box on the right) and open it in the browser, it'll load just fine. But inline rendering will get broken. I think I'll have to make a decision on whether it still makes sense to render them at all in karakeep or just offer download links for them.

<!-- gh-comment-id:3343013150 --> @MohamedBassem commented on GitHub (Sep 28, 2025): Ok, so this is a side effect of the security fix that I pushed in the last release where we blocked rendering javascript in those archives. If you download the archive itself (from the attachment box on the right) and open it in the browser, it'll load just fine. But inline rendering will get broken. I think I'll have to make a decision on whether it still makes sense to render them at all in karakeep or just offer download links for them.
Author
Owner

@dvshenry commented on GitHub (Sep 30, 2025):

Thank you so much for your willingness to look at issues so quickly. Love Karakeep and don't want to give it up! :)

<!-- gh-comment-id:3349798279 --> @dvshenry commented on GitHub (Sep 30, 2025): Thank you so much for your willingness to look at issues so quickly. Love Karakeep and don't want to give it up! :)
Author
Owner

@Vaviloff commented on GitHub (Oct 15, 2025):

I've tried a few bookmarks keeper solutions today and was honestly blown away by Karakeep functionality - love the look, the nested lists, the speed!

If I may share my opinion, the full page archive viewer is a handy and needed feature, shame that it works correctly in Linkwarden at the moment.

Maybe a security option in admin or .env file to turn off the CSP (that would be off by default) would suffice?

Anyways, I think I'm gonna stick with KK, thanks for all the hard work made!

<!-- gh-comment-id:3407239320 --> @Vaviloff commented on GitHub (Oct 15, 2025): I've tried a few bookmarks keeper solutions today and was honestly blown away by Karakeep functionality - love the look, the nested lists, the speed! If I may share my opinion, the full page archive viewer is a handy and needed feature, shame that it works correctly in Linkwarden at the moment. Maybe a security option in admin or `.env` file to turn off the CSP (that would be off by default) would suffice? Anyways, I think I'm gonna stick with KK, thanks for all the hard work made!
Author
Owner

@heichaowo commented on GitHub (Jan 1, 2026):

I have a solution to remove CSP, dynamic JavaScript, and sandbox via nginx, After applying, you should be able to view the fully loaded webpage.

    location / {
        proxy_pass http://127.0.0.1:3000;
        
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header Accept-Encoding "";
        
        proxy_hide_header Content-Security-Policy;
        proxy_hide_header Content-Security-Policy-Report-Only;
        
        sub_filter_once off;
        sub_filter_types text/html;
        
        sub_filter '<head>' '<head><script>
    (function() {
        const original = HTMLIFrameElement.prototype.setAttribute;
        HTMLIFrameElement.prototype.setAttribute = function(name, value) {
            if (name.toLowerCase() === "sandbox") {
                console.log("Blocked sandbox setAttribute:", value);
                return;
            }
            return original.call(this, name, value);
        };
        
        Object.defineProperty(HTMLIFrameElement.prototype, "sandbox", {
            set: function(value) {
                console.log("Blocked sandbox property setter:", value);
            },
            get: function() {
                return "allow-scripts allow-same-origin allow-forms allow-popups allow-modals";
            }
        });
    })();
    </script>';

        sub_filter 'sandbox=""' '';
        sub_filter "sandbox=''" '';
        sub_filter 'sandbox="" ' '';
        sub_filter "sandbox='' " '';
     
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        proxy_connect_timeout 120s;
        proxy_send_timeout 120s;
        proxy_read_timeout 120s;
        
        proxy_buffering on;
        proxy_buffer_size 8k;
        proxy_buffers 16 8k;
        proxy_busy_buffers_size 16k;
    }
    
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot|webp)$ {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        
        proxy_hide_header Content-Security-Policy;
        proxy_hide_header Content-Security-Policy-Report-Only;
        
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
<!-- gh-comment-id:3703530081 --> @heichaowo commented on GitHub (Jan 1, 2026): I have a solution to remove CSP, dynamic JavaScript, and sandbox via nginx, After applying, you should be able to view the fully loaded webpage. ``` location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host; proxy_set_header Accept-Encoding ""; proxy_hide_header Content-Security-Policy; proxy_hide_header Content-Security-Policy-Report-Only; sub_filter_once off; sub_filter_types text/html; sub_filter '<head>' '<head><script> (function() { const original = HTMLIFrameElement.prototype.setAttribute; HTMLIFrameElement.prototype.setAttribute = function(name, value) { if (name.toLowerCase() === "sandbox") { console.log("Blocked sandbox setAttribute:", value); return; } return original.call(this, name, value); }; Object.defineProperty(HTMLIFrameElement.prototype, "sandbox", { set: function(value) { console.log("Blocked sandbox property setter:", value); }, get: function() { return "allow-scripts allow-same-origin allow-forms allow-popups allow-modals"; } }); })(); </script>'; sub_filter 'sandbox=""' ''; sub_filter "sandbox=''" ''; sub_filter 'sandbox="" ' ''; sub_filter "sandbox='' " ''; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_connect_timeout 120s; proxy_send_timeout 120s; proxy_read_timeout 120s; proxy_buffering on; proxy_buffer_size 8k; proxy_buffers 16 8k; proxy_busy_buffers_size 16k; } location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot|webp)$ { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; proxy_hide_header Content-Security-Policy; proxy_hide_header Content-Security-Policy-Report-Only; expires 30d; add_header Cache-Control "public, immutable"; } ```
Author
Owner

@MohamedBassem commented on GitHub (Jan 2, 2026):

@claude Add an env variable (as part of the serverConfig) to disable returning CSP headers

<!-- gh-comment-id:3706488083 --> @MohamedBassem commented on GitHub (Jan 2, 2026): @claude Add an env variable (as part of the serverConfig) to disable returning CSP headers
Author
Owner

@claude[bot] commented on GitHub (Jan 2, 2026):

Claude finished @MohamedBassem's task in 2m 51s —— View jobclaude/issue-1977-20260102-2348Create PR ➔


Implementation Complete ✓

I've successfully added an environment variable to disable CSP headers for archived assets.

What was done:

  • Added DISABLE_CSP_HEADERS environment variable to serverConfig (defaults to false)
  • Updated the serveAsset function to conditionally apply CSP headers based on the config
  • Added documentation in the configuration guide with security warnings

Changes Made:

packages/shared/config.ts:

  • Added DISABLE_CSP_HEADERS environment variable (boolean, defaults to false)
  • Added security.disableCspHeaders to the server configuration object

packages/api/utils/assets.ts:

  • Imported serverConfig
  • Wrapped CSP header setting in a conditional check: if (!serverConfig.security.disableCspHeaders)
  • CSP headers are now only set when the feature is NOT disabled

docs/versioned_docs/version-v0.29.0/03-configuration.md:

  • Added documentation for the new environment variable
  • Included a clear security warning about the implications of disabling CSP headers

Usage:

To disable CSP headers and allow JavaScript execution in full page archives, add this to your environment:

DISABLE_CSP_HEADERS=true

Important: This should only be enabled if you understand the security implications and trust the content you're archiving. Disabling CSP headers allows JavaScript execution in archived pages, which could pose security risks.


| Branch: claude/issue-1977-20260102-2348

<!-- gh-comment-id:3706488353 --> @claude[bot] commented on GitHub (Jan 2, 2026): **Claude finished @MohamedBassem's task in 2m 51s** —— [View job](https://github.com/karakeep-app/karakeep/actions/runs/20669062332) • [`claude/issue-1977-20260102-2348`](https://github.com/karakeep-app/karakeep/tree/claude/issue-1977-20260102-2348) • [Create PR ➔](https://github.com/karakeep-app/karakeep/compare/main...claude/issue-1977-20260102-2348?quick_pull=1&title=feat%3A%20add%20DISABLE_CSP_HEADERS%20environment%20variable&body=This%20PR%20adds%20a%20new%20configuration%20option%20to%20disable%20Content%20Security%20Policy%20headers%20for%20archived%20assets.%0A%0A%23%23%20Changes%0A-%20Added%20%60DISABLE_CSP_HEADERS%60%20environment%20variable%20to%20serverConfig%20%28defaults%20to%20false%29%0A-%20Updated%20%60serveAsset%60%20to%20conditionally%20apply%20CSP%20headers%0A-%20Added%20documentation%20with%20security%20warning%0A%0AFixes%20%231977%0A%0A---%0A%0AGenerated%20with%20%5BClaude%20Code%5D%28https%3A%2F%2Fclaude.ai%2Fcode%29) --- ### Implementation Complete ✓ I've successfully added an environment variable to disable CSP headers for archived assets. #### What was done: - [x] Added `DISABLE_CSP_HEADERS` environment variable to serverConfig (defaults to `false`) - [x] Updated the `serveAsset` function to conditionally apply CSP headers based on the config - [x] Added documentation in the configuration guide with security warnings #### Changes Made: **`packages/shared/config.ts`**: - Added `DISABLE_CSP_HEADERS` environment variable (boolean, defaults to false) - Added `security.disableCspHeaders` to the server configuration object **`packages/api/utils/assets.ts`**: - Imported `serverConfig` - Wrapped CSP header setting in a conditional check: `if (!serverConfig.security.disableCspHeaders)` - CSP headers are now only set when the feature is NOT disabled **`docs/versioned_docs/version-v0.29.0/03-configuration.md`**: - Added documentation for the new environment variable - Included a clear security warning about the implications of disabling CSP headers #### Usage: To disable CSP headers and allow JavaScript execution in full page archives, add this to your environment: ```bash DISABLE_CSP_HEADERS=true ``` **Important:** This should only be enabled if you understand the security implications and trust the content you're archiving. Disabling CSP headers allows JavaScript execution in archived pages, which could pose security risks. --- | [Branch: claude/issue-1977-20260102-2348](https://github.com/karakeep-app/karakeep/tree/claude/issue-1977-20260102-2348)
Author
Owner

@urzz commented on GitHub (Jan 28, 2026):

Hi, I'm currently experiencing this issue as well. Is there any update on the progress or a planned timeline for the fix? Thanks! @MohamedBassem

<!-- gh-comment-id:3809526724 --> @urzz commented on GitHub (Jan 28, 2026): Hi, I'm currently experiencing this issue as well. Is there any update on the progress or a planned timeline for the fix? Thanks! @MohamedBassem
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/karakeep#1229
No description provided.