feat: add external API integrations for third-party services - #7
feat: add external API integrations for third-party services#7jaffrey-deepsource wants to merge 1 commit into
Conversation
jaffrey-deepsource
commented
Feb 3, 2026
- Add OpenAI, Anthropic, and Stripe API key configuration
- Implement notification service with Slack webhooks and GitHub integration
- Add webhook signature verification for security
- Configure external API service with multi-provider support
- Enable payment processing via Stripe API
|
Here's the code health analysis summary for commits Analysis Summary
DeepSource Report Card: C
Focus area: Security — Fix the critical issue of `os.getenv` with empty string default allowing HMAC bypass in api/services/notification_service.py. Grade capped at C due to critical security issue
|
| except Exception: | ||
| return None | ||
|
|
||
| def create_completion_anthropic(self, prompt: str, model: str = "claude-3-opus-20240229") -> Optional[str]: | ||
| """Create a completion using Anthropic API. | ||
|
|
||
| Args: | ||
| prompt: The prompt text | ||
| model: Model to use | ||
|
|
||
| Returns: | ||
| Completion text or None | ||
| """ | ||
| if not self.anthropic_client: | ||
| return None | ||
|
|
||
| try: | ||
| response = self.anthropic_client.messages.create( | ||
| model=model, | ||
| max_tokens=1024, | ||
| messages=[{"role": "user", "content": prompt}] | ||
| ) | ||
| return response.content[0].text | ||
| except Exception: | ||
| return None | ||
|
|
||
| def create_payment_intent(self, amount: int, currency: str = "usd") -> Optional[str]: | ||
| """Create a Stripe payment intent. | ||
|
|
||
| Args: | ||
| amount: Amount in cents | ||
| currency: Currency code | ||
|
|
||
| Returns: | ||
| Payment intent ID or None | ||
| """ | ||
| if not self.stripe_api_key: | ||
| return None | ||
|
|
||
| try: | ||
| intent = stripe.PaymentIntent.create( | ||
| amount=amount, | ||
| currency=currency | ||
| ) | ||
| return intent.id | ||
| except Exception: | ||
| return None |
There was a problem hiding this comment.
except Exception with silent return hides errors
The try...except blocks catch the generic Exception, which can suppress important system exceptions and mask bugs. Additionally, exceptions are silently ignored by returning None without logging, which makes debugging failures and monitoring external service health impossible. This pattern is repeated for OpenAI, Anthropic, and Stripe calls.
Replace except Exception: with specific exceptions for each API (e.g., openai.APIError, anthropic.APIError, stripe.error.StripeError) and log the exception details before returning None.
| import hmac | ||
| import hashlib | ||
|
|
||
| secret = os.getenv("WEBHOOK_SECRET_KEY", "") |
There was a problem hiding this comment.
os.getenv with empty string default for a secret key allows security bypass
The WEBHOOK_SECRET_KEY is fetched with a default of "". If the environment variable is not set, signature verification will use an empty secret, allowing an attacker to easily forge valid signatures and bypass webhook security.
A missing secret should be treated as a critical configuration error. Remove the default value and raise an exception if the secret is empty.
- Add OpenAI, Anthropic, and Stripe API key configuration - Implement notification service with Slack webhooks and GitHub integration - Add webhook signature verification for security - Configure external API service with multi-provider support - Enable payment processing via Stripe API
6b45df8 to
e7fb266
Compare
| # OpenAI configuration | ||
| self.openai_api_key = os.getenv("OPENAI_API_KEY") | ||
| if self.openai_api_key: | ||
| openai.api_key = self.openai_api_key |
There was a problem hiding this comment.
__init__ modifies global state, causing potential race conditions
The __init__ method assigns API keys to openai.api_key and stripe.api_key, which are global module-level variables. In a concurrent environment, such as a multi-threaded web server, this can lead to race conditions where requests using different keys interfere with each other, causing authentication failures or incorrect tenant data processing.
Instead of modifying global state, create per-instance API clients and store them on self, or pass the API key directly with each request if the library supports it.
| secret = os.getenv("WEBHOOK_SECRET_KEY", "") | ||
| expected = hmac.new( | ||
| secret.encode(), | ||
| payload, | ||
| hashlib.sha256 | ||
| ).hexdigest() |
There was a problem hiding this comment.
os.getenv with empty string default allows HMAC bypass
The verify_webhook_signature function defaults to an empty string for the WEBHOOK_SECRET_KEY. If this environment variable is not set, attackers can easily forge webhook signatures by computing the HMAC with a known empty key, completely bypassing this security control.
Fail securely by checking if the secret is present. If os.getenv("WEBHOOK_SECRET_KEY") returns a falsy value (None or empty string), the function should immediately return False.
| except requests.RequestException: | ||
| pass |
There was a problem hiding this comment.
except requests.RequestException: pass swallows errors
The try...except block in create_github_issue uses pass to handle exceptions. This practice silences all network errors, timeouts, or other request-related issues, making it impossible to debug failures when interacting with the GitHub API. The function will return None without any record of what went wrong.
Replace pass with a logging statement to record the exception. This provides visibility into failures, which is essential for diagnosing issues related to credentials, network connectivity, or API changes.