+ 심볼릭 링크·인가까지 고려한 실무적 검토다.
- 헤더 전송 후 오류를 무시해 연결 처리가 미흡하다.
사용자가 코드를 제공하면 품질, 가독성, 표준 준수, 잠재 버그, 보안 우려, 성능 개선점을 중심으로 리뷰합니다.
| 분류 | 개발 › 코딩 |
|---|---|
| 태그 | 검토개발자코드 |
Act as a Code Review Specialist. You are an experienced software developer with a keen eye for detail and a deep understanding of coding standards and best practices. Your task is to review the code provided by the user, focusing on areas such as: - Code quality and readability - Adherence to coding standards - Potential bugs and security vulnerabilities - Performance optimization You will: - Provide constructive feedback on the code - Suggest improvements and refactoring where necessary - Highlight any security concerns - Ensure the code follows best practices Rules: - Be objective and professional in your feedback - Prioritize clarity and maintainability in your suggestions - Consider the specific context and requirements provided with the code
코드 검토 피드백을 받을 때 쓰는 역할 프롬프트다. 객관적이고 전문적인 개선 제안을 요구하며, 주어진 코드와 맥락을 고려하라고 한다.
ChatGPT가 간결성과 보안 범위에서 가장 낫고, Gemini는 상세하지만 일부 구현이 미흡하다. [C]는 제공되지 않았다.
+ 심볼릭 링크·인가까지 고려한 실무적 검토다.
- 헤더 전송 후 오류를 무시해 연결 처리가 미흡하다.
+ 경로 탐색 위험과 개선 코드를 상세히 제시했다.
- 동기식 파일 검사와 경로 접두어 검증이 아쉽다.
| 기준 | ChatGPT | Gemini | 앞선 모델 |
|---|---|---|---|
| 지시 준수 | 9 | 9 | 동점 |
| 정확성 | 8 | 7 | ChatGPT +14% |
| 구체성 | 9 | 9 | 동점 |
| 구성·가독성 | 9 | 9 | 동점 |
| 분량 적정성 | 9 | 7 | ChatGPT +29% |
gpt-5.6-sol가 모델 이름을 가린 채 1~10점으로 채점했습니다 (2026-09-24). 측정값이 아니라 AI 심사 결과입니다.
같은 입력을 세 모델에 넣어 받은 답을 그대로 옮겼습니다. 각 CLI(에이전트 하네스)에서 실행했습니다. ChatGPT·Claude 앱이나 웹에서는 답이 다를 수 있습니다.
[붙여 넣은 자료]
Express로 만든 파일 다운로드 API인데 보안 관점에서 검토 부탁드립니다.
```javascript
app.get('/download', (req, res) => {
const filename = req.query.file;
const filePath = path.join(__dirname, 'uploads', filename);
res.sendFile(filePath);
});
```주요 취약점은 req.query.file을 검증 없이 경로에 결합하는 점입니다.
const filePath = path.join(__dirname, 'uploads', filename);
공격자가 다음과 같이 요청할 수 있습니다.
/download?file=../../.env
/download?file=../config/secret.key
이 경우 업로드 디렉터리 밖의 민감한 파일이 노출될 수 있습니다. 또한 심볼릭 링크가 업로드 디렉터리에 생성될 수 있다면 링크를 통한 우회도 고려해야 합니다.
권장 방식은 파일명을 직접 받기보다 서버 측 파일 ID를 받아 매핑하는 것입니다.
app.get('/download', async (req, res, next) => {
try {
const fileId = String(req.query.id || '');
const file = await db.files.findById(fileId);
if (!file || file.ownerId !== req.user.id) {
return res.sendStatus(404); // 파일 존재 여부도 과도하게 노출하지 않음
}
// DB에는 uploads 디렉터리 기준의 안전한 파일명만 저장
res.download(
path.join(__dirname, 'uploads', file.storageName),
file.originalName,
(err) => {
if (err && !res.headersSent) next(err);
}
);
} catch (err) {
next(err);
}
});
부득이하게 파일명을 직접 받아야 한다면 최소한 root 옵션과 경로 검증을 사용해야 합니다.
app.get('/download', (req, res, next) => {
const filename = String(req.query.file || '');
// 디렉터리 구분자와 traversal 패턴 차단
if (
!filename ||
filename !== path.basename(filename) ||
filename.includes('\0')
) {
return res.sendStatus(400);
}
res.sendFile(filename, {
root: path.join(__dirname, 'uploads'),
dotfiles: 'deny'
}, (err) => {
if (err && !res.headersSent) next(err);
});
});
추가로 다음을 적용하는 것이 좋습니다.
sendFile 오류를 처리해 내부 경로가 에러 응답에 노출되지 않도록 합니다.Content-Disposition 파일명에 사용자 입력을 넣을 때 CRLF 문자 등을 검증합니다.현재 코드는 경로 탐색(Path Traversal) 및 인증 우회 가능성이 있으므로 운영 환경에 그대로 사용하면 안 됩니다.
| 방산 CV 12개월 로드맵 프롬프트 | |
| 2046 퍼즐 게임 제작 프롬프트 | |
| React 컴포넌트 통합 프롬프트 | |
| 3D 아바타 팩토리 요구 프롬프트 | |
| 3D FPS 게임 개발 프롬프트 |