Skip to content

Remove committed payment credentials#98

Merged
teesofttech merged 1 commit into
masterfrom
security/remove-exposed-credentials
Jul 17, 2026
Merged

Remove committed payment credentials#98
teesofttech merged 1 commit into
masterfrom
security/remove-exposed-credentials

Conversation

@teesofttech

@teesofttech teesofttech commented Jul 17, 2026

Copy link
Copy Markdown
Owner

Summary

  • replace committed payment and database credentials with safe placeholders
  • load sample credentials from the .NET configuration stack and document user-secrets / managed secret stores
  • add a repository regression test for credentials in appsettings files
  • add Gitleaks scanning for pull requests and security-related branches

TDD

  • Red: added RepositorySecurityTests.Sample_configuration_must_not_contain_committed_credentials; it failed first on the Presentation sample and then exposed the same defect in the Example configuration
  • Green: removed the committed values and tightened placeholder validation; the suite now passes with 91 passed and 2 intentionally skipped

Senior .NET review

  • removed hard-coded gateway activation that bypassed configuration in the Presentation app
  • changed the NuGet quick start so it no longer encourages credentials in source code
  • added UserSecretsId to the Example project
  • limited the change to configuration security; unrelated repository formatting and local untracked files were left untouched

Provider guidance reviewed

  • Paystack authentication and key-management guidance
  • Flutterwave v3 authentication and compromised-key guidance
  • Stripe secret-key management guidance

