diff --git a/Dockerfile b/Dockerfile index 18ac37f71..f6865f64b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -38,16 +38,22 @@ RUN apt-get update \ libpq5 \ && rm -rf /var/lib/apt/lists/* +# Create a non-root user +RUN groupadd -r appuser && useradd -r -g appuser appuser + # Set the working directory WORKDIR /app # Copy virtual environment from builder COPY --from=builder /app/.venv /app/.venv -# Copy application code -COPY --from=builder /app/intentkit /app/intentkit -COPY --from=builder /app/app /app/app -COPY --from=builder /app/scripts /app/scripts +# Copy application code with correct ownership +COPY --from=builder --chown=appuser:appuser /app/intentkit /app/intentkit +COPY --from=builder --chown=appuser:appuser /app/app /app/app +COPY --from=builder --chown=appuser:appuser /app/scripts /app/scripts + +# Switch to non-root user +USER appuser ARG RELEASE=local ENV RELEASE=$RELEASE diff --git a/app/api.py b/app/api.py index 76da48145..76d3ad5fb 100644 --- a/app/api.py +++ b/app/api.py @@ -114,7 +114,7 @@ def _load_agent_api_docs() -> str: # Add CORS middleware to the Agent API sub-application _ = agent_app.add_middleware( CORSMiddleware, - allow_origins=["*"], # Allows all origins + allow_origins=config.cors_allow_origins, # Allows configured origins allow_methods=["*"], # Allows all methods allow_headers=["*"], # Allows all headers ) @@ -187,7 +187,7 @@ async def lifespan(app: FastAPI): # Add CORS middleware _ = app.add_middleware( CORSMiddleware, - allow_origins=["*"], # Allows all origins + allow_origins=config.cors_allow_origins, # Allows configured origins allow_methods=["*"], # Allows all methods allow_headers=["*"], # Allows all headers ) diff --git a/intentkit/config/config.py b/intentkit/config/config.py index b787c5bcd..5c5f294ea 100644 --- a/intentkit/config/config.py +++ b/intentkit/config/config.py @@ -114,6 +114,11 @@ def __init__(self) -> None: self.open_api_base_url: str = self.load( "OPEN_API_BASE_URL", "http://localhost:8000" ) + # CORS + cors_origins_raw = self.load("CORS_ALLOW_ORIGINS", "*") + self.cors_allow_origins: list[str] = [ + o.strip() for o in cors_origins_raw.split(",") if o.strip() + ] # CDP SDK Configuration self.cdp_api_key_id: str | None = self.load("CDP_API_KEY_ID") self.cdp_api_key_secret: str | None = self.load("CDP_API_KEY_SECRET") diff --git a/intentkit/wallets/privy_client.py b/intentkit/wallets/privy_client.py index a5590a181..8067c0902 100644 --- a/intentkit/wallets/privy_client.py +++ b/intentkit/wallets/privy_client.py @@ -244,10 +244,9 @@ async def create_wallet( if response.status_code not in (200, 201): logger.info( - "Privy create_wallet response: status=%s auth_sig_count=%s body=%s", + "Privy create_wallet response: status=%s auth_sig_count=%s", response.status_code, signature_count, - response.text, ) raise IntentKitAPIError( @@ -351,12 +350,11 @@ async def sign_message(self, wallet_id: str, message: str) -> str: if response.status_code not in (200, 201): logger.info( - "Privy rpc response: wallet_id=%s method=%s status=%s auth_sig_count=%s body=%s", + "Privy rpc response: wallet_id=%s method=%s status=%s auth_sig_count=%s", wallet_id, payload.get("method"), response.status_code, signature_count, - response.text, ) raise IntentKitAPIError( @@ -428,12 +426,11 @@ async def sign_hash(self, wallet_id: str, hash_bytes: bytes) -> str: if response.status_code not in (200, 201): logger.info( - "Privy rpc response: wallet_id=%s method=%s status=%s auth_sig_count=%s body=%s", + "Privy rpc response: wallet_id=%s method=%s status=%s auth_sig_count=%s", wallet_id, payload.get("method"), response.status_code, signature_count, - response.text, ) raise IntentKitAPIError( @@ -497,12 +494,11 @@ async def sign_typed_data(self, wallet_id: str, typed_data: dict[str, Any]) -> s if response.status_code not in (200, 201): logger.info( - "Privy rpc response: wallet_id=%s method=%s status=%s auth_sig_count=%s body=%s", + "Privy rpc response: wallet_id=%s method=%s status=%s auth_sig_count=%s", wallet_id, payload.get("method"), response.status_code, signature_count, - response.text, ) raise IntentKitAPIError( @@ -580,18 +576,17 @@ async def send_transaction( if response.status_code not in (200, 201): logger.info( - "Privy rpc response: wallet_id=%s method=%s status=%s auth_sig_count=%s body=%s", + "Privy rpc response: wallet_id=%s method=%s status=%s auth_sig_count=%s", wallet_id, payload.get("method"), response.status_code, signature_count, - response.text, ) raise IntentKitAPIError( response.status_code, "PrivyAPIError", - f"Failed to send transaction: {response.text}", + "Failed to send transaction with Privy wallet", ) data_response = response.json()