10 Commits
Author SHA1 Message Date
HeuJung cf1d8ab52c fix(security): 보안 제보 14건 + 유사 결함 전수조사 수정
sir.kr 커뮤니티 제보(Xbuilder 님 외)와 전수조사 발굴분을 코어·게시판·
이커머스·페이지·ckeditor5 전반에 반영.

- 통합 검색 하이라이트: 코어 SearchHighlighter 로 원문 이스케이프 후 강조
 (저장형 XSS 차단, board/ecommerce/page 3중복제 통합)
- 공개 최신글·인기글·관리자 대시보드: 읽기권한 없는 게시판·블라인드·비활성
 게시판 글 필터. 비밀글은 기존 공개 정책대로 제목 노출 유지(본문만 보호)
- 게시판 관리 대시보드 권한 게이트, 이커머스 쿠폰 다운로드·리뷰 대상·주문옵션
 확정 스코프 강화, 취소/환불 항목 검증 회원/비회원 대칭
- 만료 토큰 거부(SetLocale), 회원 탈퇴·정보관리 실패 시 내부 오류 원문 마스킹
- 예외→응답 매핑 정비(generic catch 상태코드), ckeditor 업로드 권한 게이트 정리

정책 정합 정정: 착수 계획이 "비밀글 제목 노출=취약점"으로 전제해 공개 최신글·
대시보드에 넣었던 is_secret 필터는, 저장소가 확정한 "제목 공개, 본문만 보호"
정책(2026-01-02/02-04/06-18/06-19)과 배치되어 되돌림. 읽기권한·블라인드 필터는 유지.
Chrome MCP 실측(T1~T10) + 회귀 테스트로 확인.
2026-08-17 15:46:38 +09:00
HeuJung cfc2caba1b feat(ckeditor5,board,ecommerce,page,core,admin_basic): 미참조 에디터 업로드 이미지 정리 신설 + 업로드 고아 동종 결함 7건 전수 해소
공개 (@Tuwasduliebst 제보) 대응.

- ckeditor5: 미참조 이미지 정리 엔진 신설 — 참조 판정(hash + 파일명 2토큰,
 filter_reference_sources 훅으로 확장 콘텐츠 등록) + 정리 커맨드(기본 꺼짐 옵트인,
 3중 게이트) + 업로드 관리 화면(권한 분리·참조 배지·개별/선택 삭제) + 기설치본
 설정 백필 upgrade step
- board: 임시 첨부 GC(상시) + 소프트삭제 첨부 영구 정리(옵트인) + 설정 UI,
 저장 payload 누락(F4)·빈 temp 디렉토리 잔존(F5) 수정
- ecommerce: 임시 상품 이미지 GC + 카테고리 삭제 시 이미지 파일 미삭제(S4) 수정
- page: 임시 첨부 GC
- 코어: 고아 첨부 정리 커맨드(옵트인, site_logo 보호) + 사이트 로고 교체 시
 구 로고 재편입 차단(S6) + DB 백업 미구현 501 정직화(B3) + 플러그인 관리자
 메뉴 설치·업데이트 자동 동기화(F1·F7)
- 동반: 플러그인 설정 검증 오류 필드명 라벨화(F3), Toggle 노드 type 정정
 수평 전개(marketing 1.0.2 bump·gdpr·ecommerce), ja 언어팩 4종, API 문서,
 hooks.md, 시나리오 매니페스트 8종, Playwright E2E 4종
2026-08-17 02:44:54 +09:00
HeuJung f9c4c025cb fix(ecommerce,board,tosspayments,pay_kginicis,pay_nhnkcp,pay_nicepayments,core,basic): 공개 이슈 잔여 결함 5건 해소 — 상점 주소 SSoT·게시판 계약/안내/상한/색인
공개 이슈(gnuboard/g7) 17건 전수 대조에서 "진짜 누락"으로 판정된 5건을 해소한다.

 — 서버가 만들어 내보내는 상점 주소가 각 지점에서 `/shop` 리터럴이나
`"/{$routePath}/..."` 조립으로 흩어져 있었다. 기본값이 아닌 상점에서는 그 주소가
존재하지 않는 화면을 가리키는데, 서버는 문자열을 만들어 내려보냈을 뿐이라 예외도
404 로그도 남지 않는다 — 링크만 조용히 죽는다. `ShopPathResolver` 를 단일 해석
지점으로 두고 주문 완료 이동·비회원 조회 안내·알림 메일·통합검색·상품문의·SEO
캐시·사이트맵 전 지점을 경유시켰다. 같은 값에 종속된 PG 4종 리다이렉트는
`{shopBase}` 자리표시자로, 편집기 상태 scope 는 선택 세그먼트 토큰 `/*?`
(engine-v1.58.0)로 해소했다. 기설치본은 업그레이드 스텝이 백필한다.

 M-02 — 답변 깊이 상한이 config 는 1~10 인데 컬럼 comment 만 1~5 로 남아,
comment 에서 자동 생성되는 계약 문서 4곳이 실제보다 좁은 상한을 공개하고 있었다.

 L-01 — 관리자 게시글 폼에 첨부 안내가 아예 없었고, 대신 사장된 고정 문구
("최대 5개 파일, 각 10MB")가 남아 있었다. 게시판마다 다른 실제 설정값을 렌더한다.

 — 목록 1페이지가 공지 전량을 상한 없이 읽던 것에 안전상한을 두고(구조 무변경,
limit 부가만), 조회수 정렬 목록 술어를 덮는 복합 색인을 신설했다.

브라우저 실측 검수에서 발견한 사전 결함 1건(사용자 게시판 목록이 URL 정렬
파라미터를 데이터소스로 전달하지 않던 문제)도 함께 고쳤다. 폴백을 빈 문자열로 둬
URL 에 정렬이 없을 때 게시판 설정을 덮어쓰지 않게 했다.
2026-08-07 12:04:13 +09:00
HeuJung b10e89bef0 fix(core,board,ecommerce,page,gdpr,ckeditor5,kginicis,admin_basic,basic): 목록 조회·검증 계층 정비 및 감사 지적 전건 처리
목록 조회 성능 축(깊은 OFFSET·정렬·색인)과 그 검증 계층에서 계획서 전수검수와 3회에 걸친
감사가 지적한 항목을 처리했다. 세부 경위는 의 각 회차 문서에 있다.

검증 계층 — 컨트롤러가 base Request 를 직접 주입받던 확장 13곳을 전용 FormRequest 로 옮겼다.
옮기면서 기존 동작 계약은 그대로 두었다: 상한 초과 limit 을 거부하지 않고 상한까지 반환하던
공개 API, per_page 를 범위로 조정하던 관리자 목록, 미지원 period 를 year 로 해석하던 인기글
목록 모두 종전과 같은 응답을 낸다. 상한/폴백을 rules 로 승격시키면 200 이던 응답이 422 가
되어 기존 링크가 깨지므로, 규칙은 타입만 닫고 클램프·폴백은 접근자가 맡는다. period 는
접근자가 닫힌 집합만 반환해 캐시 키 공간도 함께 닫힌다.

ckeditor5 이미지 업로드만 ResponseHelper 봉투를 쓰지 않는다. 응답을 파싱하는 주체가 CDN 으로
로드되는 상위 CKEditor5 43.3.1 의 SimpleUploadAdapter 라 규약을 바꿀 수 없어, 각 응답 지점에
사유를 명시한 면제를 부착하고 근거를 API 문서에 남겼다.

하네스 — 룰 5개의 대상 경로 패턴이 매처와 맞지 않아 번들 확장 컨트롤러가 검사 대상에서
통째로 빠져 있었다. 패턴을 고치자 확장 위반 17건이 드러나 전건 처리했다. severity 오타가
요약 집계 양쪽에 안 잡혀 "0 error" 로 보고되던 문제도 런너 사전 검증으로 막았다.

정렬 게이트 대조 하네스는 관계 정렬 변형만 쓰는 저장소를 탐지하지 못한 채 통과시키고 있었다.
탐지·제외·인자 파싱을 함께 고치고 단위 테스트를 신설했다.
2026-08-02 15:29:29 +09:00
HeuJung 5f4a733b3b feat(core,board,ecommerce,page): 성능 계측 인프라 4축 확장 및 계측 대상 선언 지점 신설
계측 축이 "목록 SELECT" 하나였고 프로파일 12종이 커맨드 파일에 하드코딩돼
있어 확장이 자기 대상을 추가할 수 없었다. 확장이 설치·제거되는 설치본마다
"실제로 존재하는 대상"이 달라지므로, 대상을 소유자가 선언하고 코어가 수집하도록
뒤집었다.

- 선언 지점 두 곳, 스키마 하나: 코어 config/benchmark.php,
 확장 getBenchmarkProfiles (모듈/플러그인). 수집은 method_exists 기반이라
 인터페이스를 직접 구현한 서드파티 확장이 깨지지 않는다.
- 축 4종(목록/화면/쓰기/배치)을 실행기로 분리하고 컨테이너 태그로 주입 —
 축이 늘 때 커맨드를 고치지 않는다.
- 화면 축은 HTTP 커널로 내부 요청을 처리한다. 라우트만 dispatch 하면 전역
 미들웨어를 건너뛰어 화면과 다른 것을 재게 된다. 인증은 프로파일이 선언한
 권한만 가진 임시 계정이 기본이며 --as 로 기존 계정을 지목할 수 있다.
- 화면/쓰기 축은 계측 계정 생성부터 처리까지 롤백되는 트랜잭션 안에서 실행해
 운영 DB 에도 잔여 데이터를 남기지 않는다. 배치 축은 내부 커밋·락 보유 때문에
 감싸지 않고 --allow-write 로만 통제한다.
- 잘못된 선언은 조용히 버리지 않고 사유를 경고로 남긴다. 버려진 선언이 곧
 계측 사각이 되기 때문이다. 전부 건너뛴 실행은 종료 코드 1 로 끝난다.
- 리포트는 환경 정보를 함께 적어 저장소 밖(storage/app/benchmarks)에 남긴다.
 측정값이 실행 머신에 종속되므로 저장소에 축적하면 비교 불가능한 수치가 섞인다.

작업 중 발견해 함께 고친 것:

- 이관 프로파일 3종의 soft_delete 선언이 실제 스키마와 어긋나 있었다
 (users/product_inquiries/pages 에 deleted_at 없음).
- 주문 목록이 상태 미지정 시 임시 주문 상태를 NOT IN 으로 제외하는데 선언에
 빠져 있었다. filters 가 등가 비교만 지원한 것이 근본 원인이라 연산자 형태를
 받도록 넓히고, 미허용 연산자는 측정 전에 거부한다.
- 댓글 프로파일은 지배적 술어가 상관 서브쿼리라 선언형으로 재현할 수 없어
 제거했다. 맨 테이블 스캔은 어느 화면도 내지 않는 수치가 된다.

g7:bench:pagination → g7:bench 로 개명(4축을 재므로). 이전 이름은 별칭으로 남겼다.

테스트 61건 통과, 라이브 18종 전건 측정.
2026-08-02 14:44:33 +09:00
HeuJung 1eedbbdda1 fix(core,engine): OFFSET 순회 중 필터 컬럼 변경으로 인한 처리 누락 수정
Laravel chunk/each 는 OFFSET 기반이라, 콜백이 행의 필터 소속을 바꾸면
(필터 컬럼을 채우거나 매칭 행을 삭제하면) 다음 조회가 그만큼 앞으로 밀려
미처리 행을 조용히 건너뛴다. 250건/청크 100 이면 정확히 100건이 남는다.
코어·번들 확장 전수 조사로 확정한 6곳을 chunkById(키셋 순회)로 통일했다.

브라우저 검수(28축)에서 계획에 없던 결함 12건이 드러나 같은 사슬에서
수정했다. 이 중 layout_strategy=keep 무효화와 수정 감지 실패 시 "수정 없음"
오보는 사용자 작업 소실에 직결된다.

재발 방지로 audit 룰을 추가했고, 수정 6곳을 원복해 red 6건 / 복원 후 green
0건으로 판별력을 검증했다.
2026-07-31 21:50:45 +09:00
HeuJung c4ea9a6cd1 v7.0.0 release 2026-07-01 10:30:32 +09:00
HeuJung 1db039ff34 v7.0.0-beta.4 release 2026-05-11 11:29:41 +09:00
HeuJung fa8eba7a0d v7.0.0-beta.2 release 2026-04-20 20:37:49 +09:00
HeuJung 6595fd0eb5 v7.0.0-beta.1 release 2026-04-01 10:30:52 +09:00