Validation

  • dotnet build PayBridge.SDK.sln --configuration Release (passes; one pre-existing nullable warning tracked in build: resolve remaining nullable warning and enforce warning-free builds #70)
  • dotnet test PayBridge.SDK.sln --configuration Release --no-restore (91 passed, 2 skipped)
  • targeted dotnet format ... whitespace --verify-no-changes
  • workflow YAML parse
  • Gitleaks v8.27.2 scan: no leaks found
  • git diff --check

Security follow-up

This PR removes credentials from the current tree and prevents recurrence. It cannot rotate provider credentials or safely purge shared Git history. A maintainer with Paystack, Flutterwave, and Stripe dashboard access must rotate the exposed credentials immediately; history cleanup should be coordinated separately because it rewrites shared commits.

Refs #60

Summary by CodeRabbit

  • Security

    • Added automated secret scanning for code changes and repository updates.
    • Removed credential examples from tracked configuration files and replaced them with safe placeholders.
  • Configuration

    • Simplified PayBridge setup to load gateway settings from application configuration.
    • Added guidance for using .NET user-secrets, environment variables, or managed secret stores.
  • Documentation

    • Updated setup guides and examples to clarify secure credential configuration.
  • Tests

    • Added checks to prevent unsafe credentials from being committed to sample configuration files.

Copilot AI review requested due to automatic review settings July 17, 2026 17:21
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The pull request replaces tracked sample credentials with placeholders, binds PayBridge setup from configuration, documents .NET user-secrets usage, adds repository placeholder validation, and introduces a gitleaks GitHub Actions workflow.

Changes

Credential-safe configuration

Layer / File(s) Summary
Credential-free configuration templates
PayBridge.SDK.Example/appsettings*.json, PayBridge.SDK.Presentation/appsettings.json
Tracked connection strings and gateway credentials are replaced with placeholders, and default enabled gateway lists are cleared.
Configuration-based SDK registration
PayBridge.SDK.Presentation/Program.cs, PayBridge.SDK.Example/Program.cs, PayBridge.SDK.Example/PayBridge.SDK.Example.csproj
The presentation sample registers PayBridge from builder.Configuration; the example project enables user-secrets metadata and updates setup comments.
User-secrets setup documentation
PayBridge.SDK.Example/README.md, README.md, README.nuget.md
Documentation now directs database and gateway configuration to user-secrets, environment variables, or managed secret stores.
Secret scanning and placeholder validation
.github/workflows/secret-scanning.yml, PayBridge.SDK.Test/Unit/RepositorySecurityTests.cs
Gitleaks scans repository contents, while a unit test rejects unsafe sensitive values in tracked appsettings*.json files.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • teesofttech/PayBridge#56: Adds or aligns the configuration-based AddPayBridge overload and gateway registration behavior used by this change.

Suggested reviewers: copilot

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: removing committed payment credentials and replacing them with safer configuration handling.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch security/remove-exposed-credentials

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Biome (2.5.3)
PayBridge.SDK.Example/appsettings.Development.json

File contains syntax errors that prevent linting: Line 2: JSON standard does not allow comments.; Line 3: End of file expected; Line 3: End of file expected; Line 3: End of file expected; Line 8: End of file expected; Line 10: End of file expected; Line 10: End of file expected; Line 10: End of file expected; Line 28: End of file expected

PayBridge.SDK.Example/appsettings.json

File contains syntax errors that prevent linting: Line 2: JSON standard does not allow comments.; Line 18: End of file expected; Line 18: End of file expected; Line 18: End of file expected; Line 23: End of file expected; Line 24: End of file expected; Line 24: End of file expected; Line 24: End of file expected; Line 24: End of file expected; Line 26: JSON standard does not allow comments.; Line 31: End of file expected; Line 31: End of file expected; Line 31: End of file expected; Line 31: End of file expected; Line 32: End of file expected; Line 32: End of file expected; Line 32: End of file expected; Line 34: End of file expected; Line 36: End of file expected; Line 36: End of file expected; Line 36: End of file expected; Line 37: JSON standard does not allow comments.; Line 41: End of file expected; Line 41: End of file expected; Line 41: End of file expected; Line 41: End of file expected; Line 43: JSON standard does not allow comments.; Line 48: End of file expected; Line 48: En

... [truncated 1415 characters] ...

file expected; Line 108: End of file expected; Line 108: End of file expected; Line 112: End of file expected; Line 114: JSON standard does not allow comments.; Line 116: End of file expected; Line 116: End of file expected; Line 116: End of file expected; Line 122: End of file expected; Line 124: End of file expected; Line 124: End of file expected; Line 124: End of file expected; Line 129: End of file expected; Line 131: End of file expected; Line 131: End of file expected; Line 131: End of file expected; Line 136: End of file expected; Line 138: End of file expected; Line 138: End of file expected; Line 138: End of file expected; Line 142: End of file expected; Line 144: End of file expected; Line 144: End of file expected; Line 144: End of file expected; Line 148: End of file expected


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@teesofttech teesofttech added the area: security Credentials, webhooks, dependency, and application security label Jul 17, 2026
@teesofttech teesofttech added the priority: P0 Release blocker or urgent security/correctness risk label Jul 17, 2026

Copilot AI left a comment

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.

Pull request overview

This PR removes committed payment/database credentials from tracked configuration and documentation, shifts local secret setup to the .NET configuration stack (user-secrets/env/secret stores), and adds automated guardrails (unit test + CI secret scan) to prevent regressions.

Changes:

  • Replaced hard-coded gateway activation and committed appsettings*.json credential values with placeholders and configuration binding.
  • Added a repository security unit test to detect committed credentials in tracked appsettings*.json files.
  • Introduced a GitHub Actions workflow to scan PRs and key branches with Gitleaks.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
README.nuget.md Updates NuGet quickstart to configure PayBridge via configuration and adds guidance to avoid committing credentials.
README.md Updates setup docs to use user-secrets for connection strings and gateway credentials.
PayBridge.SDK.Test/Unit/RepositorySecurityTests.cs Adds regression test that scans tracked appsettings*.json for committed credential values.
PayBridge.SDK.Presentation/Program.cs Removes hard-coded gateway enablement and binds PayBridge from configuration.
PayBridge.SDK.Presentation/appsettings.json Replaces committed DB/gateway values with placeholders and clears enabled gateways.
PayBridge.SDK.Example/README.md Updates example instructions to store credentials outside the repo (user-secrets/env).
PayBridge.SDK.Example/Program.cs Refreshes example comments to align with configuration-stack usage.
PayBridge.SDK.Example/PayBridge.SDK.Example.csproj Adds UserSecretsId for local secrets support.
PayBridge.SDK.Example/appsettings.json Converts example configuration to schema/placeholder-only tracked settings.
PayBridge.SDK.Example/appsettings.Development.json Keeps dev settings tracked but credential-free with placeholders.
.github/workflows/secret-scanning.yml Adds Gitleaks scanning for PRs and security-related branches.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +19 to +23
"Passkey",
"Password",
"PrivateKey",
"SecretKey",
"TerminalResourceKey"
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>PayBridge.SDK.Example</RootNamespace>
<AssemblyName>PayBridge.SDK.Example</AssemblyName>
<UserSecretsId>PayBridge.SDK.Example</UserSecretsId>
Comment thread README.nuget.md
Comment on lines +88 to 92
For local development, prefer .NET user-secrets; for deployments, use environment
variables or a managed secret store.

```json
{
@teesofttech
teesofttech merged commit 9d5331c into master Jul 17, 2026
5 of 6 checks passed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
README.nuget.md (1)

94-110: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Align configuration placeholders with the new standard.

The example configuration block still uses a concrete connection string, an integer array for EnabledGateways, and test keys (like sk_test_xxxx). To maintain consistency with the updated appsettings.json templates and to ensure the SDK's auto-ignore logic works reliably (which expects the YOUR_ prefix), consider updating these values to the new placeholder format.

♻️ Proposed update
   "ConnectionStrings": {
-    "PayBridgeDbContext": "Server=localhost;Database=PayBridgeDB;Trusted_Connection=True;TrustServerCertificate=true;"
+    "PayBridgeDbContext": "YOUR_PAYBRIDGE_CONNECTION_STRING"
   },
   "PaymentGatewayConfig": {
-    "EnabledGateways": [ 1, 2, 3 ],
+    "EnabledGateways": [],
     "FlutterwaveConfig": {
-      "PublicKey": "FLWPUBK-xxxx",
-      "SecretKey": "FLWSECK-xxxx",
-      "EncryptionKey": "xxxx"
+      "PublicKey": "YOUR_FLUTTERWAVE_PUBLIC_KEY",
+      "SecretKey": "YOUR_FLUTTERWAVE_SECRET_KEY",
+      "EncryptionKey": "YOUR_FLUTTERWAVE_ENCRYPTION_KEY"
     },
     "Paystack": {
-      "PublicKey": "pk_test_xxxx",
-      "SecretKey": "sk_test_xxxx"
+      "PublicKey": "YOUR_PAYSTACK_PUBLIC_KEY",
+      "SecretKey": "YOUR_PAYSTACK_SECRET_KEY"
     },
     "Stripe": {
-      "SecretKey": "sk_test_xxxx"
+      "SecretKey": "YOUR_STRIPE_SECRET_KEY"
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.nuget.md` around lines 94 - 110, Update the README configuration
example to match the current appsettings.json placeholder conventions: replace
the concrete PayBridgeDbContext connection string, integer EnabledGateways
values, and test gateway keys with the standardized YOUR_ placeholders expected
by the SDK auto-ignore logic. Keep the existing configuration structure and
gateway entries unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/secret-scanning.yml:
- Around line 24-25: Update the actions/checkout step in the secret-scanning
workflow to explicitly disable credential persistence with the supported
checkout configuration, while preserving the existing repository checkout
behavior.

In `@PayBridge.SDK.Test/Unit/RepositorySecurityTests.cs`:
- Around line 30-34: Update the file-filtering flow in the repository security
test to compute each file’s path relative to repositoryRoot before passing it to
IsGeneratedPath. Keep FindCredentialViolations using the original file path, and
ensure generated-directory detection only examines repository-relative segments.

---

Outside diff comments:
In `@README.nuget.md`:
- Around line 94-110: Update the README configuration example to match the
current appsettings.json placeholder conventions: replace the concrete
PayBridgeDbContext connection string, integer EnabledGateways values, and test
gateway keys with the standardized YOUR_ placeholders expected by the SDK
auto-ignore logic. Keep the existing configuration structure and gateway entries
unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 216b5636-c133-4f93-8f9e-6cb780bf15d8

📥 Commits

Reviewing files that changed from the base of the PR and between 36b4aa2 and 87711cc.

📒 Files selected for processing (11)
  • .github/workflows/secret-scanning.yml
  • PayBridge.SDK.Example/PayBridge.SDK.Example.csproj
  • PayBridge.SDK.Example/Program.cs
  • PayBridge.SDK.Example/README.md
  • PayBridge.SDK.Example/appsettings.Development.json
  • PayBridge.SDK.Example/appsettings.json
  • PayBridge.SDK.Presentation/Program.cs
  • PayBridge.SDK.Presentation/appsettings.json
  • PayBridge.SDK.Test/Unit/RepositorySecurityTests.cs
  • README.md
  • README.nuget.md

Comment on lines +24 to +25
- name: Checkout repository
uses: actions/checkout@v4

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Prevent credential persistence in the checkout step.

As flagged by static analysis, configuring persist-credentials: false prevents the GITHUB_TOKEN from being persisted in the local Git config, mitigating the risk of credential exposure if subsequent steps are compromised or if the .git directory is archived. Since this workflow only performs scanning and does not push changes, it does not need the token to persist.

🛡️ Proposed fix to explicitly disable credential persistence
       - name: Checkout repository
         uses: actions/checkout@v4
+        with:
+          persist-credentials: false
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Checkout repository
uses: actions/checkout@v4
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false
🧰 Tools
🪛 zizmor (1.26.1)

[warning] 24-25: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/secret-scanning.yml around lines 24 - 25, Update the
actions/checkout step in the secret-scanning workflow to explicitly disable
credential persistence with the supported checkout configuration, while
preserving the existing repository checkout behavior.

Source: Linters/SAST tools

Comment on lines +30 to +34
var violations = Directory
.EnumerateFiles(repositoryRoot, "appsettings*.json", SearchOption.AllDirectories)
.Where(path => !IsGeneratedPath(path))
.SelectMany(path => FindCredentialViolations(repositoryRoot, path))
.ToList();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Prevent false-positive path filtering due to repository location.

Passing the absolute file path to IsGeneratedPath means that if the repository itself is cloned into a directory structure containing a folder named bin or obj (for example, /home/user/bin/PayBridge.SDK/), IsGeneratedPath will inadvertently return true for all files. This effectively skips the entire credential scan test.

Evaluate the path relative to the repository root before checking for generated directories.

🐛 Proposed fix to evaluate the relative path
         var violations = Directory
             .EnumerateFiles(repositoryRoot, "appsettings*.json", SearchOption.AllDirectories)
-            .Where(path => !IsGeneratedPath(path))
+            .Where(path => !IsGeneratedPath(Path.GetRelativePath(repositoryRoot, path)))
             .SelectMany(path => FindCredentialViolations(repositoryRoot, path))
             .ToList();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
var violations = Directory
.EnumerateFiles(repositoryRoot, "appsettings*.json", SearchOption.AllDirectories)
.Where(path => !IsGeneratedPath(path))
.SelectMany(path => FindCredentialViolations(repositoryRoot, path))
.ToList();
var violations = Directory
.EnumerateFiles(repositoryRoot, "appsettings*.json", SearchOption.AllDirectories)
.Where(path => !IsGeneratedPath(Path.GetRelativePath(repositoryRoot, path)))
.SelectMany(path => FindCredentialViolations(repositoryRoot, path))
.ToList();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@PayBridge.SDK.Test/Unit/RepositorySecurityTests.cs` around lines 30 - 34,
Update the file-filtering flow in the repository security test to compute each
file’s path relative to repositoryRoot before passing it to IsGeneratedPath.
Keep FindCredentialViolations using the original file path, and ensure
generated-directory detection only examines repository-relative segments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: security Credentials, webhooks, dependency, and application security priority: P0 Release blocker or urgent security/correctness risk

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants