mirror of
https://iceshrimp.dev/crimekillz/trashposs
synced 2024-11-24 17:59:05 +01:00
Merge zotan's security patches from v2023.15.6
This commit is contained in:
parent
78a27c0d75
commit
3526e8f891
30
CHANGELOG.md
30
CHANGELOG.md
@ -1,3 +1,33 @@
|
|||||||
|
## v2023.12.6
|
||||||
|
This is a security release. Upgrading is therefore strongly recommended.
|
||||||
|
|
||||||
|
### Backend
|
||||||
|
- When fetching activities, their identifiers are now validated much more strictly
|
||||||
|
- Drive files now have the `X-Content-Type-Options` header set to `nosniff`
|
||||||
|
- The queue dashboard path is now validated more strictly
|
||||||
|
- The AP object resolver logic was improved to better handle edge cases
|
||||||
|
- Poll notifications are no longer generated for muted notes
|
||||||
|
|
||||||
|
### Frontend
|
||||||
|
- Remote (cross-origin) videos now plays properly
|
||||||
|
- Emoji reactions on the landing page timeline preview are now aligned properly
|
||||||
|
|
||||||
|
### Mastodon client API
|
||||||
|
- The default reaction is now returned with /v1/instance
|
||||||
|
|
||||||
|
### Miscellaneous
|
||||||
|
- The podman documentation was improved
|
||||||
|
- The example nginx config now has gzip enabled
|
||||||
|
- The Dockerfile now references the required dependencies for decoding AVIF images
|
||||||
|
- The installation requirements now mention postgresql-contrib
|
||||||
|
- Various translation updates
|
||||||
|
|
||||||
|
### Attribution
|
||||||
|
### Attribution
|
||||||
|
This release was made possible by project contributors: CookiLover311, Crimekillz, Jegler, Laura Hausmann, Lilian, Norm, Salif Mehmed, jeder, konkonkon, naskya & 老周部落
|
||||||
|
|
||||||
|
Furthermore, I want to give special thanks to Oneric for the extraordinarily detailed security disclosure.
|
||||||
|
|
||||||
## v2023.12.5
|
## v2023.12.5
|
||||||
This is a followup security release. Upgrading is recommended.
|
This is a followup security release. Upgrading is recommended.
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "iceshrimp",
|
"name": "iceshrimp",
|
||||||
"version": "2023.12.5",
|
"version": "2023.12.6",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://iceshrimp.dev/iceshrimp/iceshrimp.git"
|
"url": "https://iceshrimp.dev/iceshrimp/iceshrimp.git"
|
||||||
|
@ -123,28 +123,42 @@ export default class Resolver {
|
|||||||
apLogger.debug("Getting object from remote, authenticated as user:");
|
apLogger.debug("Getting object from remote, authenticated as user:");
|
||||||
apLogger.debug(JSON.stringify(this.user, null, 2));
|
apLogger.debug(JSON.stringify(this.user, null, 2));
|
||||||
|
|
||||||
const res = (
|
const {res, object} = await this.doFetch(value);
|
||||||
|
|
||||||
|
if (object.id == null) throw new Error("Object has no ID");
|
||||||
|
if (res.finalUrl === object.id) return object;
|
||||||
|
|
||||||
|
if (new URL(res.finalUrl).host !== new URL(object.id).host)
|
||||||
|
throw new Error("Object ID host doesn't match final url host");
|
||||||
|
|
||||||
|
const {res: finalRes, object: finalObject} = await this.doFetch(object.id);
|
||||||
|
|
||||||
|
if (finalRes.finalUrl !== finalObject.id)
|
||||||
|
throw new Error("Object ID still doesn't match final URL after second fetch attempt")
|
||||||
|
|
||||||
|
return finalObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async doFetch(uri: string) {
|
||||||
|
let res = (
|
||||||
this.user
|
this.user
|
||||||
? await signedGet(value, this.user)
|
? await signedGet(uri, this.user)
|
||||||
: await getJsonActivity(value)
|
: await getJsonActivity(uri)
|
||||||
);
|
);
|
||||||
const object = res.content as IObject;
|
let object = res.content as IObject;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
object == null ||
|
object == null ||
|
||||||
(Array.isArray(object["@context"])
|
(Array.isArray(object["@context"])
|
||||||
? !(object["@context"] as unknown[]).includes(
|
? !(object["@context"] as unknown[]).includes(
|
||||||
"https://www.w3.org/ns/activitystreams",
|
"https://www.w3.org/ns/activitystreams",
|
||||||
)
|
)
|
||||||
: object["@context"] !== "https://www.w3.org/ns/activitystreams")
|
: object["@context"] !== "https://www.w3.org/ns/activitystreams")
|
||||||
) {
|
) {
|
||||||
throw new Error("invalid response");
|
throw new Error("invalid response");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (object.id != null && new URL(res.finalUrl).host != new URL(object.id).host)
|
return {res, object};
|
||||||
throw new Error("Object ID host doesn't match final url host");
|
|
||||||
|
|
||||||
return object;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private resolveLocal(url: string): Promise<IObject> {
|
private resolveLocal(url: string): Promise<IObject> {
|
||||||
|
@ -49,6 +49,8 @@ export default async function (ctx: Koa.Context) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.set("X-Content-Type-Options", "nosniff");
|
||||||
|
|
||||||
const isThumbnail = file.thumbnailAccessKey === key;
|
const isThumbnail = file.thumbnailAccessKey === key;
|
||||||
const isWebpublic = file.webpublicAccessKey === key;
|
const isWebpublic = file.webpublicAccessKey === key;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user