fix: 보안 LOW 하드닝 (L2~L6)
- DTO 길이 바운드: 업무 content/assigneeIds/checklist ArrayMaxSize·요소 MaxLength, UpdateRepoDto.description MaxLength(300) - 비밀번호 정책: 8~72자 + 영문·숫자 포함 강제, bcrypt rounds 10→12 - 그랜드페더링을 컷오프(2026-06-20) 이전 생성 계정으로 한정 - multer 업로드 오류를 400(VAL_001)로 매핑 - 운영 환경에서 CORS localhost:3000·Swagger /api-docs 노출 제외 (L1 에이전트 터미널 v-html 은 에이전트 작업 시 함께 처리 — 보류) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -22,6 +22,19 @@ export class HttpExceptionFilter implements ExceptionFilter {
|
||||
let message =
|
||||
'일시적인 시스템 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.';
|
||||
|
||||
// multer 업로드 오류(크기 초과 등)는 HttpException 이 아니므로 별도 400(VAL_001) 매핑
|
||||
if (this.isMulterError(exception)) {
|
||||
const muMessage =
|
||||
exception.code === 'LIMIT_FILE_SIZE'
|
||||
? '파일 크기가 허용 한도(25MB)를 초과했습니다.'
|
||||
: '파일 업로드에 실패했습니다. 파일을 확인해 주세요.';
|
||||
response.status(HttpStatus.BAD_REQUEST).json({
|
||||
success: false,
|
||||
error: { code: 'VAL_001', message: muMessage },
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (exception instanceof HttpException) {
|
||||
status = exception.getStatus();
|
||||
const exceptionResponse = exception.getResponse();
|
||||
@@ -83,6 +96,15 @@ export class HttpExceptionFilter implements ExceptionFilter {
|
||||
});
|
||||
}
|
||||
|
||||
// multer 업로드 오류 판별 (name === 'MulterError', code 보유)
|
||||
private isMulterError(e: unknown): e is { name: string; code?: string } {
|
||||
return (
|
||||
typeof e === 'object' &&
|
||||
e !== null &&
|
||||
(e as { name?: unknown }).name === 'MulterError'
|
||||
);
|
||||
}
|
||||
|
||||
// 예외 응답에서 명시적 { code, message } 추출 (둘 다 문자열일 때만)
|
||||
private extractExplicitError(
|
||||
res: string | object,
|
||||
|
||||
Reference in New Issue
Block a user