feat(16-02): add EML_OBJECT_KEY_REGEX + parameterize B2 key validation (D-05)
- New EML_OBJECT_KEY_REGEX enforces phishing/<id>/<id>.eml, rejects traversal - presignDownload/presignUpload/downloadToBuffer take optional keyRegex, defaulting to OBJECT_KEY_REGEX so existing LogLift call sites are unchanged - OBJECT_KEY_REGEX itself left untouched (skill-doc rule)
This commit is contained in:
parent
6de92a507b
commit
8630fd5151
1 changed files with 19 additions and 6 deletions
|
|
@ -31,6 +31,16 @@ export const MAX_DOWNLOAD_BYTES = 25 * 1024 * 1024; // 25 MB
|
|||
export const OBJECT_KEY_REGEX =
|
||||
/^[A-Za-z0-9_-]+\/[A-Za-z0-9_.-]+\/eventlogs_[0-9_]+\.json\.gz$/;
|
||||
|
||||
/**
|
||||
* Object-key shape for raw `.eml` evidence uploads (Phase 16 / D-05):
|
||||
* `phishing/{reportId}/{attachmentId}.eml`. This is a SEPARATE regex from
|
||||
* OBJECT_KEY_REGEX — per the B2 evidence skill doc, never loosen the
|
||||
* existing LogLift guard to accommodate a new shape. Path-traversal safe:
|
||||
* each segment is restricted to `[A-Za-z0-9_-]+`, so `..` cannot appear.
|
||||
*/
|
||||
export const EML_OBJECT_KEY_REGEX =
|
||||
/^phishing\/[A-Za-z0-9_-]+\/[A-Za-z0-9_-]+\.eml$/;
|
||||
|
||||
export class B2NotConfiguredError extends Error {
|
||||
constructor() {
|
||||
super(
|
||||
|
|
@ -145,18 +155,20 @@ function presign(params: PresignParams): string {
|
|||
export function presignDownload(
|
||||
objectKey: string,
|
||||
expiresInSeconds = 600,
|
||||
cfg: B2Config = getB2Config()
|
||||
cfg: B2Config = getB2Config(),
|
||||
keyRegex: RegExp = OBJECT_KEY_REGEX
|
||||
): string {
|
||||
if (!OBJECT_KEY_REGEX.test(objectKey)) throw new B2InvalidObjectKeyError(objectKey);
|
||||
if (!keyRegex.test(objectKey)) throw new B2InvalidObjectKeyError(objectKey);
|
||||
return presign({ method: 'GET', objectKey, expiresInSeconds, config: cfg });
|
||||
}
|
||||
|
||||
export function presignUpload(
|
||||
objectKey: string,
|
||||
expiresInSeconds = 1800,
|
||||
cfg: B2Config = getB2Config()
|
||||
cfg: B2Config = getB2Config(),
|
||||
keyRegex: RegExp = OBJECT_KEY_REGEX
|
||||
): string {
|
||||
if (!OBJECT_KEY_REGEX.test(objectKey)) throw new B2InvalidObjectKeyError(objectKey);
|
||||
if (!keyRegex.test(objectKey)) throw new B2InvalidObjectKeyError(objectKey);
|
||||
return presign({ method: 'PUT', objectKey, expiresInSeconds, config: cfg });
|
||||
}
|
||||
|
||||
|
|
@ -166,9 +178,10 @@ export function presignUpload(
|
|||
*/
|
||||
export async function downloadToBuffer(
|
||||
objectKey: string,
|
||||
cfg: B2Config = getB2Config()
|
||||
cfg: B2Config = getB2Config(),
|
||||
keyRegex: RegExp = OBJECT_KEY_REGEX
|
||||
): Promise<Buffer> {
|
||||
const url = presignDownload(objectKey, 600, cfg);
|
||||
const url = presignDownload(objectKey, 600, cfg, keyRegex);
|
||||
const res = await fetch(url);
|
||||
if (!res.ok) {
|
||||
const text = await res.text().catch(() => '');
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue