• 4.7.0

    4.6.0 대비 변경사항

    보안 전수조사(브라우저·backend·crawler·edge)에서 찾은 1순위 항목을 고친 릴리스입니다. XSS·권한 누락·SQL 주입은 발견되지 않았고, 아래는 방어 강화와 DoS·우회 경로 차단입니다.

    backend

    • 요청 1건으로 backend가 멈추던 문제 수정(High) — 의심 입력 검사 정규식을 선형 패턴으로 바꾸고 검사 길이를 제한했습니다. 요청 한도 검사가 그보다 먼저 실행됩니다.
    • 다른 사이트에서 보내는 요청 차단(CSRF) — 데이터를 바꾸는 요청(POST·PUT·PATCH·DELETE)은 사이트 자체 출처일 때만 받습니다(403 REQUEST_ORIGIN_REJECTED). form 인코딩 본문 parser를 제거했습니다.
    • IPv6 요청 한도 우회 차단 — 요청 한도·조회 예산·미디어 예산·가입 시도는 IPv6 주소를 /64 단위로 셉니다.
    • 관리자 보안 키 — 틀린 시도를 IP당 1시간 10회로 제한하고(일반 가입 시도에도 함께 적용), 길이를 드러내지 않게 비교합니다. 운영에서 JWT_SECRET·COOKIE_SECRET·ADMIN_SECURITY_KEY가 예제 값(CHANGE_ME…)이거나 JWT와 쿠키 비밀값이 같으면 시작하지 않고, 32자 미만은 경고를 남깁니다.
    • Web Push — 알려진 Push 서비스 주소(HTTPS)만 등록하고 사용자당 구독은 10개까지입니다. 모든 기기 로그아웃은 Push 구독도 지웁니다.
    • DB 연결 고갈 방지 — 개인 route가 클래스의 조회 비용을 낮추지 않게 하고, 계정 내보내기·guest 병합에 비용과 사용자별 단일 실행을 적용했습니다.
    • X-Powered-By 제거, 경로 판정 대소문자·경계 정확화.

    crawler

    • Hitomi gg.js를 실행하지 않음(High) — 외부 스크립트를 실행하는 대신 형식 parser로 읽습니다. 실제 응답으로 이전 방식과 결과가 같은 것을 확인했습니다.
    • 내부 API 토큰 — 새 설정 CRAWLER_INTERNAL_TOKEN이 있으면 backend→crawler 호출을 공유 토큰으로 확인합니다. 비어 있으면 검사하지 않고 시작 경고만 남깁니다. crawler CORS를 제거했습니다.
    • Hitomi redirect는 Hitomi HTTPS 주소만 따라가고(최대 3회), E-Hentai 보호 응답 판별을 선형 검사로 바꿨습니다.

    nginx·web

    • CSP 강제 정책 승격 — unsafe-eval, 임의 외부 이미지·WebSocket 출처를 막고 object-src 'none'·base-uri·form-action·frame-ancestors를 추가했습니다(Report-Only 제거).
    • /api/ 요청 본문 상한 2 MiB, 이미지 검색만 11 MiB. 정적 파일은 GET·HEAD만, upstream X-Accel-* 무시, X-Powered-By 숨김.
    • web API 경로 인코딩과 lint 규칙, 홈 ?gallery= UUID 검사, 알림 클릭은 같은 사이트 주소로만 이동, 로그아웃 때 Push 구독·조회 cache·홈 복귀 상태 정리.
    • 의존성 — Next.js 16.3.8, Nest 11.2.7(multer 2.4.0), axios 1.20.0. 운영 의존성 npm audit 0건.

    운영

    • deploy-production.sh는 backend 이미지가 바뀌면 migration 전에 crawler를 멈춰 deadlock을 막습니다.
    • compose.yml: backend·crawler에 CRAWLER_INTERNAL_TOKEN(기본 빈 값), sql/init-db.sql 읽기 전용 mount.

    DB migration은 없습니다. 새 설정은 선택이고 기존 데이터·사용 방식이 유지되므로 minor 버전입니다. 사이트 밖 출처에서 관리 작업을 하던 경우에는 그 출처를 CORS_ORIGIN에 추가해야 합니다.

    이미지 게시 범위

    빌드 입력 지문을 4.6.0 시점 latest와 대조해 nginx·backend·crawler·web을 새로 빌드하고 4.7.0·latest를 게시했습니다(publish-images.ps1 -ChangedOnly). nginx는 보안 헤더·CSP·본문 상한 설정, backend·crawler·web은 앱 코드·공유 패키지·lockfile이 바뀌었습니다. byedpi는 입력이 같아 기존 latest digest를 유지하며 4.7.0 태그를 추가하지 않았습니다.

    NAS 업데이트

    compose.yml과 배포 스크립트가 바뀌었으므로 먼저 받습니다.

    cd /volume1/2ex-hentai
    curl -fsSL https://git.2ex.dev/hanyul/2Ex-Hentai/raw/tag/4.7.0/compose.yml -o compose.yml
    curl -fsSL https://git.2ex.dev/hanyul/2Ex-Hentai/raw/tag/4.7.0/ops/deploy-production.sh -o ops/deploy-production.sh
    grep -n "CRAWLER_INTERNAL_TOKEN" compose.yml
    docker login git.2ex.dev
    sh ops/deploy-production.sh
    docker compose --env-file .env.production ps
    
    • 권장: 배포 전 .env.production에 CRAWLER_INTERNAL_TOKEN=<openssl rand -hex 32 결과>를 넣습니다. 없어도 동작하지만 crawler가 경고를 남기고 토큰 검사를 하지 않습니다.
    • 권장: ADMIN_SECURITY_KEY가 32자 미만이면 무작위 긴 값으로 바꿉니다(이미 등록된 passkey는 계속 사용).
    • 배포 뒤 운영 사이트에서 브라우저 개발자도구 console에 CSP 오류가 없는지 확인합니다. Cloudflare가 Web Analytics·Rocket Loader 등으로 스크립트를 주입하면 막힐 수 있습니다.
    • 이 릴리스는 변경 서비스에만 버전 태그가 있으므로 IMAGE_TAG로 전체 서비스를 일괄 지정할 수 없습니다.

    4.6.0 대비 전체 변경

    검증

    • 게시 소스 main에서 run-unit.ps1 -Workspace all(web 860 포함), run-crawler-recovery.ps1(내부 토큰 거부 포함), run-operations.ps1 -DeploymentOnly, run-integration.ps1(브라우저 회귀 포함) 통과. worker 단계에서 run-hitomi-network(실제 Hitomi, gg.js parser) 통과.
    • 격리 nginx·web Playwright로 주요 화면·Turnstile 로그인·viewer·이미지 검색에서 강제 CSP 위반 0건을 확인했습니다.
    • 개발 서버를 이 소스로 재빌드해 healthy, 외부 출처 POST 403, 강제 CSP 헤더를 확인했습니다. 실제 Push 해제·PWA 설치·운영 Cloudflare 스크립트 주입 여부와 NAS 배포는 실행하지 않았습니다.

    게시 확인

    • 릴리스 소스: 969a854a (주석 태그 4.7.0).
    • nginx 4.7.0·latest: sha256:8abb8e6c23405656d22150cc1cb632d93042efd9191a0877d8d206e2cb8b41da
    • backend 4.7.0·latest: sha256:bb61f0134cafc8a8b39c05fb81fe79f4b6a396e6d72f01a382390db96dfaa35f
    • crawler 4.7.0·latest: sha256:f80c46f91309b07ab29f16c4c9497dce8f881880d5e1ecc82e415aa9818fae45
    • web 4.7.0·latest: sha256:a76b2dee8f88f96b3523ea83dcd5d1c7730ff55a87ecb6178e524d653d63fbbd
    • 네 이미지 모두 OCI version 4.7.0·revision 969a854a 확인. byedpi(15ac60ab)는 기존 latest 유지·4.7.0 태그 부재 확인.
    Downloads 2