Files
Gnuboard7/tests/scenarios/layout-expression-sandbox.yaml
T
HeuJung 0bb2ab9b49 fix(seo,engine): 7.0.7 검증 발견 결함 수정 — 표현식 구조분해 회귀·타이틀 접미사 조립·JSON-LD 이스케이프
- SafeExpressionEvaluator 교체(engine-v1.60.0)가 구 평가기가 허용하던 화살표
 파라미터 배열 구조분해(([k, v]) / ([, vid]))를 누락해 해당 문법을 쓰는 액션
 params 가 미평가 원문으로 전송, 장바구니 담기/바로 구매가 전 상품 불능이던
 회귀를 수정 (engine-v1.60.5, production 재빌드 동반). 저장소 레이아웃 54파일
 104곳 사용 형태 전수를 단위/E2E 테스트로 잠금
- TrimStrings 가 타이틀 접미사의 선행 공백을 제거해 봇 렌더 제목이
 "제목| 사이트명" 으로 접착되고 빈 제목 화면은 "| 사이트명" 이 매달리던 기존
 결함 수정 — 조립 규칙을 composeTitleSuffix 단일 지점(SSoT)으로 정규화
- JSON-LD 직렬화에 JSON_HEX_TAG 미적용으로 검색어의 </script> 가 스크립트
 컨텍스트를 조기 종료해 실행 가능한 script 요소가 재생성되던 반사형 XSS(기존
 결함) 차단 — 태그 문자 이스케이프, 구조화 데이터 의미는 보존
2026-08-18 09:53:50 +09:00

53 lines
3.2 KiB
YAML

feature: 레이아웃 표현식 평가 샌드박스 (KVE-2026-1915)
description: |
레이아웃 표현식은 AST 화이트리스트 인터프리터(SafeExpressionEvaluator)로 평가된다.
정상 표현식(삼항·옵셔널체이닝·nullish·화살표함수·스프레드·템플릿리터럴·new Date)은 그대로
평가되고, constructor 체인/Function 생성자를 통한 샌드박스 탈출은 코드를 실행하지 못한다.
단위 테스트가 소스를 잠그지만 사용자가 실행하는 것은 배포 번들이므로, 브라우저에서 배포
번들의 공개 API(`G7Core.evaluateCondition`)를 직접 호출해 (a) 정상 회귀 없음 + (b) 익스플로잇
미실행(전역 canary `window.__g7jsi` 미설정) 양면을 잠근다.
axes:
case: [safe_expression, arrow_template_literal, destructuring_param, constructor_escape, nonstring_key_escape, object_facade_safe]
effects:
- same_expression_same_value_across_paths
- sandbox_escape_blocked
- dangerous_payload_does_not_set_global
# 저장측 외부 URL 차단은 표현식 실행 축(case)과 곱해지지 않는 별개 관심사다 — case 는 "그 식이
# 실행되는가" 를, URL 축은 "그 값이 외부 origin 을 가리키는가" 를 본다. 축으로 올리면 조합을
# 관측하는 지점이 없어 어떤 칸도 커버되지 않으므로 sub_flow 로 분리한다.
sub_flows:
- id: external_url_storage_gate
description: |
레이아웃 저장 시 외부 origin URL 을 거부하는 축. 세 갈래를 함께 잠근다.
- 순회 대상: props·actions 뿐 아니라 init_actions(로드 시 자동 실행 → 외부 nav/apiCall 이
자동 리다이렉트·유출로 이어진다)까지. state/computed 는 데이터 값이라 의도적 제외이며,
실제 위험은 바인딩되는 sink(컴포넌트 prop)에서 발생하고 그 sink 는 이미 검사된다.
- 값 형태: 규칙이 배열 트리뿐 아니라 **문자열 스칼라**도 처리해야 한다. 문자열 필드에서
조기 반환하면 그 부착이 조용한 no-op 이 된다.
- 부착 패리티: Store·Update·UpdateContent·UpdateExtensionContent 4 경로가 동일 강도여야
한다. 편집기 저장 경로만 빠지면 그 경로가 우회로다.
effects:
- init_actions_external_url_rejected
- same_origin_path_in_init_actions_allowed
- plain_string_value_is_inspected_not_skipped
- same_origin_plain_string_allowed
- rule_attached_to_every_layout_content_form_request
test_files:
# 배포 번들 종단 (축·효과 마커 보유)
- tests/Playwright/specs/layout-expression-sandbox.spec.ts
# 소스 잠금 — 평가기 본체와 소비 싱크(바인딩·computed·scripts[].if·렌더 조건), 그리고
# 저장 단계 거부. 축(case)은 배포 번들 E2E 가 커버하고 이 파일들은 효과를 떠받친다.
- resources/js/core/template-engine/__tests__/SafeExpressionEvaluator.test.ts
- resources/js/core/template-engine/__tests__/ConditionEvaluator.sandbox.test.ts
- resources/js/core/__tests__/TemplateApp.safeComputed.test.ts
- tests/Feature/Rules/SafeLayoutExpressionsTest.php
# sub_flow external_url_storage_gate 를 떠받친다.
- tests/Feature/Rules/NoExternalUrlsTest.php