Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Content Security Policy (CSP) Concerns Due to Inline CSS Injection in Vaul Drawer Library #283

Closed
pieric-ux opened this issue Feb 27, 2024 · 1 comment · Fixed by #417
Closed

Comments

@pieric-ux
Copy link

pieric-ux commented Feb 27, 2024

Content Security Policy (CSP) Concerns Due to Inline CSS Injection in Vaul Drawer Library

Issue Description

Problem

The current implementation of the Vaul Drawer library injects CSS styles directly into the <head> element of the document during the build process. This practice poses a security concern as it does not support the use of nonces, resulting in compatibility issues with Content Security Policy (CSP).

Affected Files

The injection is performed in the Index.mjs file of the library, specifically through the Te function.

// Index.mjs

function Te(e, { insertAt: n } = {}) {
  if (!e || typeof document == "undefined") return;
  let t = document.head || document.getElementsByTagName("head")[0],
    r = document.createElement("style");
  r.type = "text/css";
  if (n === "top" && t.firstChild) {
    t.insertBefore(r, t.firstChild);
  } else {
    t.appendChild(r);
  }
  if (r.styleSheet) {
    r.styleSheet.cssText = e;
  } else {
    r.appendChild(document.createTextNode(e));
  }
}

Te(`
  [vaul-drawer] {
    touch-action: none;
    transition: transform 0.5s cubic-bezier(0.32, 0.72, 0, 1);
  }

  /* ... Other styles ... */
  
  @media (hover: hover) and (pointer: fine) {
    [vaul-drawer] {
      user-select: none;
    }
  }
`);

The injected styles include:

/* src/style.css */

<style type="text/css">
[vaul-drawer] {
  touch-action: none;
  transition: transform 0.5s cubic-bezier(0.32, 0.72, 0, 1);
}
[vaul-drawer][vaul-drawer-direction=bottom] {
  transform: translate3d(0, 100%, 0);
}
[vaul-drawer][vaul-drawer-direction=top] {
  transform: translate3d(0, -100%, 0);
}
[vaul-drawer][vaul-drawer-direction=left] {
  transform: translate3d(-100%, 0, 0);
}
[vaul-drawer][vaul-drawer-direction=right] {
  transform: translate3d(100%, 0, 0);
}
.vaul-dragging .vaul-scrollable [vault-drawer-direction=top] {
  overflow-y: hidden !important;
}
.vaul-dragging .vaul-scrollable [vault-drawer-direction=bottom] {
  overflow-y: hidden !important;
}
.vaul-dragging .vaul-scrollable [vault-drawer-direction=left] {
  overflow-x: hidden !important;
}
.vaul-dragging .vaul-scrollable [vault-drawer-direction=right] {
  overflow-x: hidden !important;
}
[vaul-drawer][vaul-drawer-visible=true][vaul-drawer-direction=top] {
  transform: translate3d(0, var(--snap-point-height, 0), 0);
}
[vaul-drawer][vaul-drawer-visible=true][vaul-drawer-direction=bottom] {
  transform: translate3d(0, var(--snap-point-height, 0), 0);
}
[vaul-drawer][vaul-drawer-visible=true][vaul-drawer-direction=left] {
  transform: translate3d(var(--snap-point-height, 0), 0, 0);
}
[vaul-drawer][vaul-drawer-visible=true][vaul-drawer-direction=right] {
  transform: translate3d(var(--snap-point-height, 0), 0, 0);
}
[vaul-overlay] {
  opacity: 0;
  transition: opacity 0.5s cubic-bezier(0.32, 0.72, 0, 1);
}
[vaul-overlay][vaul-drawer-visible=true] {
  opacity: 1;
}
[vaul-drawer]::after {
  content: "";
  position: absolute;
  background: inherit;
  background-color: inherit;
}
[vaul-drawer][vaul-drawer-direction=top]::after {
  top: initial;
  bottom: 100%;
  left: 0;
  right: 0;
  height: 200%;
}
[vaul-drawer][vaul-drawer-direction=bottom]::after {
  top: 100%;
  bottom: initial;
  left: 0;
  right: 0;
  height: 200%;
}
[vaul-drawer][vaul-drawer-direction=left]::after {
  left: initial;
  right: 100%;
  top: 0;
  bottom: 0;
  width: 200%;
}
[vaul-drawer][vaul-drawer-direction=right]::after {
  left: 100%;
  right: initial;
  top: 0;
  bottom: 0;
  width: 200%;
}
[vaul-overlay][vaul-snap-points=true]:not([vaul-snap-points-overlay="true"]):not([data-state="closed"]) {
  opacity: 0;
}
[vaul-overlay][vaul-snap-points-overlay=true]:not([vaul-drawer-visible="false"]) {
  opacity: 1;
}
@keyframes fake-animation {
  from {
  }
  to {
  }
}
@media (hover: hover) and (pointer: fine) {
  [vaul-drawer] {
    user-select: none;
  }
}
</style>

Issue Description

Impact on Secure Web Development

The inability to apply a nonce to these styles impacts adherence to best practices in secure web development.

Requested Action

I propose addressing this issue by enhancing the Vaul Drawer library to support nonces for injected styles. This improvement would enable users to seamlessly integrate the library into applications with a strict Content Security Policy (CSP).

Additional Context

The injected styles include critical elements for the functionality of the Vaul Drawer, and without the ability to use a nonce, users face challenges in maintaining a secure application environment. The issue particularly affects users who prioritize CSP in their web applications and seek a more robust security posture.

Proposed Solution

Implement a mechanism within the Vaul Drawer library to allow users to specify a nonce for the injected styles. This enhancement would align with best practices for secure web development and provide a more flexible integration process for users with stringent CSP policies.

Thank you for your attention to this matter, and I appreciate your efforts to continually improve the Vaul Drawer library.

Sincerly,
Demont Pieric

@r34son
Copy link

r34son commented May 10, 2024

That's why: previously lib was using the injectStyles option from tsup.
egoist/tsup#483.

But in #260 @huozhi moved to bunchee which is doing same thing under the hood

Question: Can i somehow use libs with css that are built with bunchee without specifying 'unsafe-inline' in CSP?

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 a pull request may close this issue.

2 participants