fix(backend): reject malformed timestamp (#12554)
This commit is contained in:
parent
34223f3da4
commit
af15f8d09d
8 changed files with 49 additions and 6 deletions
|
@ -7,11 +7,11 @@ import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { ulid } from 'ulid';
|
import { ulid } from 'ulid';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
import type { Config } from '@/config.js';
|
import type { Config } from '@/config.js';
|
||||||
import { genAid, parseAid } from '@/misc/id/aid.js';
|
import { genAid, isSafeAidT, parseAid } from '@/misc/id/aid.js';
|
||||||
import { genAidx, parseAidx } from '@/misc/id/aidx.js';
|
import { genAidx, isSafeAidxT, parseAidx } from '@/misc/id/aidx.js';
|
||||||
import { genMeid, parseMeid } from '@/misc/id/meid.js';
|
import { genMeid, isSafeMeidT, parseMeid } from '@/misc/id/meid.js';
|
||||||
import { genMeidg, parseMeidg } from '@/misc/id/meidg.js';
|
import { genMeidg, isSafeMeidgT, parseMeidg } from '@/misc/id/meidg.js';
|
||||||
import { genObjectId, parseObjectId } from '@/misc/id/object-id.js';
|
import { genObjectId, isSafeObjectIdT, parseObjectId } from '@/misc/id/object-id.js';
|
||||||
import { bindThis } from '@/decorators.js';
|
import { bindThis } from '@/decorators.js';
|
||||||
import { parseUlid } from '@/misc/id/ulid.js';
|
import { parseUlid } from '@/misc/id/ulid.js';
|
||||||
|
|
||||||
|
@ -26,6 +26,19 @@ export class IdService {
|
||||||
this.method = config.id.toLowerCase();
|
this.method = config.id.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@bindThis
|
||||||
|
public isSafeT(t: number): boolean {
|
||||||
|
switch (this.method) {
|
||||||
|
case 'aid': return isSafeAidT(t);
|
||||||
|
case 'aidx': return isSafeAidxT(t);
|
||||||
|
case 'meid': return isSafeMeidT(t);
|
||||||
|
case 'meidg': return isSafeMeidgT(t);
|
||||||
|
case 'ulid': return t > 0;
|
||||||
|
case 'objectid': return isSafeObjectIdT(t);
|
||||||
|
default: throw new Error('unrecognized id generation method');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 時間を元にIDを生成します(省略時は現在日時)
|
* 時間を元にIDを生成します(省略時は現在日時)
|
||||||
* @param time 日時
|
* @param time 日時
|
||||||
|
|
|
@ -306,9 +306,15 @@ export class ApInboxService {
|
||||||
this.logger.info(`Creating the (Re)Note: ${uri}`);
|
this.logger.info(`Creating the (Re)Note: ${uri}`);
|
||||||
|
|
||||||
const activityAudience = await this.apAudienceService.parseAudience(actor, activity.to, activity.cc);
|
const activityAudience = await this.apAudienceService.parseAudience(actor, activity.to, activity.cc);
|
||||||
|
const createdAt = activity.published ? new Date(activity.published) : null;
|
||||||
|
|
||||||
|
if (createdAt && createdAt < this.idService.parse(renote.id).date) {
|
||||||
|
this.logger.warn('skip: malformed createdAt');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await this.noteCreateService.create(actor, {
|
await this.noteCreateService.create(actor, {
|
||||||
createdAt: activity.published ? new Date(activity.published) : null,
|
createdAt,
|
||||||
renote,
|
renote,
|
||||||
visibility: activityAudience.visibility,
|
visibility: activityAudience.visibility,
|
||||||
visibleUsers: activityAudience.visibleUsers,
|
visibleUsers: activityAudience.visibleUsers,
|
||||||
|
|
|
@ -92,6 +92,10 @@ export class ApNoteService {
|
||||||
return new Error(`invalid Note: attributedTo has different host. expected: ${expectHost}, actual: ${actualHost}`);
|
return new Error(`invalid Note: attributedTo has different host. expected: ${expectHost}, actual: ${actualHost}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (object.published && !this.idService.isSafeT(new Date(object.published).valueOf())) {
|
||||||
|
return new Error('invalid Note: published timestamp is malformed');
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,3 +34,7 @@ export function parseAid(id: string): { date: Date; } {
|
||||||
const time = parseInt(id.slice(0, 8), 36) + TIME2000;
|
const time = parseInt(id.slice(0, 8), 36) + TIME2000;
|
||||||
return { date: new Date(time) };
|
return { date: new Date(time) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isSafeAidT(t: number): boolean {
|
||||||
|
return t > TIME2000;
|
||||||
|
}
|
||||||
|
|
|
@ -41,3 +41,7 @@ export function parseAidx(id: string): { date: Date; } {
|
||||||
const time = parseInt(id.slice(0, TIME_LENGTH), 36) + TIME2000;
|
const time = parseInt(id.slice(0, TIME_LENGTH), 36) + TIME2000;
|
||||||
return { date: new Date(time) };
|
return { date: new Date(time) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isSafeAidxT(t: number): boolean {
|
||||||
|
return t > TIME2000;
|
||||||
|
}
|
||||||
|
|
|
@ -38,3 +38,7 @@ export function parseMeid(id: string): { date: Date; } {
|
||||||
date: new Date(parseInt(id.slice(0, 12), 16) - 0x800000000000),
|
date: new Date(parseInt(id.slice(0, 12), 16) - 0x800000000000),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isSafeMeidT(t: number): boolean {
|
||||||
|
return t > 0;
|
||||||
|
}
|
||||||
|
|
|
@ -38,3 +38,7 @@ export function parseMeidg(id: string): { date: Date; } {
|
||||||
date: new Date(parseInt(id.slice(1, 12), 16)),
|
date: new Date(parseInt(id.slice(1, 12), 16)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isSafeMeidgT(t: number): boolean {
|
||||||
|
return t > 0;
|
||||||
|
}
|
||||||
|
|
|
@ -38,3 +38,7 @@ export function parseObjectId(id: string): { date: Date; } {
|
||||||
date: new Date(parseInt(id.slice(0, 8), 16) * 1000),
|
date: new Date(parseInt(id.slice(0, 8), 16) * 1000),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isSafeObjectIdT(t: number): boolean {
|
||||||
|
return t > 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue