Using a data uri in Forge

I get this error in my browser console when working with Forge Custom UI:

Refused to connect to 'data:image/svg+xml;base64,<STUFF>' because it violates the document's Content Security Policy.

I have tried all of the following and they fail to lint:

permissions:
  external:
    images:
      - 'data:*' < invalid
      - 'data:' < invalid
      - 'data' < invalid

I would argue that a data uri is technically not external so I also tried the following, which also fails to lint:

permissions:
  content:
    images:  < invalid
      - 'data:'

I also tried:

permissions:
  fetch:
    client:
      - '*'

Which gives:

index-wWxwMUh6.js:128 Refused to connect to 'data:image/svg+xml;base64,<STUFF>' 
because it violates the following Content Security Policy directive: 
"connect-src 'self' https://api.atlassian.com/metal/ingest *". 
Note that '*' matches only URLs with network schemes ('http', 'https', 'ws', 'wss'), 
or URLs whose scheme matches `self`'s scheme. 
The scheme 'data:' must be added explicitly.

Any tips or suggestions on how this should work?

The ‘data:’ property seems to be correct for this per Content Security Policy "data" not working for base64 Images in Chrome 28 - Stack Overflow

11 Likes

Looks like I got to 10 likes here so a few vendors also care about this. Any chance you can ping the relevant team for a response here @ibuchanan / @tpettersen ?

Hi @BPB , do you have a code snippet on how you’re trying to render your data URI ?
I have an example here of using a data URI in an image tag and this works without any permissions required in the manifest

export const App = () => {
  return (
    <div>
      <img
        src="data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
        alt="star"
        width="16"
        height="16"
      />
    </div>
  );
};

image

1 Like

Try something like this:


    const containerRef = useRef<HTMLDivElement>(null);

    useEffect(() => {
        console.log("Script running from useEffect");
        // Creating and appending an image element, similar to your original script code
        if (containerRef.current) { // Check if the ref.current is not null
            console.log("Container ref is not null");
            const image = new Image();
            image.src = "data:image/svg+xml;base64,<STUFF>";
            image.alt = "Dynamic Image";
            image.style.height = "auto";
            image.style.objectFit = "cover";
            containerRef.current.appendChild(image); // Append the image to the div
        }
    }, []);


<div ref={containerRef} style={{ maxWidth: "600px" }} /> 
1 Like

I’ve used this example and had no issues with getting the image to render

  const containerRef = React.useRef<HTMLDivElement>(null);

  React.useEffect(() => {
    console.log("Script running from useEffect");
    // Creating and appending an image element, similar to your original script code
    if (containerRef.current) {
      // Check if the ref.current is not null
      console.log("Container ref is not null");
      const image = new Image();
      image.src =
        "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='40' stroke='green' stroke-width='4' fill='yellow' /%3E%3C/svg%3E";
      image.alt = "Dynamic Image";
      image.style.height = "auto";
      image.style.objectFit = "cover";
      containerRef.current.appendChild(image); // Append the image to the div
    }
  }, []);

  return <div ref={containerRef} style={{ maxWidth: "600px" }} />;

1 Like

Thanks for trying this @QuocLieu .You are using svg+xml directly:

