+
+ {{#if @controller.advisories.length}}
+ Advisories
+
+ {{#each @controller.advisories as |advisory|}}
+ -
+
+ {{htmlSafe (@controller.convertMarkdown advisory.details)}}
+
+ {{/each}}
+
+ {{else}}
+
+ No advisories found for this crate.
+
+ {{/if}}
+
diff --git a/e2e/acceptance/security.spec.ts b/e2e/acceptance/security.spec.ts
new file mode 100644
index 0000000000..648993d252
--- /dev/null
+++ b/e2e/acceptance/security.spec.ts
@@ -0,0 +1,107 @@
+import { expect, test } from '@/e2e/helper';
+import { http, HttpResponse } from 'msw';
+
+test.describe('Acceptance | crate security page', { tag: '@acceptance' }, () => {
+ test('show some advisories', async ({ page, msw, percy }) => {
+ let crate = await msw.db.crate.create({ name: 'foo' });
+ await msw.db.version.create({ crate, num: '1.0.0' });
+
+ let advisories = [
+ {
+ id: 'TEST-001',
+ summary: 'First test advisory',
+ details: 'This is the first test advisory with **markdown** support.',
+ },
+ {
+ id: 'TEST-002',
+ summary: 'Second test advisory',
+ details: 'This is the second test advisory with more details.',
+ },
+ ];
+
+ await msw.worker.use(http.get('https://rustsec.org/packages/:crateId.json', () => HttpResponse.json(advisories)));
+
+ await page.goto('/crates/foo/security');
+
+ await expect(page.locator('[data-test-list] li')).toHaveCount(2);
+
+ // Check first advisory
+ let advisory1 = page.locator('[data-test-list] li').nth(0);
+ await expect(advisory1.locator('h3 a')).toHaveAttribute('href', 'https://rustsec.org/advisories/TEST-001.html');
+ await expect(advisory1.locator('h3 a')).toHaveText('TEST-001');
+ await expect(advisory1.locator('h3')).toContainText('First test advisory');
+ expect(await advisory1.locator('p').innerHTML()).toBe(
+ 'This is the first test advisory with