보안 및 CSP
오리진 허용 목록, 브라우저 정책, 안전한 자격 증명 처리로 임베드 에이전트를 보호합니다.
오리진 허용 목록, 브라우저 정책, 안전한 자격 증명 처리로 임베드 에이전트를 보호합니다.
오리진 허용 목록#
임베드가 활성화되고 브라우저의 정확한 상위 오리진이 허용되어야 임베드가 로드됩니다. 오리진은 scheme://hostname[:port] 형식이며 경로와 쿼리 문자열은 포함하지 않습니다.
| 호스트 페이지 | 허용 목록 값 |
|---|---|
https://example.com/pricing | https://example.com |
https://www.example.com/help | https://www.example.com |
https://preview.example.com:8443/demo | https://preview.example.com:8443 |
http://localhost:3000 | http://localhost:3000 |
운영, 미리보기, 로컬 오리진을 각각 추가하세요. 설치 오류를 해결하려고 와일드카드를 추가하지 마세요. 공개 슬러그를 복사한 누구나 에이전트를 임베드하고 사이트 크레딧을 사용할 수 있게 됩니다.
콘텐츠 보안 정책#
로더에는 스크립트 권한, 위젯에는 프레임 권한, 로더의 디자인 요청에는 연결 권한이 필요할 수 있습니다. 다음 출처를 호스트의 기존 지시문에 병합하고 완성된 정책 전체를 이 최소 예시로 교체하지 마세요.
Content-Security-Policy:
default-src 'self';
script-src 'self' https://makeagent.fast;
frame-src https://makeagent.fast;
connect-src 'self' https://makeagent.fast;사이트가 script-src-elem을 사용하면 그 지시문에도 https://makeagent.fast를 추가합니다. 외부 로더에는 unsafe-inline이 필요하지 않지만 호스트 프레임워크에는 별도의 nonce 또는 해시 요구 사항이 있을 수 있습니다. 테스트 중에는 보고 전용 정책을 사용할 수 있습니다.
Content-Security-Policy-Report-Only:
script-src 'self' https://makeagent.fast;
frame-src https://makeagent.fast;
connect-src 'self' https://makeagent.fast;브라우저 콘솔에 CSP 위반이 표시되면 default-src를 넓게 풀지 말고 오류에 표시된 지시문만 수정한 뒤 공개 페이지를 다시 테스트하세요.
마이크 및 브라우저 권한#
로더는 allow="microphone; autoplay; clipboard-write"로 iframe을 생성합니다. 더 엄격한 호스트 수준 Permissions Policy가 이 권한을 다시 차단할 수 있습니다. 음성을 사용한다면 호스트 응답에서 Make Agent Fast 프레임 오리진을 허용하세요.
Permissions-Policy: microphone=(self "https://makeagent.fast")방문자가 브라우저에서도 마이크 접근을 허용해야 합니다. 브라우저는 보통 안전하지 않은 공개 오리진에서 마이크를 제한하므로 HTTPS에서 테스트하세요. 텍스트 채팅에는 마이크 권한이 필요하지 않습니다.
메시지 및 프레임 경계#
로더는 현재 사이트 슬러그와 연결된 maf:ready, maf:open, maf:close, 테마 생명주기 메시지만 처리합니다. 프레임에서 오는 메시지는 https://makeagent.fast 오리진과 대조됩니다. 로더를 자체 번들에 복사하거나 이 오리진 검증을 제거하지 마세요.
호스트 페이지 코드는 iframe DOM에 직접 접근하지 않아야 합니다. 프레임은 의도적으로 교차 오리진이며 지원되는 통합 표면은 로더, 문서화된 data-* 속성 및 아래의 신원 식별 메서드입니다.
비밀 값 및 방문자 식별 정보#
사이트 슬러그와 로더 URL은 공개 값입니다. 그 외 값은 페이지 소스에 넣지 마세요.
- MAF API 키, OAuth 토큰, AI 제공자 키, 커넥터 토큰, 웹훅 시크릿을 스니펫에 넣지 마세요.
- JavaScript 번들에 비밀 값을 빌드하거나
NEXT_PUBLIC_*,VITE_*같은 브라우저 환경 변수로 노출하지 마세요. - 애플리케이션이 사이트 생성, 에이전트 업데이트, 비공개 워크스페이스 데이터 조회를 해야 한다면 서버 측 API 통합을 사용하세요.
- 이메일 주소, 계정 ID 같은 방문자 데이터를
data-label,data-locale, 쿼리 매개변수에 넣지 마세요.
로그인한 고객 식별#
에이전트 → 작업 → 로그인한 고객에서 비밀 키를 만들고 표시될 때 복사하세요. 서버의 MAF_SECRET_KEY에만 저장하고 브라우저 코드, 공개 환경 변수, 저장소에 넣지 마세요. 이 에이전트 비밀 키는 워크스페이스 API 키와 다릅니다. 교체하면 기존 토큰이 무효화되고 조회 요청의 서명 키도 바뀝니다. 삭제하면 새 비밀 키를 설정할 때까지 고객 식별과 조회가 비활성화됩니다.
기존 설치 코드의 로더 URL을 https://makeagent.fast/embed.js?v=20261022-open로 바꾸세요. 이전 버전 URL은 1년 동안 캐시될 수 있으며 이 SDK를 제공하지 않습니다. 기존 origin 허용 목록과 CSP 보호는 유지하세요.
인증된 서버가 자체 세션의 고객 정보로 토큰을 발급해야 합니다. 브라우저가 임의로 보낸 고객 ID에 서명하지 마세요. 다음 함수는 서버에서만 실행합니다:
import { createHmac } from "node:crypto";
export function signCustomerIdentity(customer) {
const secret = process.env.MAF_SECRET_KEY;
if (!secret) throw new Error("MAF_SECRET_KEY is required");
const encode = (value) => Buffer.from(JSON.stringify(value)).toString("base64url");
const now = Math.floor(Date.now() / 1000);
const header = encode({ alg: "HS256", typ: "JWT" });
const payload = encode({
sub: customer.id,
email: customer.email,
name: customer.name,
iat: now,
exp: now + 3600,
});
const body = `${header}.${payload}`;
const signature = createHmac("sha256", secret).update(body).digest("base64url");
return `${body}.${signature}`;
}헤더는 alg: "HS256", typ: "JWT"여야 합니다. sub는 비어 있지 않은 최대 128자의 고정 고객 ID입니다. exp는 현재보다 미래이면서 최대 24시간 이내인 정수형 Unix 초 타임스탬프입니다. 선택 항목 iat는 정수, email은 유효한 이메일로 최대 160자, name은 최대 120자입니다. 전체 토큰은 2,048자 이하여야 합니다. 필요 없는 선택 항목은 생략하세요. JWT 내용은 서명되지만 암호화되지 않습니다.
HTTPS로 해당 인증 세션에 토큰만 반환하고 Cache-Control: no-store를 설정하세요. 토큰을 로그, URL, localStorage에 저장하지 마세요. embed.js가 로드된 뒤 응답으로 받은 토큰을 전달합니다:
window.MakeAgentFast.identify(token);로더 실행 전에 초기화하려면 앱 시작 코드에서 window.MakeAgentFastSettings = { identityToken: token }을 설정하세요. 로더는 최신 토큰을 메모리에 유지하고 프레임 준비 후 전달합니다. 만료 전에 인증된 서버에서 새 토큰을 받아 identify를 다시 호출하세요. 모든 채팅 요청에 토큰이 포함되며 대화 요청에는 x-maf-identity가 사용됩니다. 검증된 호스트 신원은 af_xid 쿠키에 의존하지 않습니다.
앱에서 로그아웃할 때 다른 계정의 채팅을 보여주기 전에 다음을 호출하고 앱에 남은 초기화 토큰도 지우세요:
window.MakeAgentFast.logout();위젯 신원과 로컬 대화 캐시를 초기화하지만 자체 앱에서 로그아웃하거나 복사된 토큰을 폐기하지는 않습니다. 다른 고객의 sub로 바뀌어도 캐시가 초기화됩니다. 위조·만료·다른 에이전트용 토큰으로는 해당 로그인 고객의 기록에 접근할 수 없으며 일반 방문자 경로로 돌아갑니다. 짧은 유효 기간을 사용하고 에이전트마다 별도 비밀 키를 유지하세요. 소유자 리허설은 신원 토큰을 무시하므로 실제 임베드에서 테스트 계정 두 개로 격리를 확인하세요.
동의, 개인정보, 보존#
개인정보 및 동의 정책에 맞게 임베드를 분류하세요. 동의 관리자가 필수가 아닌 제3자 스크립트를 차단한다면 해당 동의를 받은 후에만 embed.js를 로드합니다. 그 전에는 관리자를 우회하지 말고 일반 링크나 비활성 자리 표시자를 보여 주세요.
정책과 관련 법률이 요구하면 AI, 마이크 녹음, 리드 수집, 분석, 외부 메시징 제공자 사용을 방문자에게 알리세요. 출시 전에 사이트의 대화 보존 및 삭제 흐름을 확인하세요. 임베드를 연결 해제하거나 제거하는 것만으로 기존 대화가 삭제되지는 않습니다.
보안 출시 체크리스트#
- 고객 웹사이트를 배포하고 임베드 에이전트를 활성화해 테스트했습니다.
- 의도한 정확한 상위 오리진만 허용했습니다.
- 호스트 CSP가 광범위한 와일드카드 없이 스크립트, 프레임, 디자인 요청을 허용합니다.
- 음성을 사용할 때만 마이크를 허용하고 HTTPS에서 테스트했습니다.
- HTML, 번들 출력, 브라우저 로그에 자격 증명이나 비공개 방문자 값이 없습니다.
- 동의 전후의 동의 관리자 동작을 테스트했습니다.
- 허용 목록에 없는 오리진에서는 복사된 스니펫이 실패합니다.