Mine is base64 encoded:

            image.src = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMTAwIDEwMCIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHBhdGggZD0iTTY4Ljc1LDVoLTM3LjVDMzAuNTYsNSwzMCw1LjU2LDMwLDYuMjVWMTBoLTcuNWMtNC4xMzYsMC03LjUsMy4zNjQtNy41LDcuNXY3MGMwLDQuMTM2LDMuMzY0LDcuNSw3LjUsNy41aDU1ICBjNC4xMzYsMCw3LjUtMy4zNjQsNy41LTcuNXYtNzBjMC00LjEzNi0zLjM2NC03LjUtNy41LTcuN...QuMTE2bC00LjExNi00LjExNmMtMC40ODgtMC40ODgtMS4yNzktMC40ODgtMS43NjgsMCAgcy0wLjQ4OCwxLjI3OSwwLDEuNzY4bDQuMTE2LDQuMTE2bC00LjExNiw0LjExNmMtMC40ODgsMC40ODgtMC40ODgsMS4yNzksMCwxLjc2OEMyOC4xMSw1OS44NzgsMjguNDMsNjAsMjguNzUsNjAgIHMwLjY0LTAuMTIyLDAuODg0LTAuMzY2bDQuMTE2LTQuMTE2bDQuMTE2LDQuMTE2QzM4LjExLDU5Ljg3OCwzOC40Myw2MCwzOC43NSw2MHMwLjY0LTAuMTIyLDAuODg0LTAuMzY2ICBjMC40ODgtMC40ODgsMC40ODgtMS4yNzksMC0xLjc2OGwtNC4xMTYtNC4xMTZsNC4xMTYtNC4xMTZDNDAuMTIyLDQ5LjE0Niw0MC4xMjIsNDguMzU0LDM5LjYzNCw0Ny44NjZ6Ij48L3BhdGg+PC9zdmc+"

1 Like

Hi @QuocLieu did the example I provided help you to reproduce the issue?

Thanks,
Boris

1 Like

I think SVG probably should not be encoded with base64 - I don’t know why but it didn’t work for me. I’ve been using this online svg-to-data-uri encoder to do conversion for SVGs and it works perfectly for me. The encoder also noted that:

Use encodeURIComponent to encode plain-text files, use base64 to encode binary files

So there might be a reason for why base64 encoding doesn’t work.

1 Like

I appreciate the workaround suggestion. In my case I have a library I use which encodes it as base64 because it works with more than svg/xml. This is also supported by the browser. The only issue here is Forge’s CSP implementation hence I am asking for there to be an appropriate adjustment for how to handle the scenario.

1 Like

Hey @BPB , I tried your example but I was getting an invalid URL error suggesting the data URI is incorrect. I tried this example of a base 64 encoded svg and it’s rendering okay.

export const App = () => {
  return (
    <div>
      <img
        src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMCIgaGVpZ2h0PSIxMCI+PHJlY3Qgd2lkdGg9IjEwIiBoZWlnaHQ9IjEwIiBzdHlsZT0iZmlsbDogcmdiKDAsMCwyNTUpOyIgLz48L3N2Zz4="
        width="16"
        height="16"
      />
    </div>
  );
};

I tried your example in a code sandbox as well and I get the same invalid URL error
https://codesandbox.io/p/sandbox/sleepy-goldwasser-g66dd6?file=%2Findex.html

Forge isn’t intentionally blocking base64 encoded images but if you’re having issues I would suggest either trying a different format or double checking the data URI is correct

1 Like

I don’t think this is correct. For example, I used your SVG yellow circle example and it works fine:

https://codesandbox.io/p/sandbox/elegant-architecture-2xr592?file=%2Findex.html

The error I get within Confluence is not a rendering error, this is a CSP issue that only happens in forge:

index-wWxwMUh6.js:128 Refused to connect to 'data:image/svg+xml;base64,<STUFF>' 
because it violates the following Content Security Policy directive: 
"connect-src 'self' https://api.atlassian.com/metal/ingest *". 
Note that '*' matches only URLs with network schemes ('http', 'https', 'ws', 'wss'), 
or URLs whose scheme matches `self`'s scheme. 
The scheme 'data:' must be added explicitly.

Hi @BPB , I understand. I’m having issues reproducing the error you’re seeing in Forge as I’m getting an invalid URL error instead of the CSP issue that you’re seeing when trying to render your data URI. As this seems like a unique issue, I suggest raising an ECOHELP ticket here: https://ecosystem.atlassian.net/servicedesk/customer/portals so the team can look into this problem more closely and try to debug your issue from there