-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdual_path_parity_oracle.test.js
More file actions
81 lines (73 loc) · 3.46 KB
/
Copy pathdual_path_parity_oracle.test.js
File metadata and controls
81 lines (73 loc) · 3.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/**
* Part A — Golden-parity: JS renderer path for the adversarial bash tool_result.
*
* The Python md-exporter path is covered by
* ``tests/test_dual_path_parity_oracle.py``. Both suites use the same
* adversarial payload (``<img src=x onerror=alert(1)>``).
*
* These tests drive the **real** JS dispatch path via ``renderToolResult``
* (registry.js) and the direct renderer ``renderBashResult`` (bash.js) — no
* reimplementations.
*
* Oracle discipline (test-review C3/C8/C9):
* Every assertion checks the real observable HTML output, never merely that
* the function does not throw.
*/
import { describe, it, expect } from 'vitest';
import { renderToolResult } from '../registry.js';
import { renderBashResult } from './bash.js';
// Shared adversarial payload — must match the Python constant in
// tests/test_dual_path_parity_oracle.py.
const PAYLOAD = '<img src=x onerror=alert(1)>';
// Parsed bash dict that mirrors what ``_parse_tool_result`` / ``_tool_result_build_bash``
// would produce for the adversarial blob.
const ADVERSARIAL_PARSED = {
result_type: 'bash',
slug: null,
stdout: PAYLOAD,
stderr: '',
exit_code: 0,
interrupted: false,
is_error: false,
return_code_interpretation: 'success',
};
describe('Part A: golden-parity — adversarial bash result (JS renderer path)', () => {
it('renders a non-empty HTML string for the adversarial payload', () => {
// Oracle: output must not be empty — the payload is not silently dropped.
const html = renderToolResult(ADVERSARIAL_PARSED);
expect(typeof html).toBe('string');
expect(html.length).toBeGreaterThan(0);
});
it('HTML-escapes the adversarial payload — raw XSS tag must not appear', () => {
// Oracle: the raw ``<img src=x onerror=`` string must be absent (escaped);
// the HTML-entity form must be present.
//
// Negative control: if esc() were removed from renderBashResult, the raw
// tag WOULD appear in the output and ``not.toContain`` would fail —
// a regressed renderer cannot pass this test.
const html = renderToolResult(ADVERSARIAL_PARSED);
expect(html).not.toContain('<img src=x onerror=');
expect(html).toContain('<img src=x onerror=alert(1)>');
});
it('routes through the real renderBashResult dispatch path — no re-implementation', () => {
// Driving both the registry dispatch (renderToolResult) and the direct
// renderer (renderBashResult) confirms they produce the same output.
// If registry.js ever wired a different renderer for result_type 'bash',
// this equality assertion would fail.
const viaRegistry = renderToolResult(ADVERSARIAL_PARSED);
const viaDirect = renderBashResult(ADVERSARIAL_PARSED);
expect(viaRegistry).toBe(viaDirect);
});
it('negative control: the raw payload is a dangerous string without escaping', () => {
// Documents why esc() is load-bearing: PAYLOAD itself contains the
// executable XSS vector. If the renderer passed it through unchanged,
// the browser could execute it.
expect(PAYLOAD).toContain('<img');
expect(PAYLOAD).toContain('onerror=');
expect(PAYLOAD).not.toContain('<');
// The renderer must NOT pass PAYLOAD through unchanged.
const html = renderBashResult(ADVERSARIAL_PARSED);
expect(html).not.toContain(PAYLOAD);
expect(html).toContain('<');
});
});