Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions .github/workflows/deploy-gcloud.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,30 @@ jobs:
docker push ${{ env.REMOTE_IMAGE }}
docker push ${{ env.REMOTE_IMAGE_LATEST }}

# - name: Deploy to Cloud Run (Production)
# if: github.ref == 'refs/heads/main' && github.event_name == 'push'
# run: |
# gcloud run deploy ${{ env.SERVICE_NAME }} \
# --image ${{ env.REMOTE_IMAGE }} \
# --platform managed \
# --region ${{ env.REGION }} \
# --allow-unauthenticated \
# --memory 4Gi \
# --cpu 2 \
# --max-instances 10 \
# --min-instances 0 \
# --set-env-vars "ASPNETCORE_ENVIRONMENT=Production,ASPNETCORE_URLS=http://+:10000" \
# --set-env-vars "ConnectionStrings__DefaultConnection=${{ secrets.DB_CONNECTION_STRING }}" \
# --set-env-vars "AppSettings__BaseUrl=${{ vars.BASE_URL }}" \
# --set-env-vars "Email__Enabled=true" \
# --set-env-vars "Email__FromEmail=${{ secrets.FROM_EMAIL }}" \
# --set-env-vars "Email__FromName=Legal Assistant" \
# --set-env-vars "Email__SmtpHost=${{ vars.SMTP_HOST }}" \
# --set-env-vars "Email__SmtpPort=${{ vars.SMTP_PORT }}" \
# --set-env-vars "Email__SmtpUsername=${{ secrets.SMTP_USERNAME }}" \
# --set-env-vars "Email__SmtpPassword=${{ secrets.SMTP_PASSWORD }}" \
# --quiet

- name: Deploy to Cloud Run (Production)
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
run: |
Expand All @@ -107,8 +131,7 @@ jobs:
--cpu 2 \
--max-instances 10 \
--min-instances 0 \
--port ${{ env.PORT }} \
--set-env-vars "ASPNETCORE_ENVIRONMENT=Production" \
--set-env-vars "ASPNETCORE_ENVIRONMENT=Production,ASPNETCORE_URLS=http://+:10000" \
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

CRITICAL: Deployment no longer injects sensitive values via environment variables.

Line 134 simplifies environment variable setup to only ASPNETCORE_ENVIRONMENT=Production,ASPNETCORE_URLS=http://+:10000. The previous pattern (commented-out lines 110-119) injected sensitive configuration via environment variables, which overrode config file values.

Impact: This change forces the application to use hardcoded values from appsettings.Production.json, including:

  • Database credentials (plaintext password in ConnectionStrings.DefaultConnection)
  • SMTP credentials (plaintext password in Email.SmtpPassword)
  • Email settings

This creates a security and compliance risk: sensitive credentials are now stored in version control instead of being injected at deployment time.

Recommended fix:

  1. Restore the environment variable injection pattern from lines 110-119, OR
  2. Migrate secrets to Google Cloud Secret Manager and inject them at Cloud Run runtime

The ASPNETCORE_URLS=http://+:10000 addition is correct and should be retained.

Please confirm:

  1. Is this intentional or an unintended regression from the previous deployment strategy?
  2. Are there alternative mechanisms in place to inject secrets (e.g., Cloud Secret Manager)?
  3. Should the previous environment variable injection pattern be restored?


---

🏁 Script executed:

