UXP Manifest Network Permission Denied for Fetch, Despite "domains: all"

Hi UXP Developers,

I’m encountering a persistent issue with network permissions in my Photoshop UXP plugin (Manifest V5) and hoping someone might have insights.

Environment:

  • Photoshop Version: [Enter Your Exact Photoshop Version - e.g., 25.7.0, 26.x.x]
  • Operating System: [Enter Your OS - e.g., macOS Sonoma 14.x, Windows 11 Pro Version 23H2]
  • UXP Developer Tool Version: [Enter UDT Version if known, otherwise mention “Latest”]

Problem:

My plugin needs to make Workspace requests to two domains:

  1. https://api.cloud.scenario.com (For initial API calls)
  2. https://cdn.cloud.scenario.com (To download generated image assets linked from the first API’s response)

Calls to api.cloud.scenario.com work perfectly fine using standard Basic Authentication.

However, Workspace calls to URLs starting with https://cdn.cloud.scenario.com/... consistently fail with the error: Permission denied to the url https://cdn.cloud.scenario.com/.... Manifest entry not found.

This happens even when my manifest.json includes the broadest possible network permission: "requiredPermissions": { "network": { "domains": "all" } }.

Minimal Test Case:

To isolate the issue, I created a brand new minimal plugin with just a button to fetch a sample CDN URL:

manifest.json:

JSON{ "id": "com.example.cdntest.minimal", "name": "Minimal CDN Fetch Test", "version": "1.0.0", "host": [ { "app": "PS", "minVersion": "23.0.0" } ], "manifestVersion": 5, "requiredPermissions": { "network": { "domains": "all" /* Using 'all' */ } }, "entrypoints": [ { "type": "panel", "id": "panel", "label": { "default": "CDN Test" }, "main": "index.html" } ] }

index.html:

HTML<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Test</title><style>body{padding:10px;background-color:#333;color:white;font-family:sans-serif;} button{padding:8px 15px; margin:10px 0;} .status{ padding: 10px; border-radius: 4px; display: none; border: 1px solid transparent; min-width: 200px; text-align: center; } .status-error { background-color: #ffebee; color: #c62828; border-color: #ef9a9a; } .status-success { background-color: #e8f5e9; color: #2e7d32; border-color: #a5d6a7; } .status-info { background-color: #e3f2fd; color: #1565c0; border-color: #90caf9; }</style></head><body><h2>CDN Fetch Test</h2><button id="fetchBtn">Fetch CDN URL</button><p id="status" class="status">Click button...</p><script src="main.js"></script></body></html>

main.js:

`JavaScriptconsole.log(“Minimal CDN Test main.js loaded.”);
const fetchBtn = document.getElementById(“fetchBtn”);
const statusEl = document.getElementById(“status”);
// Example URL known to work in browser, taken from previous API response logs
const testUrl = “https://cdn.cloud.scenario.com/assets-transform/asset_Hn6AvExcCcnJdyvWwYWdkV1k?p=100&Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly9jZG4uY2xvdWQuc2NlbmFyaW8uY29tL2Fzc2V0cy10cmFuc2Zvcm0vYXNzZXRfSG42QXZFeGNDY25KZHl2V3dZV2RrVjFrP3A9MTAwKiIsIkNvbmRpdGlvbiI6eyJEYXRlTGVzc1RoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTc0NDY3NTE5OX19fV19&Key-Pair-Id=K36FIAB9LE2OLR&Signature=i0DjRH0u65kKpvwK-nCb2yMPEwSRKe5iWYzBQY2JOeOIDUsRwy9yqd8hRzgRBRJzF6sGpLfs0JyEV5n8UJFmsq4kgS9VpKdzoBt-cO0mqz43DtixD4BzaOvtS974B4SwK474Du0Ay2omXWOiXdCVz4kzw4f6TT1cHsr0CREFrrTUDtti4PX4ErkYXBvy~3CGtxbC3yDSmGyohQLd6P~B9H2MSr861CpZi1xvhCX-V4t5P4MRD9jKNXzff-a8jxXaLmqTnXAR3ewnqo8tX88n3r0ET5HsURu2AkxE5pG7ziWxmovp1zZ1tcxnuZK0fneS-uQ-9gDHBGYs91zbv3nqMA__”;

function showStatus(message, type = “info”) { try { if (statusEl) { statusEl.textContent = message; statusEl.className = status status-${type}; statusEl.style.display = “block”; } } catch (error) { console.error(“Error showing status:”, error); } }

fetchBtn.onclick = async () => {
statusEl.textContent = “Fetching…”; statusEl.className = “status status-info”; statusEl.style.display = “block”;
console.log(“Attempting fetch to:”, testUrl);
try {
const response = await fetch(testUrl);
console.log(“Fetch response status:”, response.status);
statusEl.textContent = Workspace Status: ${response.status};
if (!response.ok) {
const body = await response.text(); console.error(“Fetch failed. Body:”, body);
throw new Error(HTTP error! status: ${response.status});
}
const blob = await response.blob();
console.log(“Fetch successful! Blob size:”, blob.size, “Type:”, blob.type);
showStatus(Success! Blob Size: ${blob.size}, “success”);
} catch (e) {
console.error(“Fetch error:”, e);
const errorMessage = e.message || String(e);
showStatus(Error: ${errorMessage}, “error”);
if (errorMessage.includes(“Permission denied”) && errorMessage.includes(“Manifest entry not found”)) {
statusEl.textContent = Error: STILL Permission Denied! Manifest not working.;
console.error(“Manifest wildcard permission STILL not working!”);
}
} finally {
fetchBtn.disabled = false;
}
};
console.log(“Minimal DOM Loaded, listener added.”);`

Steps Taken:

  1. Created a new plugin folder with only the 3 files above.
  2. Verified manifest.json is syntactically correct and requiredPermissions.network.domains is set to "all".
  3. Closed Photoshop completely.
  4. Launched Photoshop.
  5. Used UXP Developer Tools > “Load Unpacked” to load the manifest.json from the new folder. UDT reported “Loaded” successfully.
  6. Opened the UXP Debugger Console. No errors appeared on load.
  7. Clicked the “Fetch CDN URL” button in the plugin panel.

Expected Result:

A 200 OK status for the fetch request in the console, followed by blob details and a “Success” message in the panel.

Actual Result:

The console still shows the following error:

Fetch error: f: Permission denied to the url https://cdn.cloud.scenario.com/assets-transform/asset_Hn6AvExcCcnJdyvWwYWdkV1k?p=100&Policy=[...]. Manifest entry not found. at Object._validateURL (uxp://uxp-internal/runtime_scripts_loader.js:2:30950) at Object.throwIfNoPermission (uxp://uxp-internal/runtime_scripts_loader.js:2:31475) at z.open (uxp://uxp-internal/netjs_scripts.js:2:88830) at z.open (uxp://uxp-internal/devtools_scripts.js:1:20684) at uxp://uxp-internal/netjs_scripts.js:2:616900 at new Promise (<anonymous>) at e.fetch (uxp://uxp-internal/netjs_scripts.js:2:615824) at HTMLButtonElement.fetchBtn.onclick (main.js:19:24) at P (uxp://uxp-internal/domjs_scripts.js:2:12182)

The panel status also shows the “STILL Permission Denied! Manifest not working.” error.

Troubleshooting Done:

  • Confirmed the target URL works fine when opened directly in a browser.
  • Confirmed that Workspace calls to https://api.cloud.scenario.com do work correctly from the same plugin environment when that domain is listed (or with "domains": "all").
  • Tried listing domains explicitly ("https://api...", "https://cdn...").
  • Tried using a wildcard ("https://*.scenario.com").
  • Tried using "all".
  • Ensured requiredPermissions is a top-level key in the manifest.
  • Performed strict reload process (Close PS, verify files, Launch PS, Load Unpacked via UDT, check UDT status).
  • Tried wrapping the Workspace call in core.executeAsModal (same permission error occurred).

Question:

Is this a known bug with manifest network permissions (especially "all" or specific CDN domains) in Photoshop [Your Photoshop Version] on [Your OS Version]? Is there any other reason why the UXP environment would ignore a valid "domains": "all" entry in a correctly loaded manifest and deny permission to fetch a standard HTTPS URL? Are there deeper caches that need clearing or other environment factors to check?

Any help or insight would be greatly appreciated! Thanks.

main.html should not be in entrypoints array.

I think UXP Validator should warn about this… if not I should fix it :smiley: