Cursor가 CORS를 * 로 설정하는 이유 (그리고 해결 방법)
Source: Dev.to
TL;DR
- 대부분의 AI‑생성 Express 백엔드에서 와일드카드 CORS(
Access-Control-Allow-Origin: *)가 나타납니다. - Cursor는 많은 학습 데이터 예제에서 origin 화이트리스트를 생략하기 때문에 이를 기본값으로 사용합니다.
- 해결 방법:
origin: '*'를 런타임 허용 목록 함수로 교체하십시오 – 몇 분이면 작업이 끝나고 추가 의존성이 전혀 없습니다.
Source:
문제
Cursor로 생성된 사이드 프로젝트를 검토하던 중, 모든 라우트가 어떤 도메인에서도 접근 가능하도록 열려 있음을 발견했습니다:
app.use(cors({ origin: '*' }));
이 패턴은 제가 살펴본 대부분의 AI‑생성 Express 백엔드에서 나타납니다. 이는 특정 Cursor 버그가 아니라 훈련 데이터 문제입니다. 많은 StackOverflow 답변이 개발자들에게 CORS를 가르칠 때 origin: '*'를 사용했으며, 이는 “브라우저 요청을 작동하게 만들기”는 즉각적인 문제를 해결하지만 보안을 무시합니다.
“내 Express API에 CORS를 추가해 주세요”라고 요청했을 때 Cursor가 생성하는 전형적인 코드 조각은 다음과 같습니다:
import cors from 'cors';
// CWE-346: Origin Validation Error
app.use(cors({
origin: '*',
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true
}));
origin: '*'와 credentials: true를 함께 사용하면 대부분의 브라우저에서 거부되어 개발자는 CORS 오류를 겪고 수정 요청을 합니다. 일반적인 “수정” 방법은 '*'를 특정 문자열로 바꾸는 것이지만, AI가 여전히 '*'를 쓰거나 allowedHeaders: '*'를 제안하는 경우가 있어 근본적인 문제가 해결되지 않습니다.
자격 증명이 없더라도 인증된 API에 와일드카드 CORS를 적용하면 어떤 웹사이트든 피해자의 브라우저에서 요청을 보내고 응답을 읽을 수 있습니다. 사용자가 로그인된 상태라면 세션 토큰이 요청에 함께 전송되어 실제 공격 표면이 생깁니다.
왜 계속 발생하는가
- CORS 오류는 고통스럽다 – 개발자는 빠른 해결책을 원한다.
- 와일드카드 CORS는 동작한다 – 요청이 성공하고 오류나 경고가 없으므로 개발자는 그대로 진행한다.
- 위험이 눈에 보이지 않는다 – 스택 트레이스, 모니터링 알림, 테스트 실패가 없으며, 누군가 코드를 감사할 때까지 남아 있다.
보안 수정
정적 문자열을 요청의 Origin을 허용 목록과 비교하는 검증 함수로 교체합니다:
const ALLOWED_ORIGINS = [
'https://yourapp.com',
'https://www.yourapp.com',
process.env.NODE_ENV === 'development' ? 'http://localhost:3000' : null,
].filter(Boolean) as string[];
app.use(
cors({
origin: (origin, callback) => {
// Allow non‑browser requests (no Origin header)
if (!origin) return callback(null, true);
if (ALLOWED_ORIGINS.includes(origin)) return callback(null, true);
callback(new Error(`CORS blocked: ${origin}`));
},
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization'],
})
);
핵심 포인트
!origin경우는 의도적으로 통과합니다 – 서버‑대‑서버 요청 및 CLI 도구는Origin헤더를 보내지 않으며, 이는 정상입니다.credentials: true는'*'가 명시적인 검증 함수로 대체되었기 때문에 안전합니다.
자동화 테스트
권한이 없는 출처가 차단되는지 확인하는 통합 테스트를 추가합니다:
it('blocks requests from unauthorized origins', async () => {
const res = await request(app)
.get('/api/user/me')
.set('Origin', 'https://malicious.example.com');
expect(res.headers['access-control-allow-origin']).toBeUndefined();
});
이 테스트를 CI 파이프라인에 포함시켜, 향후 AI가 생성한 변경 사항이 허용적인 CORS 설정으로 되돌아가는 경우 자동으로 감지하도록 합니다.
Beyond Express
동일한 문제가 다른 프레임워크에서도 나타납니다:
- Next.js –
next.config.js에서cors설정 - FastAPI –
allow_origins와 함께 사용하는CORSMiddleware - Django –
CORS_ALLOWED_ORIGINS설정 - Rails –
origins와 함께 사용하는rack-cors
모든 프레임워크에 비슷한 설정이 있으며, AI 편집기는 종종 허용적인 옵션을 기본값으로 선택합니다.
문제 조기 감지
저는 SafeWeave를 사용하고 있습니다. 이 도구는 Cursor와 Claude Code에 MCP 서버로 연결되어 이러한 패턴을 표시합니다. semgrep이나 gitleaks와 같은 도구를 이용한 기본적인 pre‑commit 훅만으로도 여기서 설명한 대부분의 문제 설정을 잡아낼 수 있습니다. 중요한 점은 어떤 도구를 선택하든 개발 워크플로우 초기에 검사를 통합하는 것입니다.