/**
 * @module @arcis/node/middleware/response-splitting
 *
 * HTTP response splitting prevention (sdk-vectors.md tier 1 #27).
 *
 * Response splitting is the *output* counterpart to header injection: app
 * code passes user input into `res.setHeader`, `res.writeHead`, or
 * `res.appendHeader` (Node 17+) without stripping CR/LF, and an attacker
 * uses the embedded newline to break out of the header block and forge a
 * second response. Most often weaponised against `Location:` after a
 * redirect that reflects user input (`/redirect?to=...`).
 *
 * `sanitizeHeaderValue` already covers the byte-level fix on the way in;
 * this middleware wraps the response object so every header that leaves
 * the app gets sanitised on the way out — even when the app forgets.
 *
 * ```ts
 * import { responseSplittingGuard } from '@arcis/node/middleware/response-splitting';
 *
 * app.use(responseSplittingGuard());
 *
 * // Later — even this passes through clean:
 * app.get('/r', (req, res) => res.redirect(req.query.to as string));
 * ```
 *
 * Pair with `validateRedirect` for full coverage: this middleware blocks
 * the response-splitting payload, `validateRedirect` blocks the
 * open-redirect payload.
 */
import type { RequestHandler } from 'express';
import { detectHeaderInjection, sanitizeHeaderValue } from '../sanitizers/headers';
export interface ResponseSplittingGuardOptions {
    /**
     * What to do when an outgoing header value contains CR / LF / NUL.
     *
     * - `'strip'` (default) — silently sanitise the value before it reaches
     *   the wire. Preserves availability; existing routes don't break.
     * - `'reject'` — throw a `ResponseSplittingError`. Use in apps that
     *   would rather fail-closed than emit a partial response.
     *
     * Both modes invoke `onDetect` if provided.
     */
    mode?: 'strip' | 'reject';
    /**
     * Per-detection callback. Fires before strip/reject. Useful for
     * logging or alerting when an attempted split slips through into the
     * response builder.
     */
    onDetect?: (header: string, originalValue: string) => void;
}
/**
 * Thrown by `responseSplittingGuard({ mode: 'reject' })` when an
 * outgoing header value contains CR / LF / NUL. The header name is in
 * `header`; the originally attempted value is in `value` so it can be
 * logged or surfaced in an error handler.
 */
export declare class ResponseSplittingError extends Error {
    readonly header: string;
    readonly value: string;
    constructor(header: string, value: string);
}
/**
 * Re-export under the response-splitting name. Same byte pattern as
 * header injection (CR / LF / NUL) — different threat model: input
 * boundary vs output boundary.
 */
export declare const detectResponseSplitting: typeof detectHeaderInjection;
/**
 * Re-export under the response-splitting name. Strips CR / LF / NUL.
 */
export declare const sanitizeResponseHeader: typeof sanitizeHeaderValue;
/**
 * Build the response-splitting guard middleware. Wraps `res.setHeader`,
 * `res.writeHead`, and `res.appendHeader` (when present) on each
 * incoming request so every header that leaves the app gets the same
 * CRLF / NUL treatment regardless of which code path emitted it.
 *
 * Wrapping happens per-request (not on the prototype) so multiple
 * mounts with different options don't trample each other.
 */
export declare function responseSplittingGuard(options?: ResponseSplittingGuardOptions): RequestHandler;
export default responseSplittingGuard;
//# sourceMappingURL=response-splitting.d.ts.map