security hardening
This commit is contained in:
@@ -18,6 +18,15 @@ export interface GiroCodeInput {
|
||||
remittance: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces CR/LF in a free-text EPC field with a single space and collapses
|
||||
* runs of whitespace, so the line-delimited payload can't be tampered with by
|
||||
* smuggling newlines into user-supplied text (beneficiary name / remittance).
|
||||
*/
|
||||
function sanitizeEpcField(value: string): string {
|
||||
return value.replace(/[\r\n]+/g, " ").replace(/\s+/g, " ").trim();
|
||||
}
|
||||
|
||||
export function buildGiroCodePayload(input: GiroCodeInput): string {
|
||||
const currency = input.currency || "EUR";
|
||||
if (currency !== "EUR") {
|
||||
@@ -25,12 +34,14 @@ export function buildGiroCodePayload(input: GiroCodeInput): string {
|
||||
console.warn(`GiroCode: non-EUR currency ${currency} is non-standard.`);
|
||||
}
|
||||
|
||||
// Beneficiary name max 70 chars per spec.
|
||||
const name = input.beneficiaryName.slice(0, 70);
|
||||
// Beneficiary name max 70 chars per spec. Strip CR/LF first so injected
|
||||
// newlines can't forge/add EPC fields (the payload is line-delimited).
|
||||
const name = sanitizeEpcField(input.beneficiaryName).slice(0, 70);
|
||||
const iban = input.iban.replace(/\s+/g, "").toUpperCase();
|
||||
const bic = (input.bic || "").replace(/\s+/g, "").toUpperCase();
|
||||
const amount = input.amount.toFixed(2);
|
||||
const remittance = input.remittance.slice(0, 140);
|
||||
// Unstructured remittance max 140 chars; strip CR/LF for the same reason.
|
||||
const remittance = sanitizeEpcField(input.remittance).slice(0, 140);
|
||||
|
||||
// Field order is fixed; trailing fields can be empty.
|
||||
// Service tag SCT = SEPA Credit Transfer.
|
||||
|
||||
Reference in New Issue
Block a user