From 64f2034a7f26b16923e4e9d39444af2c4415679c Mon Sep 17 00:00:00 2001 From: Nicholai Date: Wed, 4 Mar 2026 22:51:51 -0700 Subject: [PATCH] 2026-03-05T05-51-50_auto_memory/memories.db --- .skill-lock.json | 9 + memory/memories.db | Bin 84803584 -> 84803584 bytes skills/security-best-practices/SKILL.md | 286 ++++++++++++++++++++++ skills/security-best-practices/SKILL.toon | 14 ++ 4 files changed, 309 insertions(+) create mode 100644 skills/security-best-practices/SKILL.md create mode 100644 skills/security-best-practices/SKILL.toon diff --git a/.skill-lock.json b/.skill-lock.json index 7aff1d4c7..708f2c47a 100644 --- a/.skill-lock.json +++ b/.skill-lock.json @@ -234,6 +234,15 @@ "skillFolderHash": "a8dac27e201bb47987943db4f3af2c65c88473b0", "installedAt": "2026-03-03T10:00:28.711Z", "updatedAt": "2026-03-03T10:00:28.711Z" + }, + "security-best-practices": { + "source": "supercent-io/skills-template", + "sourceType": "github", + "sourceUrl": "https://github.com/supercent-io/skills-template.git", + "skillPath": ".agent-skills/security-best-practices/SKILL.md", + "skillFolderHash": "4e4f7c7800510431415bbad025443e692efef201", + "installedAt": "2026-03-05T05:51:45.115Z", + "updatedAt": "2026-03-05T05:51:45.115Z" } }, "dismissed": { diff --git a/memory/memories.db b/memory/memories.db index faca3fe5e5ecdfcbad3b422333aa910da347a646..900c3380b372e8fa3d1e3f791b3c13813f787b0f 100644 GIT binary patch delta 9723 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 delta 9727 zcmZwN4SbFD|M>Ci?wsA8ow>iwhLPNDCik*+?}5^1Bz{VqgEwvj`VZEg>WONB^m z40F3PDk(9N5~~qPsfKQ7mGgVQmi9f@|MA!3^?YA%=Q?MfW9pGvM#iod8B%Uj^~~0o zUPINqg7HJwh15EoAwN__NglkMD=nH5cPmO#wR1eEhFeN# zX+hDL2Mm3tQdrEw7{vAP@V}sIEbu${O z5sX@@ixHuQGlJBxfA6fTIaey3)jE}1LBZsHy`7sv+<&+?6@(YhcgL2ERorz{)uE~( zsv4@QVX7LQ7-}e)h9W~mJezKeo!Oug9a{^QQ@n4ffPqYO4Z_X1iU~= z;8GU2lshV7tDY0(40ukgGvLjo1wN7<_=qp?krHRXtNERQ?h1k%* z7YMC-fw}(lP$^7)hlK}xY7$%l$I5dB{K}TQs@|mhc8ieQQlwN(sxH-#YD%@F+EN{< zu2fH|FEx-FN_R+&q$nv`YAiL8no2QJGpV_Br_@5aOKK^#l3Gh`q_$G56eqQl;-&V| z-BJgsqtr?2EOn8(O5LRH(mhfSDM3n_dRB5O*OnO#&P8u$ake-)DN~5IF z(imy1G)@{XrAekVL7FH{l3tJ|OH-s5rK!?1X}a{1G(&n>nkl7A8B(S+OPVdcBF&LJ z(p+ht^s4+@o)s3Uxl6pM`H?j>_iAtIx!`#3jL5%Qcykli8s3c5tPs^#n3b9pAL2bS zHmh0T`B7OJTJTVH-0*Q}6Q@}dR(kXp@2a#cm-lR1Rx@w**sOMiSI1_})HFr$nrT@n z-uzKn?L20d$DHpmU-Os?JZ84X%<-7H9&@3`T;wqqd(0&sbE(H%<}tkSbDhUr?=j!;m>WFiMvwWf$K2#G-}9K8 zJ?0jVnddR{J?7S(<~A)dVuI33bvxZ9?$z#bs@ofxv8}P1X!VHhWYqEY%Gfr{yCGxS zpL5q{Zj%b6?a~fur&K8Il6Fgbq`lHUX}?q?`J`g$fOJrLU;04$P&y=iBpsGMmOhb= zNS{harDIZwbX+E$N3h6KDZ|NWDmgJwm^O~9?fd)Dl-~cBCK`?|sD1<>c zxF7=D5DC?wI@ExgPz!299jFWSpguH!hHwWof+&cF#?Sq z2HHX_#6dfVhxTwcbbyY~2|7a;=nCDSJKO_3AORBLUbqkLhX>$6cnBVbp3n<=Lmzkq z`og1-1j+CiJP!Tf3Fr?4;7J$=Pr)D<3{S%lcm`4+6^6nvcov?6;V=T8hmkM}M#C5w z3*%rsq=5+&U?NO{7hp0>ffr#aOoQq063l>?VJ4(Q24uo4m<_MM9Pq$gmy%!~w_4c9&`F{9g;onW z7kbL78M#V}*Yp&tr(E>Z!koTEa&cO-^6RhCn)`BVtkP-)X>hUDyQg!DiS3d5{lV zVH*^{cGv+sp%8Y#ZrB5RVIS;=BJe>m9DsxHK70Tl!Xfww4#UUr2^@h>;V2w~5;zVg z;4?T0pTjBm0=|UP@D-eavrr0O!#7X{=ioei3m4!bT!Qc5d$jbReuAIj7bu6T za1E}*ukaiE4u8N6xCwtk1^fkn!#{8f{M!5#4RyItK?5BOaDWqnAQ(a*6v7}JTo3_n zh=giT9cn;Ls0Fp54%CHuP#+pVIxQ-|BhVKf zg(OIZ$KY}32TwqM7ywVgKzIrU!C-hAhQKqB0;w<*hQYJ&91MpM@H~u!Q7{_Dz*rau z;~@=9n4tSsG@Ph^JUckzVaF!NbhXCP#9>Y9MoiU$)i2fc>SX>nrflV(h%*sqmYwff z*SBxYME!Dz=DOrt|L#ORLDwQSTBTbi>aj+|MrD}g&YP%r@ow9EXH%=D{A@>cvDHUr z8~FpYHC--JbGpkN!X$VBCc_kX5vIa4m<}(&40su4LONtXCd`7_@CwWU56p#m@G4}% ze0U8OKsMw+E-Zvauo#xWQdkCFSPm;-CA9@q=}U_TUr4~pRc9EA7b1NaaQ!AEcyK88== z2z&}h;TV*_aX0~=!AbZWPQe%OC7gz@;0&CFQurFafigG;=iytp02kpBd#UPG|vl zK}%=_t)UIHg;LH>aYrLIMDOt57nM?bMaG1OI>WV7 zx9_&LcDSU*Sc!`|8V+@B<^64}NwT#Mo)q{b2T!`+x+$;MR?})&EtYVhUa%sUb(FW^ z3|9*(pB$&ovX*mGi2C^d`+T)Y<@00J>y=NBm3KT)UZ!dBUK2vz^>l`Qoh||9(}>`bBrN%(*D9;k&q`lToYN?XSE0{3V_K_ZK5Rf0=D7 zw{3pg=I$K$yeQiiYugfRTas-{v2AI#E#0=|*fz_y<=Hl$Z7Z>DWwx!{w)t(FyNm7p z*|u2QmSEeGY+H(LOS5h1wk^lDS+*_Dw)t#ZiES&hZRNJjFI!aA=RK-x;QNcUZ3(t5 z$+o4~wlv$8ZrgHfn`PVbY@5%vmDsj2+g5Jd{IUhSqi(i$WZM#KTas-{k?nu4l5Tq} z$F^CvEzh?3Y+H$KE3<9ow#{$b+}#7;LzHckFKk!+?VHb^VB3;xTS~x|<4@~u2=_n_ zNPtAR7w&`m;Q@FM9)gFVC-j2e&<7rYzVIj{K{7lBk3&Cr0{X)McoGJ}Q!oey!_zPX zo`Dodg`qGEo`vUNIE;YjVI+)#(J%(a!Z;WYX<)(xmQU(@HF!ZuGD+;s9eSqNuxM?vDF;w4%aj8s=VZzOl+!Zh0LpQhascJ9%+2X?Q7jj70A-g< zIe?NcQx2ePkSPaH*2t6tD9dHa0hC;sasXwXOgVs(A(I14mB|52nH*rGOb(DLlLHKt z$pMmOa)6#PbA0ky5MF{A@G{JVbjW~Am<6-p6_^7am<#jZRmg(*@ERg|hcbG4CeTGATnP3bM^ zZE3BvPFgR$BW;j2O79v)=B9sNE<0nBk)83Lv{~9B~&yNmiB z`9_bmmEY)5mXk8&pdq{uAHauj2tG1=DN_y`Ru}oD%g#S+Waob@ePR^lA2Du~@sqiq z8riu=rDIZwbX+=N6y<(q+)C$$$dg8P9q8fbVfQWl}cYr-$-TBIqAIg zt#m=UC|#1ilfIWOOFu|IN>`+xq@Sfu{ulKz(dk!~5QqW#9x;qGHbKck6$O)pk!teWRHmRo1tej_F< z@c$PZhdryu_$H}-qisah-+_C>w`_>9j>^pu*6fsSMiZ^xdpUkt=lk6bxllm^9Sm@Q z6M`TZLLd~vAl%{eyIl@7vaU;hTLd|eDeguQLtRb6lS5Ai9daHUR9yK<_UM_tKeb*T z?Q)z@4}0a$eCgItW8_Ju< zoR%(!uB!i^m+`3|{P%n6-w#(-6z6gnaY3rmSWy~lOYe=Xy}$7_qs+a { + if (process.env.NODE_ENV === 'production' && !req.secure) { + return res.redirect(301, `https://${req.headers.host}${req.url}`); + } + next(); +}); + +// Rate Limiting (DDoS 방지) +const limiter = rateLimit({ + windowMs: 15 * 60 * 1000, // 15분 + max: 100, // IP당 최대 100 요청 + message: 'Too many requests from this IP, please try again later.', + standardHeaders: true, + legacyHeaders: false, +}); + +app.use('/api/', limiter); + +// Auth 엔드포인트는 더 엄격하게 +const authLimiter = rateLimit({ + windowMs: 15 * 60 * 1000, + max: 5, // 15분에 5번만 + skipSuccessfulRequests: true // 성공 요청은 카운트하지 않음 +}); + +app.use('/api/auth/login', authLimiter); +``` + +### Step 2: Input Validation (SQL Injection, XSS 방지) + +**Joi 검증**: +```typescript +import Joi from 'joi'; + +const userSchema = Joi.object({ + email: Joi.string().email().required(), + password: Joi.string().min(8).pattern(/^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]/).required(), + name: Joi.string().min(2).max(50).required() +}); + +app.post('/api/users', async (req, res) => { + // 1. Input 검증 + const { error, value } = userSchema.validate(req.body); + + if (error) { + return res.status(400).json({ error: error.details[0].message }); + } + + // 2. SQL Injection 방지: Parameterized Queries + // ❌ 나쁜 예 + // db.query(`SELECT * FROM users WHERE email = '${email}'`); + + // ✅ 좋은 예 + const user = await db.query('SELECT * FROM users WHERE email = ?', [value.email]); + + // 3. XSS 방지: Output Encoding + // React/Vue는 자동으로 escape, 그 외는 라이브러리 사용 + import DOMPurify from 'isomorphic-dompurify'; + const sanitized = DOMPurify.sanitize(userInput); + + res.json({ user: sanitized }); +}); +``` + +### Step 3: CSRF 방지 + +**CSRF Token**: +```typescript +import csrf from 'csurf'; +import cookieParser from 'cookie-parser'; + +app.use(cookieParser()); + +// CSRF protection +const csrfProtection = csrf({ cookie: true }); + +// CSRF 토큰 제공 +app.get('/api/csrf-token', csrfProtection, (req, res) => { + res.json({ csrfToken: req.csrfToken() }); +}); + +// 모든 POST/PUT/DELETE 요청에 CSRF 검증 +app.post('/api/*', csrfProtection, (req, res, next) => { + next(); +}); + +// 클라이언트에서 사용 +// fetch('/api/users', { +// method: 'POST', +// headers: { +// 'CSRF-Token': csrfToken +// }, +// body: JSON.stringify(data) +// }); +``` + +### Step 4: Secrets 관리 + +**.env (절대 커밋하지 않음)**: +```bash +# Database +DATABASE_URL=postgresql://user:password@localhost:5432/mydb + +# JWT +ACCESS_TOKEN_SECRET=your-super-secret-access-token-key-min-32-chars +REFRESH_TOKEN_SECRET=your-super-secret-refresh-token-key-min-32-chars + +# API Keys +STRIPE_SECRET_KEY=sk_test_xxx +SENDGRID_API_KEY=SG.xxx +``` + +**Kubernetes Secrets**: +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: myapp-secrets +type: Opaque +stringData: + database-url: postgresql://user:password@postgres:5432/mydb + jwt-secret: your-jwt-secret +``` + +```typescript +// 환경변수에서 읽기 +const dbUrl = process.env.DATABASE_URL; +if (!dbUrl) { + throw new Error('DATABASE_URL environment variable is required'); +} +``` + +### Step 5: API 인증 보안 + +**JWT + Refresh Token Rotation**: +```typescript +// Access Token 짧게 (15분) +const accessToken = jwt.sign({ userId }, ACCESS_SECRET, { expiresIn: '15m' }); + +// Refresh Token 길게 (7일), DB에 저장 +const refreshToken = jwt.sign({ userId }, REFRESH_SECRET, { expiresIn: '7d' }); +await db.refreshToken.create({ + userId, + token: refreshToken, + expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000) +}); + +// Refresh Token Rotation: 사용 시마다 새로 발급 +app.post('/api/auth/refresh', async (req, res) => { + const { refreshToken } = req.body; + + const payload = jwt.verify(refreshToken, REFRESH_SECRET); + + // 기존 토큰 무효화 + await db.refreshToken.delete({ where: { token: refreshToken } }); + + // 새 토큰 발급 + const newAccessToken = jwt.sign({ userId: payload.userId }, ACCESS_SECRET, { expiresIn: '15m' }); + const newRefreshToken = jwt.sign({ userId: payload.userId }, REFRESH_SECRET, { expiresIn: '7d' }); + + await db.refreshToken.create({ + userId: payload.userId, + token: newRefreshToken, + expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000) + }); + + res.json({ accessToken: newAccessToken, refreshToken: newRefreshToken }); +}); +``` + +## Constraints + +### 필수 규칙 (MUST) + +1. **HTTPS Only**: 프로덕션에서 HTTPS 필수 +2. **Secrets 분리**: 환경변수로 관리, 절대 코드에 하드코딩 금지 +3. **Input Validation**: 모든 사용자 입력 검증 +4. **Parameterized Queries**: SQL Injection 방지 +5. **Rate Limiting**: DDoS 방지 + +### 금지 사항 (MUST NOT) + +1. **eval() 사용 금지**: 코드 인젝션 위험 +2. **innerHTML 직접 사용**: XSS 위험 +3. **Secrets 커밋**: .env 파일 절대 커밋하지 않음 + +## OWASP Top 10 체크리스트 + +```markdown +- [ ] A01: Broken Access Control - RBAC, 권한 검증 +- [ ] A02: Cryptographic Failures - HTTPS, 암호화 +- [ ] A03: Injection - Parameterized Queries, Input Validation +- [ ] A04: Insecure Design - Security by Design +- [ ] A05: Security Misconfiguration - Helmet, 기본 비밀번호 변경 +- [ ] A06: Vulnerable Components - npm audit, 정기 업데이트 +- [ ] A07: Authentication Failures - 강력한 인증, MFA +- [ ] A08: Data Integrity Failures - 서명 검증, CSRF 방지 +- [ ] A09: Logging Failures - 보안 이벤트 로깅 +- [ ] A10: SSRF - 외부 요청 검증 +``` + +## Best practices + +1. **Principle of Least Privilege**: 최소 권한 부여 +2. **Defense in Depth**: 다층 보안 +3. **Security Audits**: 정기적인 보안 점검 + +## References + +- [OWASP Top 10](https://owasp.org/www-project-top-ten/) +- [helmet.js](https://helmetjs.github.io/) +- [Security Checklist](https://github.com/shieldfy/API-Security-Checklist) + +## Metadata + +### 버전 +- **현재 버전**: 1.0.0 +- **최종 업데이트**: 2025-01-01 +- **호환 플랫폼**: Claude, ChatGPT, Gemini + +### 관련 스킬 +- [authentication-setup](../../backend/authentication/SKILL.md) +- [deployment](../deployment/SKILL.md) + +### 태그 +`#security` `#OWASP` `#HTTPS` `#CORS` `#XSS` `#SQL-injection` `#CSRF` `#infrastructure` + +## Examples + +### Example 1: Basic usage + + +### Example 2: Advanced usage + diff --git a/skills/security-best-practices/SKILL.toon b/skills/security-best-practices/SKILL.toon new file mode 100644 index 000000000..414649df2 --- /dev/null +++ b/skills/security-best-practices/SKILL.toon @@ -0,0 +1,14 @@ +N:security-best-practices +D:Implement security best practices for web applications and infrastructure. Use when securing APIs... +G:security HTTPS CORS XSS SQL-injection +U[4]: + **신규 프로젝트**: 처음부터 보안 고려 + **보안 감사**: 취약점 점검 및 수정 + **API 공개**: 외부 접근 API 보안 강화 + **컴플라이언스**: GDPR, PCI-DSS 등 준수 +S[5]{n,action}: + 1,HTTPS 강제 및 보안 헤더 + 2,Input Validation (SQL Injection, XSS 방지) + 3,CSRF 방지 + 4,Secrets 관리 + 5,API 인증 보안 \ No newline at end of file