fix: 🔒 prevent issues

This commit is contained in:
ThatOneCalculator 2023-02-10 11:14:33 -08:00
parent 96e1a93216
commit f7564d87b0
No known key found for this signature in database
GPG Key ID: 8703CACD01000000
6 changed files with 41 additions and 6 deletions

View File

@ -111,6 +111,16 @@ export async function createNote(
const note: IPost = object; const note: IPost = object;
if (note.id && !note.id.startsWith('https://')) {
throw new Error(`unexpected shcema of note.id: ${note.id}`);
}
const url = getOneApHrefNullable(note.url);
if (url && !url.startsWith('https://')) {
throw new Error(`unexpected shcema of note url: ${url}`);
}
logger.debug(`Note fetched: ${JSON.stringify(note, null, 2)}`); logger.debug(`Note fetched: ${JSON.stringify(note, null, 2)}`);
logger.info(`Creating the Note: ${note.id}`); logger.info(`Creating the Note: ${note.id}`);
@ -345,7 +355,7 @@ export async function createNote(
apEmojis, apEmojis,
poll, poll,
uri: note.id, uri: note.id,
url: getOneApHrefNullable(note.url), url: url,
}, },
silent, silent,
); );

View File

@ -195,6 +195,12 @@ export async function createPerson(
const bday = person["vcard:bday"]?.match(/^\d{4}-\d{2}-\d{2}/); const bday = person["vcard:bday"]?.match(/^\d{4}-\d{2}-\d{2}/);
const url = getOneApHrefNullable(person.url);
if (url && !url.startsWith('https://')) {
throw new Error(`unexpected shcema of person url: ${url}`);
}
// Create user // Create user
let user: IRemoteUser; let user: IRemoteUser;
try { try {
@ -237,7 +243,7 @@ export async function createPerson(
description: person.summary description: person.summary
? htmlToMfm(truncate(person.summary, summaryLength), person.tag) ? htmlToMfm(truncate(person.summary, summaryLength), person.tag)
: null, : null,
url: getOneApHrefNullable(person.url), url: url,
fields, fields,
birthday: bday ? bday[0] : null, birthday: bday ? bday[0] : null,
location: person["vcard:Address"] || null, location: person["vcard:Address"] || null,
@ -387,6 +393,12 @@ export async function updatePerson(
const bday = person["vcard:bday"]?.match(/^\d{4}-\d{2}-\d{2}/); const bday = person["vcard:bday"]?.match(/^\d{4}-\d{2}-\d{2}/);
const url = getOneApHrefNullable(person.url);
if (url && !url.startsWith('https://')) {
throw new Error(`unexpected shcema of person url: ${url}`);
}
const updates = { const updates = {
lastFetchedAt: new Date(), lastFetchedAt: new Date(),
inbox: person.inbox, inbox: person.inbox,
@ -430,7 +442,7 @@ export async function updatePerson(
await UserProfiles.update( await UserProfiles.update(
{ userId: exist.id }, { userId: exist.id },
{ {
url: getOneApHrefNullable(person.url), url: url,
fields, fields,
description: person.summary description: person.summary
? htmlToMfm(truncate(person.summary, summaryLength), person.tag) ? htmlToMfm(truncate(person.summary, summaryLength), person.tag)

View File

@ -44,6 +44,14 @@ export const urlPreviewHandler = async (ctx: Koa.Context) => {
logger.succ(`Got preview of ${url}: ${summary.title}`); logger.succ(`Got preview of ${url}: ${summary.title}`);
if (summary.url && !(summary.url.startsWith('http://') || summary.url.startsWith('https://'))) {
throw new Error('unsupported schema included');
}
if (summary.player?.url && !(summary.player.url.startsWith('http://') || summary.player.url.startsWith('https://'))) {
throw new Error('unsupported schema included');
}
summary.icon = wrap(summary.icon); summary.icon = wrap(summary.icon);
summary.thumbnail = wrap(summary.thumbnail); summary.thumbnail = wrap(summary.thumbnail);

View File

@ -80,6 +80,8 @@ export default defineComponent({
this.state = 'accepted'; this.state = 'accepted';
const getUrlParams = () => window.location.search.substring(1).split('&').reduce((result, query) => { const [k, v] = query.split('='); result[k] = decodeURI(v); return result; }, {}); const getUrlParams = () => window.location.search.substring(1).split('&').reduce((result, query) => { const [k, v] = query.split('='); result[k] = decodeURI(v); return result; }, {});
if (this.session.app.callbackUrl) { if (this.session.app.callbackUrl) {
const url = new URL(this.session.app.callbackUrl);
if (['javascript:', 'file:', 'data:', 'mailto:', 'tel:'].includes(url.protocol)) throw new Error('invalid url');
location.href = `${this.session.app.callbackUrl}?token=${this.session.token}&code=${this.session.token}&state=${getUrlParams().state || ''}`; location.href = `${this.session.app.callbackUrl}?token=${this.session.token}&code=${this.session.token}&state=${getUrlParams().state || ''}`;
} }
}, onLogin(res) { }, onLogin(res) {

View File

@ -71,14 +71,13 @@ async function accept(): Promise<void> {
state = 'accepted'; state = 'accepted';
if (props.callback) { if (props.callback) {
const cbUrl = new URL(props.callback); const cbUrl = new URL(props.callback);
if (!['http:', 'https:'].includes(cbUrl.protocol)) throw new Error('invalid url'); if (['javascript:', 'file:', 'data:', 'mailto:', 'tel:'].includes(cbUrl.protocol)) throw new Error('invalid url');
location.href = appendQuery(props.callback, query({ location.href = appendQuery(props.callback, query({
session: props.session, session: props.session,
})); }));
} }
} }
function deny(): void {
state = 'denied'; state = 'denied';
} }

View File

@ -24,7 +24,11 @@ export function createAiScriptEnv(opts) {
return confirm.canceled ? values.FALSE : values.TRUE; return confirm.canceled ? values.FALSE : values.TRUE;
}), }),
"Mk:api": values.FN_NATIVE(async ([ep, param, token]) => { "Mk:api": values.FN_NATIVE(async ([ep, param, token]) => {
if (token) utils.assertString(token); if (token) {
utils.assertString(token);
// バグがあればundefinedもあり得るため念のため
if (typeof token.value !== 'string') throw new Error('invalid token');
}
apiRequests++; apiRequests++;
if (apiRequests > 16) return values.NULL; if (apiRequests > 16) return values.NULL;
const res = await os.api( const res = await os.api(