create-safest-tools 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
package/template/package.json
CHANGED
|
@@ -67,7 +67,8 @@ export function reporterEmailConfigured(env: unknown): boolean {
|
|
|
67
67
|
export type CaseReplyAudience = "reporter" | "affected_user";
|
|
68
68
|
|
|
69
69
|
const legacyReplyTokenPattern = /^r1\.([a-z0-9_-]{16})\.([0-9a-f]{8})\.([0-9a-f]{24})$/u;
|
|
70
|
-
const replyTokenPattern = /^
|
|
70
|
+
const replyTokenPattern = /^r([ra])\.([a-z0-9_-]{16})\.([0-9a-f]{8})\.([0-9a-f]{24})$/u;
|
|
71
|
+
const transitionalReplyTokenPattern = /^r2([ra])\.([a-z0-9_-]{16})\.([0-9a-f]{8})\.([0-9a-f]{24})$/u;
|
|
71
72
|
const encoder = new TextEncoder();
|
|
72
73
|
|
|
73
74
|
function hex(bytes: Uint8Array): string {
|
|
@@ -98,7 +99,7 @@ export async function reporterReplyToken(input: {
|
|
|
98
99
|
const expiry = input.expiresAt.toString(16).padStart(8, "0");
|
|
99
100
|
if (!/^[0-9a-f]{8}$/u.test(expiry)) throw new Error("The reporter reply expiry is outside the supported range.");
|
|
100
101
|
const audience = input.audience === "affected_user" ? "a" : "r";
|
|
101
|
-
const payload = `
|
|
102
|
+
const payload = `r${audience}.${reference}.${expiry}`;
|
|
102
103
|
return `${payload}.${hex(await replySignature(input.signingSecret, payload))}`;
|
|
103
104
|
}
|
|
104
105
|
|
|
@@ -108,21 +109,23 @@ export async function verifyReporterReplyToken(
|
|
|
108
109
|
currentTime = Math.floor(Date.now() / 1_000),
|
|
109
110
|
): Promise<{ publicReference: string; expiresAt: number; audience: CaseReplyAudience } | null> {
|
|
110
111
|
const current = replyTokenPattern.exec(token);
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const
|
|
115
|
-
const
|
|
112
|
+
const transitional = current ? null : transitionalReplyTokenPattern.exec(token);
|
|
113
|
+
const legacy = current || transitional ? null : legacyReplyTokenPattern.exec(token);
|
|
114
|
+
if (!current && !transitional && !legacy) return null;
|
|
115
|
+
const reference = current?.[2] ?? transitional?.[2] ?? legacy?.[1] ?? "";
|
|
116
|
+
const expiryHex = current?.[3] ?? transitional?.[3] ?? legacy?.[2] ?? "";
|
|
117
|
+
const signatureHex = current?.[4] ?? transitional?.[4] ?? legacy?.[3] ?? "";
|
|
116
118
|
const expiry = Number.parseInt(expiryHex, 16);
|
|
117
119
|
const supplied = Uint8Array.from(signatureHex.match(/.{2}/gu) ?? [], (pair) => Number.parseInt(pair, 16));
|
|
118
120
|
if (!expiry || expiry <= currentTime) return null;
|
|
119
|
-
const payload = current ? `
|
|
121
|
+
const payload = current ? `r${current[1]}.${reference}.${expiryHex}`
|
|
122
|
+
: transitional ? `r2${transitional[1]}.${reference}.${expiryHex}` : `r1.${reference}.${expiryHex}`;
|
|
120
123
|
const expected = await replySignature(signingSecret, payload);
|
|
121
124
|
if (!constantTimeEqual(supplied, expected)) return null;
|
|
122
125
|
return {
|
|
123
126
|
publicReference: `RPT-${reference.toUpperCase()}`,
|
|
124
127
|
expiresAt: expiry,
|
|
125
|
-
audience: current?.[1] === "a" ? "affected_user" : "reporter",
|
|
128
|
+
audience: (current?.[1] ?? transitional?.[1]) === "a" ? "affected_user" : "reporter",
|
|
126
129
|
};
|
|
127
130
|
}
|
|
128
131
|
|