calendar-ics-normalizer-security.test.mjs
71 lines 2.9 KB
Raw
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd feat(calendar): enforce agent context tiers in retrieval AP… Human minor ⚠ breaking 1 day ago
1 /**
2 * Tier 7 — SECURITY: injection fixtures, payload bounds, tier-0 agent isolation.
3 * Reference: docs/CALENDAR-EVENTS-V0-SPEC.md — Security checklist
4 */
5 import { describe, it } from 'node:test';
6 import assert from 'node:assert/strict';
7 import fs from 'node:fs';
8 import path from 'node:path';
9 import { fileURLToPath } from 'node:url';
10 import { parseIcsToEvents } from '../lib/calendar/ics-normalizer.mjs';
11 import { buildSourceCalendarDefaults, isAgentTierAllowed } from '../lib/calendar/source-calendar-defaults.mjs';
12 import { redactEventForAgentTier } from '../lib/calendar/agent-context-tier.mjs';
13
14 const __dirname = path.dirname(fileURLToPath(import.meta.url));
15 const fixtureDir = path.join(__dirname, 'fixtures', 'calendar');
16
17 describe('Security — prompt injection in SUMMARY is stored verbatim but tier-redacted', () => {
18 it('preserves escaped injection text in normalized summary', () => {
19 const ics = fs.readFileSync(path.join(fixtureDir, 'injection-summary.ics'), 'utf8');
20 const [event] = parseIcsToEvents(ics);
21 assert.match(event.summary ?? '', /Ignore prior instructions/);
22 assert.match(event.summary ?? '', /delete vault/);
23 });
24
25 it('tier 0 default calendar exposes no agent fields', () => {
26 const ics = fs.readFileSync(path.join(fixtureDir, 'injection-summary.ics'), 'utf8');
27 const [event] = parseIcsToEvents(ics);
28 const cal = buildSourceCalendarDefaults();
29 assert.equal(isAgentTierAllowed(cal, 1), false);
30 assert.equal(redactEventForAgentTier(event, 0), null);
31 const tier1 = redactEventForAgentTier(event, 1);
32 assert.ok(tier1);
33 assert.equal(tier1.summary, undefined);
34 });
35 });
36
37 describe('Security — payload size limits', () => {
38 it('rejects ICS text above MAX_ICS_BYTES', () => {
39 const big = `BEGIN:VCALENDAR\nBEGIN:VEVENT\nUID:x\nDTSTART:20260101T000000Z\nDTEND:20260101T010000Z\nSUMMARY:${'A'.repeat(6 * 1024 * 1024)}\nEND:VEVENT\nEND:VCALENDAR`;
40 assert.throws(() => parseIcsToEvents(big), /exceeds/);
41 });
42
43 it('rejects non-string input', () => {
44 assert.throws(() => parseIcsToEvents(/** @type {*} */ (null)), /must be a string/);
45 });
46 });
47
48 describe('Security — no OAuth or network surface in normalizer module', () => {
49 it('parseIcsToEvents accepts only in-memory string (no URL fetch API)', () => {
50 assert.deepEqual(parseIcsToEvents(''), []);
51 const events = parseIcsToEvents(`BEGIN:VCALENDAR
52 BEGIN:VEVENT
53 UID:local@only
54 DTSTART:20260101T000000Z
55 DTEND:20260101T010000Z
56 END:VEVENT
57 END:VCALENDAR`);
58 assert.equal(events.length, 1);
59 });
60 });
61
62 describe('Security — display vs agent toggles are independent', () => {
63 it('display-on agents-off default allows UI but blocks tier > 0', () => {
64 const cal = buildSourceCalendarDefaults({
65 enabled_for_display: true,
66 enabled_for_agents: false,
67 });
68 assert.equal(cal.enabled_for_display, true);
69 assert.equal(isAgentTierAllowed(cal, 2), false);
70 });
71 });
File History 1 commit
sha256:65ccb454656ea5acdea0a10e559b78bcde1eb6ff753ecc2911bc99d1c3d7cadd feat(calendar): enforce agent context tiers in retrieval AP… Human minor 1 day ago