DEV-1815: stop apiUrl example from leaking Fliplet auth headers to third parties - #290
Conversation
…ird parties The "Using Custom API URL" example showed Fliplet.API.request() with apiUrl pointed at an external service. Fliplet's Auth-token/Authorization headers are attached unconditionally regardless of apiUrl, so following that example leaks the user's Fliplet session credentials to whatever third-party host is set. Replaces the example with a legitimate Fliplet-owned-host use case, adds an explicit warning against pointing apiUrl at third parties, and points readers to fetch() with the third party's own credentials instead. Follow-up from fliplet-studio PR #8851 (DEV-1802) review, where this doc example was found to contradict the fix being made to the V3 AI builder prompt.
DEV-1815: stop apiUrl example from leaking Fliplet auth headers to third parties
zeryabkhan91
left a comment
There was a problem hiding this comment.
Code review (via /fliplet-pr-review)
Summary
Release PR promoting release/DEV-1815 → master. Rewrites the apiUrl section of docs/API/core/api.md: replaces the old "Using Custom API URL" example (which pointed apiUrl at a third-party host) with a Fliplet-owned-host example, and adds an explicit warning that Fliplet's Auth-token/Authorization headers are attached regardless of the override.
Regression Risk
Docs-only, no runtime path — near-zero blast radius. The change is a net security improvement: it removes a published example that leaked session credentials.
Verified: the central security claim is true
I checked this against SDK source rather than the docs, since the docs are what this PR says were wrong. In fliplet-api/public/assets/fliplet-core/1.0/core.js:
:1813—let apiUrl = options.apiUrl || Fliplet.Env.get('apiUrl');:1820—options.url = apiUrl + options.url;(plain concatenation, so a full external URL passed asurlis appended to the base — this also confirms the "malformed request" claim made in the sibling Studio PR):1825-1827—if (!options.headers['Auth-token']) { options.headers['Auth-token'] = Fliplet.User.getAuthToken(); }— no host check anywhere:1831— converted toAuthorization: Bearer <btoa(token)>
The leak is real and the new warning text is accurate.
Acceptance Criteria (DEV-1815)
| Criterion | Verdict |
|---|---|
Example no longer points apiUrl at a third-party host |
✅ api.md:131-145 |
| Explicit warning that auth headers still attach | ✅ api.md:147, reinforced at :39 and :162 |
Point readers to fetch() with the third party's own credentials |
✅ api.md:147 |
| Example is correct as written | ❌ see inline comment on api.md:140 |
Warning 1 — non-existent hostname
Left inline on docs/API/core/api.md:140, with a one-line suggestion.
Flagging for visibility: the DEV-1815 sign-off comment ("Fix is correct and complete") explicitly lists api-eu.fliplet.com as verified, so this one slipped through that check too — no criticism intended, it's an easy string to read past.
Warning 2 — docs/.well-known/llms-full.txt wasn't regenerated (no diff line to anchor to)
This file is a committed build artifact — "concatenated markdown of all docs", docs/bin/build-agent-indexes.mjs:9, written at :1108. At this PR's head it still contains the old example at llms-full.txt:5326 (url: 'v1/external-service/data') and none of the new warning text.
PR #289's body states the build was run with "no generated index files changed by this wording fix". I ran the repo's own documented command (cd docs && node bin/build-agent-indexes.mjs --strict) at this PR's head: it exits 0 and produces a 19-insertion / 5-deletion diff to llms-full.txt carrying exactly the new warning text. So that claim doesn't hold.
Scope, stated precisely so this isn't over-read: the live site is fine. Cloudflare Pages runs the generator at build time — proven by llms-v3-libraries.json carrying generatedAt: 2026-07-23T20:33:54Z live vs 2026-07-22T13:41:33Z committed, i.e. later than the last docs/ commit. So developers.fliplet.com/.well-known/llms-full.txt will pick up the fix on merge, and this is not a live exposure. What's wrong is repo drift: the tracked artifact disagrees with source, anyone reading the file in git gets the old example, and the next person to regenerate inherits an unrelated diff in their PR. The repo's own convention agrees — master carries cb6d473 "DEV-1545: regenerate llms-full.txt from source (review fix)", i.e. exactly this, caught in review on the previous docs PR.
Fix: cd docs && npm run build:agent-indexes, then commit docs/.well-known/llms-full.txt only — llms-v3-libraries.json changes only its generatedAt stamp, so leave that one out.
Worth noting neither CI gate can catch this: docs-validate.yml runs check:docs, which regenerates in place and only validates frontmatter, and docs-freshness-check.yml compares deploy lag rather than artifact-vs-source. A git diff --exit-code step after the strict build would close the gap permanently.
Suggestion
api.md:136 says "another Fliplet-owned API host (e.g. a regional deployment)" — naming the three real hosts inline would make the correct values unmissable.
Notes
- Branch strategy correct:
release/DEV-1815→masteris the release-PR shape. - The release diff is byte-identical to feature PR #289's, so no unreviewed commits rode along.
- No
?auth_token=in added lines (DEV-1231 clean). No hotspot files touched.
CI Status
Green — Cloudflare Pages, "Frontmatter + unit tests", and ci/circleci: build all pass.
Verdict
COMMENT — the security fix is correct and well-verified, and the change is a clear improvement. Two things to fix first: the non-existent hostname (one line) and regenerating the committed index. Neither is a design problem.
Related: the sibling Studio PR #8860 (DEV-1802) has a line coupled to this one — once this merges, its prompt text asserting the official docs are wrong becomes stale. Commented there.
| url: 'v1/external-service/data', | ||
| apiUrl: 'https://custom-api.example.com/', | ||
| url: 'v1/apps/123', | ||
| apiUrl: 'https://api-eu.fliplet.com/', |
There was a problem hiding this comment.
Warning — this replacement example uses a hostname that doesn't exist.
There is no api-eu.fliplet.com. Verified three ways:
getent hosts api-eu.fliplet.comreturns no DNS record, and curl cannot connect (000). For contrast,api.fliplet.comresolves via CloudFront and returns401as expected for this endpoint without a token.fliplet-api/config/production.jsongives the real regional hosts ashttps://api.fliplet.com/(EU,:16),https://us.api.fliplet.com/(US,:30),https://ca.api.fliplet.com/(CA,:44).- The string appears zero times across the 132 API-hostname references in
docs/(which useapi.fliplet.com90×,us.16×,ca.16×).
Since the point of this PR is doc accuracy, it's worth not shipping an example that fails on copy-paste. Minimal exact fix:
| apiUrl: 'https://api-eu.fliplet.com/', | |
| apiUrl: 'https://api.fliplet.com/', |
One caveat on that suggestion: EU is already the default apiUrl for EU-hosted apps, so the line above technically demonstrates an override that overrides nothing. https://us.api.fliplet.com/ would illustrate the feature better — but I couldn't verify whether a region-prefixed token is accepted cross-region, so I'm not suggesting it blind. Worth confirming before publishing cross-region override as the blessed use case.
The rest of the section is accurate — I verified the credential-leak claim against SDK source (see the review summary).
There was a problem hiding this comment.
Fixed in ca27d85 — swapped in https://api.fliplet.com/ (your suggested value) and regenerated llms-full.txt via the docs build script so it matches source. Left llms-v3-libraries.json out of the commit since its only diff was the generatedAt stamp, as you noted.
…ll.txt api-eu.fliplet.com does not resolve; the real EU host is api.fliplet.com per fliplet-api's production config. Addresses PR review comment.
Deploying fliplet-cli with
|
| Latest commit: |
ca27d85
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://898e528e.fliplet-cli.pages.dev |
| Branch Preview URL: | https://release-dev-1815.fliplet-cli.pages.dev |
Summary
apiUrlusage doesn't leak Fliplet auth headers to third-party endpointsTest plan