Found while reviewing the renderer for memory; unrelated to it, and not fixed.
The problem
Every launch logs this, twice:
Refused to connect to moho-media://file/?p=%2Fhome%2Fultra%2F.cache%2Fnobilis%2Fsneedchat-avatars%2F62488.webp
because it violates the following Content Security Policy directive: connect-src 'self' https: wss: ws://localhost:* http://localhost:*
The policy in src/renderer/index.html allows moho-media: in img-src and media-src but not in connect-src, and has since the initial commit - so
this is a fetch()/XHR against a moho-media URL rather than an <img>, and it
has never once succeeded.
The likely culprit is the content-type sniffer (sniffUrl in src/renderer/src/lib/sniff.ts, reached through extractMedia's onNeedSniff
in MessageRow) being handed a URL that resolveMediaUrl has already turned
into a local one. Harmless as far as anything drawn goes - the sniff fails and
is remembered as "not media" - but it is a request made and refused on every
message carrying one, and a permanent line of red in the console.
The solution
Fix it at the source rather than by widening the policy: a file the daemon has
already fetched and cached does not need its content type probed over HTTP.
The sniffer should skip anything carrying the MEDIA_SCHEME from src/renderer/src/lib/util.ts and treat it as already known.
Found while reviewing the renderer for memory; unrelated to it, and not fixed.
## The problem
Every launch logs this, twice:
> Refused to connect to
> `moho-media://file/?p=%2Fhome%2Fultra%2F.cache%2Fnobilis%2Fsneedchat-avatars%2F62488.webp`
> because it violates the following Content Security Policy directive:
> `connect-src 'self' https: wss: ws://localhost:* http://localhost:*`
The policy in `src/renderer/index.html` allows `moho-media:` in `img-src` and
`media-src` but not in `connect-src`, and has since the initial commit - so
this is a `fetch()`/XHR against a moho-media URL rather than an `<img>`, and it
has never once succeeded.
The likely culprit is the content-type sniffer (`sniffUrl` in
`src/renderer/src/lib/sniff.ts`, reached through `extractMedia`'s `onNeedSniff`
in `MessageRow`) being handed a URL that `resolveMediaUrl` has already turned
into a local one. Harmless as far as anything drawn goes - the sniff fails and
is remembered as "not media" - but it is a request made and refused on every
message carrying one, and a permanent line of red in the console.
## The solution
Fix it at the source rather than by widening the policy: a file the daemon has
already fetched and cached does not need its content type probed over HTTP.
The sniffer should skip anything carrying the `MEDIA_SCHEME` from
`src/renderer/src/lib/util.ts` and treat it as already known.
The description above had the wrong culprit, so for the record: it is not the
sniffer. extractMedia only ever calls onNeedSniff for a URL matching ^https?://, and that one fetch in lib/sniff.ts is the only fetch in the
whole renderer.
It was Notifier.transcodeToPng in src/main/notifications.ts, injecting a fetch("moho-media://...") into the window with executeJavaScript. Which
makes it not cosmetic at all: that transcode is what draws a notification icon
for an avatar nativeImage cannot read, the fetch was refused every time, the catch swallowed it, and the notification went out with no icon. 83% of the
Sneedchat avatars in this cache are WebP or GIF - so on that service the
feature has never once worked.
Fixed by not fetching: main already holds the path and may read it, so it
hands the renderer the bytes as a data URL. A data: image does not taint the
canvas, so the PNG comes back out. The type is sniffed from the first bytes
rather than taken from the filename, because Sneedchat serves WebP called .jpg - ten of two hundred cached avatars are misfiled that way.
Deliberately not the other fix. Widening connect-src to moho-media: is the
smaller diff and the worse answer: that scheme can also reach the daemon's
config directory, where accounts.toml and its tokens live, and allowing
connect there turns "a script in this window could ask for that file" into "a
script in this window could read it".
Verified in the running client against a real cached avatar
(sneedchat-avatars/62488.webp):
old path (fetch moho-media): FAILED: Failed to fetch
new path (data URL) : source 96x96 -> png 96x96, 33146 chars, starts data:image/png;base64,
Finished - https://git.salastil.com/Salastil/moho/commit/433d2708e8a483a0cd8647c63e1b7adb2996cfcf
The description above had the wrong culprit, so for the record: it is not the
sniffer. `extractMedia` only ever calls `onNeedSniff` for a URL matching
`^https?://`, and that one `fetch` in `lib/sniff.ts` is the only fetch in the
whole renderer.
It was `Notifier.transcodeToPng` in `src/main/notifications.ts`, injecting a
`fetch("moho-media://...")` into the window with `executeJavaScript`. Which
makes it not cosmetic at all: that transcode is what draws a notification icon
for an avatar `nativeImage` cannot read, the fetch was refused every time, the
`catch` swallowed it, and the notification went out with no icon. **83% of the
Sneedchat avatars in this cache are WebP or GIF** - so on that service the
feature has never once worked.
Fixed by not fetching: main already holds the path and may read it, so it
hands the renderer the bytes as a data URL. A `data:` image does not taint the
canvas, so the PNG comes back out. The type is sniffed from the first bytes
rather than taken from the filename, because Sneedchat serves WebP called
`.jpg` - ten of two hundred cached avatars are misfiled that way.
Deliberately not the other fix. Widening `connect-src` to `moho-media:` is the
smaller diff and the worse answer: that scheme can also reach the daemon's
config directory, where `accounts.toml` and its tokens live, and allowing
connect there turns "a script in this window could ask for that file" into "a
script in this window could read it".
Verified in the running client against a real cached avatar
(`sneedchat-avatars/62488.webp`):
```
old path (fetch moho-media): FAILED: Failed to fetch
new path (data URL) : source 96x96 -> png 96x96, 33146 chars, starts data:image/png;base64,
```
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Found while reviewing the renderer for memory; unrelated to it, and not fixed.
The problem
Every launch logs this, twice:
The policy in
src/renderer/index.htmlallowsmoho-media:inimg-srcandmedia-srcbut not inconnect-src, and has since the initial commit - sothis is a
fetch()/XHR against a moho-media URL rather than an<img>, and ithas never once succeeded.
The likely culprit is the content-type sniffer (
sniffUrlinsrc/renderer/src/lib/sniff.ts, reached throughextractMedia'sonNeedSniffin
MessageRow) being handed a URL thatresolveMediaUrlhas already turnedinto a local one. Harmless as far as anything drawn goes - the sniff fails and
is remembered as "not media" - but it is a request made and refused on every
message carrying one, and a permanent line of red in the console.
The solution
Fix it at the source rather than by widening the policy: a file the daemon has
already fetched and cached does not need its content type probed over HTTP.
The sniffer should skip anything carrying the
MEDIA_SCHEMEfromsrc/renderer/src/lib/util.tsand treat it as already known.Finished -
433d2708e8The description above had the wrong culprit, so for the record: it is not the
sniffer.
extractMediaonly ever callsonNeedSnifffor a URL matching^https?://, and that onefetchinlib/sniff.tsis the only fetch in thewhole renderer.
It was
Notifier.transcodeToPnginsrc/main/notifications.ts, injecting afetch("moho-media://...")into the window withexecuteJavaScript. Whichmakes it not cosmetic at all: that transcode is what draws a notification icon
for an avatar
nativeImagecannot read, the fetch was refused every time, thecatchswallowed it, and the notification went out with no icon. 83% of theSneedchat avatars in this cache are WebP or GIF - so on that service the
feature has never once worked.
Fixed by not fetching: main already holds the path and may read it, so it
hands the renderer the bytes as a data URL. A
data:image does not taint thecanvas, so the PNG comes back out. The type is sniffed from the first bytes
rather than taken from the filename, because Sneedchat serves WebP called
.jpg- ten of two hundred cached avatars are misfiled that way.Deliberately not the other fix. Widening
connect-srctomoho-media:is thesmaller diff and the worse answer: that scheme can also reach the daemon's
config directory, where
accounts.tomland its tokens live, and allowingconnect there turns "a script in this window could ask for that file" into "a
script in this window could read it".
Verified in the running client against a real cached avatar
(
sneedchat-avatars/62488.webp):