mirror of
https://github.com/alam00000/bentopdf.git
synced 2026-11-13 17:54:19 +01:00
feat(timestamp): add TSA URL validation and sanitization methods
This commit is contained in:
1 parent
b09fc21e66
commit
b21f602cca
7 files changed
+168
-2
No files matched your search
@@ -12,3 +12,26 @@ export const TIMESTAMP_TSA_PRESETS: TimestampTsaPreset[] = [
|
||||
{ label: 'FreeTSA', url: 'https://freetsa.org/tsr' },
|
||||
{ label: 'MeSign', url: 'http://tsa.mesign.com' },
|
||||
];
|
||||
|
||||
const ALLOWED_TSA_HOSTS: ReadonlySet<string> = new Set(
|
||||
TIMESTAMP_TSA_PRESETS.map((preset) => new URL(preset.url).hostname)
|
||||
);
|
||||
|
||||
export function isValidTsaRequestUrl(value: unknown): value is string {
|
||||
if (typeof value !== 'string') {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
const url = new URL(value);
|
||||
return url.protocol === 'http:' || url.protocol === 'https:';
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function isAllowedTsaUrl(value: unknown): value is string {
|
||||
if (!isValidTsaRequestUrl(value)) {
|
||||
return false;
|
||||
}
|
||||
return ALLOWED_TSA_HOSTS.has(new URL(value).hostname);
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { PdfSigner, type SignOption } from 'zgapdfsigner';
|
||||
import forge from 'node-forge';
|
||||
import { CertificateData, SignPdfOptions } from '@/types';
|
||||
import { isValidTsaRequestUrl } from '../config/timestamp-tsa.js';
|
||||
|
||||
export function parsePfxFile(
|
||||
pfxBytes: ArrayBuffer,
|
||||
@@ -349,6 +350,12 @@ export async function timestampPdf(
|
||||
pdfBytes: Uint8Array,
|
||||
tsaUrl: string
|
||||
): Promise<Uint8Array> {
|
||||
if (!isValidTsaRequestUrl(tsaUrl)) {
|
||||
throw new Error(
|
||||
`Invalid TSA URL. The timestamp authority must be a valid http:// or https:// URL.`
|
||||
);
|
||||
}
|
||||
|
||||
const pageIsHttps =
|
||||
typeof window !== 'undefined' && window.location?.protocol === 'https:';
|
||||
const tsaIsHttp = /^http:\/\//i.test(tsaUrl);
|
||||
|
||||
@@ -28,4 +28,19 @@ export abstract class BaseWorkflowNode extends ClassicPreset.Node {
|
||||
description: this.description,
|
||||
};
|
||||
}
|
||||
|
||||
sanitizeControlValue(key: string, value: unknown): unknown {
|
||||
const control = this.controls[key];
|
||||
if (!control || typeof control !== 'object' || !('value' in control)) {
|
||||
return value;
|
||||
}
|
||||
const current = (control as { value: unknown }).value;
|
||||
if (current === null || current === undefined) {
|
||||
return value;
|
||||
}
|
||||
if (typeof value !== typeof current) {
|
||||
return current;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,10 @@ import { pdfSocket } from '../sockets';
|
||||
import type { SocketData } from '../types';
|
||||
import { requirePdfInput, processBatch } from '../types';
|
||||
import { wfError } from '../errors';
|
||||
import { TIMESTAMP_TSA_PRESETS } from '../../config/timestamp-tsa.js';
|
||||
import {
|
||||
TIMESTAMP_TSA_PRESETS,
|
||||
isAllowedTsaUrl,
|
||||
} from '../../config/timestamp-tsa.js';
|
||||
import { timestampPdf } from '../../logic/digital-sign-pdf.js';
|
||||
import { loadPdfDocument } from '../../utils/load-pdf-document.js';
|
||||
|
||||
@@ -32,6 +35,14 @@ export class TimestampNode extends BaseWorkflowNode {
|
||||
return TIMESTAMP_TSA_PRESETS;
|
||||
}
|
||||
|
||||
sanitizeControlValue(key: string, value: unknown): unknown {
|
||||
const sanitized = super.sanitizeControlValue(key, value);
|
||||
if (key === 'tsaUrl' && !isAllowedTsaUrl(sanitized)) {
|
||||
return TIMESTAMP_TSA_PRESETS[0].url;
|
||||
}
|
||||
return sanitized;
|
||||
}
|
||||
|
||||
async data(
|
||||
inputs: Record<string, SocketData[]>
|
||||
): Promise<Record<string, SocketData>> {
|
||||
|
||||
@@ -98,7 +98,10 @@ async function deserializeWorkflow(
|
||||
for (const [key, value] of Object.entries(serializedNode.controls || {})) {
|
||||
const control = node.controls[key];
|
||||
if (control && 'value' in control) {
|
||||
(control as { value: unknown }).value = value;
|
||||
(control as { value: unknown }).value = node.sanitizeControlValue(
|
||||
key,
|
||||
value
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user