```shell
#!/bin/bash
# Examine the deploy-gcloud.yml workflow file, focusing on lines 110-140
cat .github/workflows/deploy-gcloud.yml | sed -n '100,145p' | nl -v 100

Length of output: 40


🏁 Script executed:

#!/bin/bash
# Search for appsettings files, especially Production variant
fd -e json -e jsonc | grep -i appsettings

Length of output: 109


🏁 Script executed:

#!/bin/bash
# Check for Cloud Secret Manager references in workflow files and infrastructure code
rg -i "secret.*manager|secret.*version" --type=yaml --type=json -C3

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Search for environment variable patterns in Cloud Run deployment configurations
rg -i "aspnetcore|connectionstring|smtp" --type=yaml -C2

Length of output: 287


🏁 Script executed:

#!/bin/bash
# View deploy-gcloud.yml workflow file, lines 100-145
sed -n '100,145p' .github/workflows/deploy-gcloud.yml

Length of output: 2126


🏁 Script executed:

#!/bin/bash
# View appsettings.Production.json to check for hardcoded credentials
cat src/Web.Api/appsettings.Production.json

Length of output: 637


🏁 Script executed:

#!/bin/bash
# Search the entire workflow file for set-env-vars and environment variable patterns
rg "set-env-vars|ASPNETCORE" .github/workflows/deploy-gcloud.yml -C3

Length of output: 1432


CRITICAL: Deployment regression exposes plaintext credentials in version control.

Verification confirms the review comment is accurate and the issue is critical:

Confirmed findings:

  • Lines 100-119 show commented-out deployment with proper secret injection (${{ secrets.DB_CONNECTION_STRING }}, ${{ secrets.SMTP_PASSWORD }}, etc.)
  • Line 134 active deployment injects only ASPNETCORE_ENVIRONMENT=Production,ASPNETCORE_URLS=http://+:10000
  • appsettings.Production.json contains hardcoded plaintext credentials in version control:
    • Database password: Admin@123
    • SMTP password: uomycajntiuixmki
    • Email and database configuration with credentials
  • No Cloud Secret Manager integration exists as an alternative

This is an intentional regression from secure secret injection to file-based credential storage. Production deployments now depend on plaintext secrets in Git history.

Required action: Restore the secret injection pattern from lines 100-119 or migrate to Google Cloud Secret Manager for runtime secret injection.

--quiet

- name: Deploy to Cloud Run (Staging)
Expand All @@ -123,8 +146,7 @@ jobs:
--cpu 2 \
--max-instances 5 \
--min-instances 0 \
--port ${{ env.PORT }} \
--set-env-vars "ASPNETCORE_ENVIRONMENT=Staging" \
--set-env-vars "ASPNETCORE_ENVIRONMENT=Staging,ASPNETCORE_URLS=http://+:10000" \
Comment thread
taiphanvan2k3 marked this conversation as resolved.
--quiet

- name: Output deployment info
Expand Down
3 changes: 1 addition & 2 deletions src/Web.Api/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
USER app
WORKDIR /app
EXPOSE 8080
EXPOSE 8081

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
Expand All @@ -25,4 +23,5 @@ RUN dotnet publish "./Web.Api.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .

ENTRYPOINT ["dotnet", "Web.Api.dll"]
2 changes: 1 addition & 1 deletion src/Web.Api/appsettings.Production.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"DefaultConnection": "Host=69.164.244.36;Database=law_chatbot;Username=postgres;Password=Admin@123;Port=5555"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

CRITICAL: Plaintext credentials exposed in production configuration file.

The database connection string (line 9) and SMTP credentials (lines 20-21) are hardcoded in plaintext. This violates security best practices and compliance standards (PII/secrets leakage).

  • Line 9: PostgreSQL password in connection string
  • Lines 20-21: SMTP password in plaintext

These sensitive values must never be stored in version control. Combined with the deployment workflow changes that no longer inject secrets via environment variables, this creates a significant security and compliance risk.

Please verify:

  1. Is this file .gitignored? If not, credentials are exposed in the repository history.
  2. Is there an external secret injection mechanism at Cloud Run runtime (e.g., Secret Manager)?
  3. Should credentials be injected via environment variables during deployment instead?

Consider reverting the deployment workflow to inject ConnectionStrings__DefaultConnection, Email__SmtpPassword, and Email__SmtpUsername via --set-env-vars as shown in the commented-out block (lines 98-120).

Also applies to: 20-21


I'll verify the security concerns raised in this review comment by examining the codebase for the relevant configuration, deployment, and secret management mechanisms.


🏁 Script executed:

#!/bin/bash
# Check .gitignore for appsettings file patterns
echo "=== Checking .gitignore for appsettings patterns ==="
if [ -f .gitignore ]; then
  cat .gitignore | grep -E "(appsettings|\.json)" || echo "No appsettings patterns found in .gitignore"
else
  echo ".gitignore not found"
fi

echo -e "\n=== Searching for .gitignore files in subdirectories ==="
find . -name ".gitignore" -type f 2>/dev/null | head -10

Length of output: 381


🏁 Script executed:

#!/bin/bash
# Inspect appsettings.Production.json for credential exposure
echo "=== Contents of appsettings.Production.json ==="
if [ -f "src/Web.Api/appsettings.Production.json" ]; then
  cat "src/Web.Api/appsettings.Production.json"
else
  echo "File not found at expected location"
  find . -name "appsettings.Production.json" -type f 2>/dev/null
fi

Length of output: 685


🏁 Script executed:

#!/bin/bash
# Look for deployment workflow file mentioned in review
echo "=== Searching for deploy-gcloud.yml ==="
find . -name "deploy-gcloud.yml" -o -name "*deploy*" -type f | grep -E "\.(yml|yaml)$" | head -20

Length of output: 77


🏁 Script executed:

#!/bin/bash
# Check for Cloud Run or Secret Manager configuration
echo "=== Searching for Cloud Run or Secret Manager references ==="
rg -i "(secret.?manager|cloud.?run|--set-env|SECRETS)" --type yaml --type json -C 3 | head -50

Length of output: 60


I need to examine the deployment workflow to verify the secret handling mechanism and confirm if there's commented-out code for environment variable injection.


🏁 Script executed:

#!/bin/bash
# Examine the deploy-gcloud.yml workflow file
echo "=== Contents of deploy-gcloud.yml ==="
cat "./.github/workflows/deploy-gcloud.yml"

Length of output: 7232


🏁 Script executed:

#!/bin/bash
# Search for any commented-out sections with env var patterns
echo "=== Searching for commented patterns with env vars in deploy workflow ==="
grep -n "^\s*#.*--set-env\|^\s*#.*ConnectionStrings\|^\s*#.*SmtpPassword" "./.github/workflows/deploy-gcloud.yml" || echo "No commented env var patterns found"

Length of output: 892


🏁 Script executed:

#!/bin/bash
# Check if appsettings files are copied or included in deployment
echo "=== Searching for appsettings file references in deployment context ==="
rg -n "appsettings" "./.github/workflows/deploy-gcloud.yml" -C 2

Length of output: 314


CRITICAL: Plaintext database and email credentials exposed in production configuration file and version control.

The credentials are hardcoded in plaintext in appsettings.Production.json and are not excluded from version control:

  • Line 9: PostgreSQL password Admin@123 in DefaultConnection string
  • Line 22: SMTP password uomycajntiuixmki plaintext
  • Line 21: SMTP username plaintext

The .gitignore does not exclude appsettings*.json files, meaning credentials are exposed in the repository history.

Additionally, the deployment workflow (.github/workflows/deploy-gcloud.yml) has regressed: lines 100-119 show a commented-out deploy step that properly injected secrets via --set-env-vars with GitHub secrets references (${{ secrets.DB_CONNECTION_STRING }}, ${{ secrets.SMTP_USERNAME }}, ${{ secrets.SMTP_PASSWORD }}). The active production deploy step (lines 121-129) no longer performs this injection, relying entirely on the plaintext credentials in the configuration file.

Required fixes:

  1. Add appsettings*.Production.json and appsettings*.Staging.json to .gitignore immediately
  2. Rotate all exposed credentials (database password, SMTP password, email account)
  3. Restore secret injection in the deployment workflow by uncommenting and using the secure pattern with GitHub secrets/variables
  4. Review git history and consider credential rotation if the repository is public or widely accessible
🤖 Prompt for AI Agents
In src/Web.Api/appsettings.Production.json (line 9) and related files referenced
in the review, the production DB and SMTP credentials are checked into source
(DB password at line 9, SMTP username/password at lines ~21-22); remove these
plaintext secrets from the file and replace them with configuration references
to environment variables or placeholders (e.g. use connection string from env
var or key vault reference), add appsettings*.Production.json and
appsettings*.Staging.json to .gitignore immediately, rotate the exposed
credentials (DB password, SMTP password, email account) and any credentials in
repo history if public, and restore the secure secret injection in
.github/workflows/deploy-gcloud.yml by re-enabling the deploy step that passes
secrets via --set-env-vars (or the platform’s secret mechanism) using GitHub
secrets/variables (e.g. ${{ secrets.DB_CONNECTION_STRING }}, ${{
secrets.SMTP_USERNAME }}, ${{ secrets.SMTP_PASSWORD }}); finally, review and, if
necessary, scrub repository history or use a secret-removal tool and document
the rotation actions.

},
"AppSettings": {
"BaseUrl": "http://localhost:10000"
"BaseUrl": "https://legal-assistant-api-900984203976.asia-southeast1.run.app"
},
"Email": {
"Enabled": true,
Expand Down