toURL() leaves `#` unencoded in text overlays and public IDs
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 82/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- javascript, nodejs, typescript
- Domain
- api
Research direction
The URL is assembled in src/assets/CloudinaryFile.ts, in createCloudinaryURL(), where encodeURI is followed by replace calls for ? and =. Read that chain and compare it with the createCloudinaryLegacyURL output the issue cites, which encodes # as %23. Reproduce with the two snippets in the issue and check that toURL() yields Item%20%231 and a%23b. Done when both URLs contain %23 and the existing URL-generation tests still pass.
Written by the indexing model from the issue text.
Description
toURL() encodes URL segments with encodeURI() and replaces ? and =, leaving # unencoded so any # in a text overlay or public ID starts a URL fragment and truncates the request path.
Reproduction (npm install @cloudinary/[email protected], then run with node --input-type=module):
import { CloudinaryImage } from "@cloudinary/url-gen";
import { source } from "@cloudinary/url-gen/actions/overlay";
import { text } from "@cloudinary/url-gen/qualifiers/source";
import { TextStyle } from "@cloudinary/url-gen/qualifiers/textStyle";
console.log(
new CloudinaryImage("sample", { cloudName: "demo" }, { analytics: false })
.overlay(source(text("Item #1", new TextStyle("Arial", 20))))
.toURL()
);
console.log(
new CloudinaryImage("a#b", { cloudName: "demo" }, { analytics: false }).toURL()
);
Actual output:
https://res.cloudinary.com/demo/image/upload/l_text:Arial_20:Item%20#1/fl_layer_apply/sample
https://res.cloudinary.com/demo/image/upload/a#b
Browsers and fetch() strip #1/fl_layer_apply/sample as the fragment and request /demo/image/upload/l_text:Arial_20:Item%20, which returns HTTP 404 (x-cld-error: Resource not found - l_text:Arial_20:Item). Likewise, /demo/image/upload/a#b requests /demo/image/upload/a.
Expected output:
https://res.cloudinary.com/demo/image/upload/l_text:Arial_20:Item%20%231/fl_layer_apply/sample
https://res.cloudinary.com/demo/image/upload/a%23b
Per the text layer documentation, SDK helper methods escape special URL characters automatically. createCloudinaryLegacyURL in @cloudinary/url-gen encodes # to %23 in both cases, and https://res.cloudinary.com/demo/image/upload/l_text:Arial_20:Item%20%231/fl_layer_apply/sample returns HTTP 200.
In src/assets/CloudinaryFile.ts, createCloudinaryURL() runs encodeURI(...) followed by .replace(/\?/g, '%3F').replace(/=/g, '%3D'), without .replace(/#/g, '%23').
Versions tested: @cloudinary/[email protected] (npm latest, with @cloudinary/[email protected]) and master at 8f61b55, on Node.js v26.13.0.
Credit: https://ucsbplse.github.io/
- Dominant language
- HTML
- Stars
- 56
- Forks
- 11
- PR merge metrics
- No merged PRs in 30d
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- No contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from cloudinary/js-url-gen
-
Difficulty 2/5 1-3 hours Newbie friendliness 35/100
cloudinary/js-url-gen#606 · 1 comment ·
-
Difficulty 4/5 3-5 days Newbie friendliness 20/100
cloudinary/js-url-gen#600 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 35/100
cloudinary/js-url-gen#588 ·
-
Difficulty 5/5 Over a week Newbie friendliness 25/100
cloudinary/js-url-gen#587 · 4 comments ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 25/100
cloudinary/js-url-gen#572 · 1 comment ·
All issues in cloudinary/js-url-gen
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
openwisp/openwisp-monitoring#889 ·
Maintainers usually reply within 2 days
-
Old /download.php attachment links: redirect drops the subfolder, nginx.example.conf returns 404OpenBug
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 1 day
-
IsTextFile reads the whole file into memory (OOM on large files in the file watcher)Possibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
gtsteffaniak/filebrowser#3395 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
Maintainers usually reply within 1 day
-
area: csp area: css area: http-headers area: web ui bug difficulty: easy frontend good first issue help wanted javascript journey: first-visit priority: P3 quality tech: css tech: html typescript ui user-experience
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day