-
-
Notifications
You must be signed in to change notification settings - Fork 260
Expand file tree
/
Copy pathgenerate-version-validation.test.ts
More file actions
71 lines (57 loc) · 2.55 KB
/
generate-version-validation.test.ts
File metadata and controls
71 lines (57 loc) · 2.55 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
import { describe, it, expect } from 'vitest';
// We cannot easily import the generate-version script (it runs main() immediately),
// so we extract and test the core logic: VERSION_REGEX and JSON.stringify defense.
const VERSION_REGEX = /^v?[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.\-]+)?(\+[a-zA-Z0-9.\-]+)?$/;
describe('generate-version: VERSION_REGEX validation', () => {
it('accepts standard semver', () => {
expect(VERSION_REGEX.test('2.3.0')).toBe(true);
});
it('accepts v-prefixed semver', () => {
expect(VERSION_REGEX.test('v1.0.8')).toBe(true);
});
it('accepts pre-release semver', () => {
expect(VERSION_REGEX.test('1.0.0-beta.1')).toBe(true);
});
it('accepts pre-release with hyphens', () => {
expect(VERSION_REGEX.test('1.0.0-rc-1')).toBe(true);
});
it('accepts build metadata', () => {
expect(VERSION_REGEX.test('1.0.0+build.123')).toBe(true);
});
it('accepts pre-release + build metadata', () => {
expect(VERSION_REGEX.test('1.0.0-alpha.1+meta')).toBe(true);
});
it('rejects injection payloads with single quotes', () => {
expect(VERSION_REGEX.test("'; process.exit(1); //")).toBe(false);
});
it('rejects injection payloads with template literals', () => {
expect(VERSION_REGEX.test('${process.exit(1)}')).toBe(false);
});
it('rejects empty string', () => {
expect(VERSION_REGEX.test('')).toBe(false);
});
it('rejects arbitrary text', () => {
expect(VERSION_REGEX.test('not-a-version')).toBe(false);
});
});
describe('generate-version: JSON.stringify defense-in-depth', () => {
it('produces safe code even if a value somehow contains quotes', () => {
const malicious = "1.0.0'; process.exit(1); //";
const generated = `const version = ${JSON.stringify(malicious)};\n`;
// The output should use escaped double-quoted string, not break out
expect(generated).toContain('"1.0.0');
expect(generated).not.toContain("'1.0.0'; process.exit(1)");
// Should be parseable JS (using const instead of export for Function() compat)
expect(() => new Function(generated)).not.toThrow();
});
it('JSON.stringify properly escapes backslashes and control characters', () => {
const tricky = '1.0.0\n";process.exit(1);//';
const serialized = JSON.stringify(tricky);
// The newline should be escaped as \\n, and the quote should be escaped
expect(serialized).toContain('\\n');
expect(serialized).toContain('\\"');
// The resulting assignment should be valid JS
const code = `const v = ${serialized};`;
expect(() => new Function(code)).not.toThrow();
});
});