Address Images review feedback

Co-authored-by: mroxso <24775431+mroxso@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-09-06 21:04:08 +00:00
committed by GitHub
parent cea944c513
commit 442c460b13
3 changed files with 18 additions and 3 deletions

View File

@@ -163,8 +163,13 @@ function PictureComposer({ onPublished }: { onPublished: () => void }) {
const publishPicture = async () => {
if (!file) return;
try {
const tags = await upload.mutateAsync(file);
await publish.mutateAsync({ kind: 20, content: description.trim(), tags });
const uploadTags = await upload.mutateAsync(file);
const url = uploadTags.find(([name, value]) => name === 'url' && value)?.[1];
if (!url) throw new Error('Upload did not return a URL.');
const imeta = ['imeta', `url ${url}`, ...uploadTags
.filter(([name, value]) => name !== 'url' && value)
.map(([name, value]) => `${name} ${value}`)];
await publish.mutateAsync({ kind: 20, content: description.trim(), tags: [imeta] });
setFile(null); setDescription(''); toast({ title: 'Picture published' }); onPublished();
} catch (error) { toast({ title: 'Could not publish picture', description: error instanceof Error ? error.message : 'Upload failed.', variant: 'destructive' }); }
};

View File

@@ -17,5 +17,7 @@ describe('picture posts', () => {
it('rejects non-picture kinds and unsafe image URLs', () => {
expect(isPicturePost(event(1, [['imeta', 'url https://images.example/picture.jpg']]))).toBe(false);
expect(isPicturePost(event(20, [['imeta', 'url javascript:alert(1)']]))).toBe(false);
expect(isPicturePost(event(20, [['imeta', 'url mailto:image@example.com']]))).toBe(false);
expect(isPicturePost(event(20, [['imeta', 'url /picture.jpg']]))).toBe(false);
});
});

View File

@@ -7,7 +7,15 @@ export function pictureUrl(event: NostrEvent): string | undefined {
const metadata = event.tags.find(([name]) => name === 'imeta');
const url = metadata?.find((value) => value.startsWith('url '))?.slice(4);
return sanitizeUrl(url);
if (!url) return undefined;
try {
const parsed = new URL(url);
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') return undefined;
return sanitizeUrl(parsed.href);
} catch {
return undefined;
}
}
/** Picture posts are Kind 20 events with an image the client can safely render. */