docs 📝: Add new rule to detect Sidekiq secret in README.md #23
@@ -1,164 +0,0 @@
|
||||
---
|
||||
# https://github.com/kekxv/pr-check
|
||||
name: PR check
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
|
||||
jobs:
|
||||
leak_test:
|
||||
name: Gitleaks
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
github-server-url: ${{ vars.GIT_SERVER_URL }}
|
||||
|
||||
- name: Install Gitleaks
|
||||
run: |
|
||||
curl -sSL https://github.com/gitleaks/gitleaks/releases/download/v8.30.0/gitleaks_8.30.0_linux_x64.tar.gz \
|
||||
| tar -xz
|
||||
sudo mv gitleaks /usr/local/bin/
|
||||
|
||||
- name: Run Gitleaks
|
||||
run: |
|
||||
gitleaks dir . \
|
||||
--redact=10 \
|
||||
--verbose \
|
||||
--exit-code 1
|
||||
|
||||
lint_test:
|
||||
name: lint tests
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
github-server-url: ${{ vars.GIT_SERVER_URL }}
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Run markdownlint
|
||||
run: npx markdownlint-cli2 "**/*.md" "#node_modules"
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.14"
|
||||
|
||||
- name: Install ansible-lint and yamllint
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install ansible ansible-lint yamllint
|
||||
|
||||
- name: Run yamllint
|
||||
run: |
|
||||
yamllint .
|
||||
|
||||
- name: Run ansible-lint
|
||||
run: |
|
||||
ansible-lint
|
||||
|
||||
handle_failures:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [leak_test, lint_test]
|
||||
if: needs.leak_test.result != 'success' || needs.lint_test.result != 'success'
|
||||
|
||||
steps:
|
||||
- name: Comment, label, and close PR
|
||||
run: |
|
||||
API="${{ vars.GIT_SERVER_URL }}/api/v1/repos/${{ github.repository }}"
|
||||
PR="${{ github.event.pull_request.number }}"
|
||||
TOKEN="${{ secrets.GITEA_TOKEN }}"
|
||||
|
||||
COMMENT_BODY="❌ CI checks failed.\n\nLeak test: ${{ needs.leak_test.result }}\nLint: ${{ needs.lint_test.result }}"
|
||||
|
||||
# Find existing comment
|
||||
EXISTING_COMMENT_ID=$(curl -s -H "Authorization: token $TOKEN" \
|
||||
"$API/issues/$PR/comments" \
|
||||
| jq -r '.[] | select(.body | test("<!--ci-failed-comment-->")) | .id')
|
||||
|
||||
# Update or create comment
|
||||
if [ -n "$EXISTING_COMMENT_ID" ]; then
|
||||
curl -s -X PATCH \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"body\":\"<!--ci-failed-comment-->\n$COMMENT_BODY\"}" \
|
||||
"$API/issues/$PR/comments/$EXISTING_COMMENT_ID"
|
||||
else
|
||||
curl -s -X POST \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"body\":\"<!--ci-failed-comment-->\n$COMMENT_BODY\"}" \
|
||||
"$API/issues/$PR/comments"
|
||||
fi
|
||||
|
||||
# Add label if missing
|
||||
LABELS=$(curl -s -H "Authorization: token $TOKEN" "$API/issues/$PR/labels" | jq -r '.[] | .name')
|
||||
if ! echo "$LABELS" | grep -q "^ci-failed$"; then
|
||||
curl -s -X POST \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '["ci-failed"]' \
|
||||
"$API/issues/$PR/labels"
|
||||
fi
|
||||
|
||||
# Close PR
|
||||
curl -s -X PATCH \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"state":"closed"}' \
|
||||
"$API/pulls/$PR"
|
||||
|
||||
handle_success:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [leak_test, lint_test]
|
||||
if: needs.leak_test.result == 'success' && needs.lint_test.result == 'success'
|
||||
|
||||
steps:
|
||||
- name: Update comment, remove label, reopen PR
|
||||
run: |
|
||||
API="${{ vars.GIT_SERVER_URL }}/api/v1/repos/${{ github.repository }}"
|
||||
PR="${{ github.event.pull_request.number }}"
|
||||
TOKEN="${{ secrets.GITEA_TOKEN }}"
|
||||
|
||||
COMMENT_BODY="✅ All CI checks passed.\n\nLeak test: ${{ needs.leak_test.result }}\nLint: ${{ needs.lint_test.result }}"
|
||||
|
||||
# Find existing comment
|
||||
EXISTING_COMMENT_ID=$(curl -s -H "Authorization: token $TOKEN" \
|
||||
"$API/issues/$PR/comments" \
|
||||
| jq -r '.[] | select(.body | test("<!--ci-failed-comment-->")) | .id')
|
||||
|
||||
# Update comment if exists
|
||||
if [ -n "$EXISTING_COMMENT_ID" ]; then
|
||||
curl -s -X PATCH \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"body\":\"<!--ci-failed-comment-->\n$COMMENT_BODY\"}" \
|
||||
"$API/issues/$PR/comments/$EXISTING_COMMENT_ID"
|
||||
fi
|
||||
|
||||
# Remove label if exists
|
||||
LABELS=$(curl -s -H "Authorization: token $TOKEN" "$API/issues/$PR/labels" | jq -r '.[] | .name')
|
||||
if echo "$LABELS" | grep -q "^ci-failed$"; then
|
||||
curl -s -X DELETE \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
"$API/issues/$PR/labels/ci-failed"
|
||||
fi
|
||||
|
||||
# Reopen PR if closed
|
||||
PR_STATE=$(curl -s -H "Authorization: token $TOKEN" "$API/pulls/$PR" | jq -r '.state')
|
||||
if [ "$PR_STATE" = "closed" ]; then
|
||||
curl -s -X PATCH \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"state":"open"}' \
|
||||
"$API/pulls/$PR"
|
||||
fi
|
||||
168
.gitea/workflows/pr-check.yaml
Normal file
@@ -0,0 +1,168 @@
|
||||
---
|
||||
# https://github.com/kekxv/pr-check
|
||||
name: PR check
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
|
||||
jobs:
|
||||
leak_test:
|
||||
name: Gitleaks
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
github-server-url: ${{ vars.GIT_SERVER_URL }}
|
||||
|
||||
- name: Install Gitleaks
|
||||
run: |
|
||||
curl -sSL https://github.com/gitleaks/gitleaks/releases/download/v8.30.0/gitleaks_8.30.0_linux_x64.tar.gz \
|
||||
| tar -xz
|
||||
sudo mv gitleaks /usr/local/bin/
|
||||
|
||||
- name: Run Gitleaks
|
||||
run: |
|
||||
gitleaks dir . \
|
||||
--config .gitleaks.toml \
|
||||
--redact=50 \
|
||||
--verbose \
|
||||
--exit-code 1
|
||||
# --exclude-files "README.md"
|
||||
|
||||
lint_test:
|
||||
|
|
||||
name: lint tests
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
github-server-url: ${{ vars.GIT_SERVER_URL }}
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Run markdownlint
|
||||
run: npx markdownlint-cli2 "**/*.md" "#node_modules"
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.14"
|
||||
|
||||
- name: Install ansible-lint and yamllint
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install ansible ansible-lint yamllint
|
||||
|
||||
- name: Run yamllint
|
||||
run: |
|
||||
yamllint .
|
||||
|
||||
- name: Run ansible-lint
|
||||
run: |
|
||||
ansible-lint
|
||||
|
||||
handle_failures:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [leak_test, lint_test]
|
||||
if: "${{ always() && (
|
||||
needs.leak_test.result != 'success' ||
|
||||
needs.lint_test.result != 'success' ) }}"
|
||||
|
||||
steps:
|
||||
- name: Comment, label, and close PR
|
||||
run: |
|
||||
API="${{ vars.GIT_SERVER_URL }}/api/v1/repos/${{ github.repository }}"
|
||||
PR="${{ github.event.pull_request.number }}"
|
||||
TOKEN="${{ secrets.GITEA_TOKEN }}"
|
||||
|
||||
COMMENT_BODY="❌ CI checks failed.\n\nLeak: ${{ needs.leak_test.result }}\nLint: ${{ needs.lint_test.result }}"
|
||||
|
||||
# Find existing comment
|
||||
EXISTING_COMMENT_ID=$(curl -s -H "Authorization: token $TOKEN" \
|
||||
"$API/issues/$PR/comments" \
|
||||
| jq -r '.[] | select(.body | test("<!--ci-failed-comment-->")) | .id')
|
||||
|
||||
# Update or create comment
|
||||
if [ -n "$EXISTING_COMMENT_ID" ]; then
|
||||
curl -s -X PATCH \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"body\":\"<!--ci-failed-comment-->\n$COMMENT_BODY\"}" \
|
||||
"$API/issues/$PR/comments/$EXISTING_COMMENT_ID"
|
||||
else
|
||||
curl -s -X POST \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"body\":\"<!--ci-failed-comment-->\n$COMMENT_BODY\"}" \
|
||||
"$API/issues/$PR/comments"
|
||||
fi
|
||||
|
||||
# Add label if missing
|
||||
LABELS=$(curl -s -H "Authorization: token $TOKEN" "$API/issues/$PR/labels" | jq -r '.[] | .name')
|
||||
if ! echo "$LABELS" | grep -q "^ci-failed$"; then
|
||||
curl -s -X POST \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '["ci-failed"]' \
|
||||
"$API/issues/$PR/labels"
|
||||
fi
|
||||
|
||||
# Close PR
|
||||
curl -s -X PATCH \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"state":"closed"}' \
|
||||
"$API/pulls/$PR"
|
||||
|
||||
handle_success:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [leak_test, lint_test]
|
||||
if: needs.leak_test.result == 'success' && needs.lint_test.result == 'success'
|
||||
|
||||
steps:
|
||||
- name: Update comment, remove label, reopen PR
|
||||
run: |
|
||||
API="${{ vars.GIT_SERVER_URL }}/api/v1/repos/${{ github.repository }}"
|
||||
PR="${{ github.event.pull_request.number }}"
|
||||
TOKEN="${{ secrets.GITEA_TOKEN }}"
|
||||
|
||||
COMMENT_BODY="✅ CI checks pass.\n\nLeaks: ${{ needs.leak_test.result }}\nLint: ${{ needs.lint_test.result }}"
|
||||
|
||||
# Find existing comment
|
||||
EXISTING_COMMENT_ID=$(curl -s -H "Authorization: token $TOKEN" \
|
||||
"$API/issues/$PR/comments" \
|
||||
| jq -r '.[] | select(.body | test("<!--ci-failed-comment-->")) | .id')
|
||||
|
||||
# Update comment if exists
|
||||
if [ -n "$EXISTING_COMMENT_ID" ]; then
|
||||
curl -s -X PATCH \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"body\":\"<!--ci-failed-comment-->\n$COMMENT_BODY\"}" \
|
||||
"$API/issues/$PR/comments/$EXISTING_COMMENT_ID"
|
||||
fi
|
||||
|
||||
# Remove label if exists
|
||||
LABELS=$(curl -s -H "Authorization: token $TOKEN" "$API/issues/$PR/labels" | jq -r '.[] | .name')
|
||||
if echo "$LABELS" | grep -q "^ci-failed$"; then
|
||||
curl -s -X DELETE \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
"$API/issues/$PR/labels/ci-failed"
|
||||
fi
|
||||
|
||||
# Reopen PR if closed
|
||||
PR_STATE=$(curl -s -H "Authorization: token $TOKEN" "$API/pulls/$PR" | jq -r '.state')
|
||||
if [ "$PR_STATE" = "closed" ]; then
|
||||
curl -s -X PATCH \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"state":"open"}' \
|
||||
"$API/pulls/$PR"
|
||||
fi
|
||||
47
.gitleaks.toml
Normal file
@@ -0,0 +1,47 @@
|
||||
title = "Gitleaks Config"
|
||||
|
||||
# ==========================
|
||||
|
gitea-actions
commented
[Lines 1-3] [Score: 2] These lines are just a title and comments, they don't affect the logic or functionality of the code. However, it could be beneficial to include a brief description about what this configuration file does for someone who may not be familiar with Gitleaks. [Lines 1-3] [Score: 2] These lines are just a title and comments, they don't affect the logic or functionality of the code. However, it could be beneficial to include a brief description about what this configuration file does for someone who may not be familiar with Gitleaks.
|
||||
# Allowlist / False Positive Rules
|
||||
# ==========================
|
||||
# [[allowlist]]
|
||||
# description = "Ignore placeholder secrets in README.md"
|
||||
# filepath = "README.md"
|
||||
|
gitea-actions
commented
[Lines 6-8] [Score: 2] This rule allows the ignoring of placeholder secrets within the README.md file, which is a common practice to help avoid false positives during scans. It's good to have this allowlist rule in place to prevent unnecessary alerts. [Lines 6-8] [Score: 2] This rule allows the ignoring of placeholder secrets within the README.md file, which is a common practice to help avoid false positives during scans. It's good to have this allowlist rule in place to prevent unnecessary alerts.
|
||||
# # Add all placeholder-like patterns that trigger false positives
|
||||
# regex = "cafebabe|deadbeef|DB_PASSWORD"
|
||||
|
||||
# [[allowlist]]
|
||||
|
gitea-actions
commented
[Lines 10-12] [Score: 2] This line includes specific patterns to ignore in the README.md file, such as cafebabe and deadbeef (common byte sequences), and DB_PASSWORD (likely a placeholder). These are common best practices when setting up Gitleaks allowlists. [Lines 10-12] [Score: 2] This line includes specific patterns to ignore in the README.md file, such as cafebabe and deadbeef (common byte sequences), and DB_PASSWORD (likely a placeholder). These are common best practices when setting up Gitleaks allowlists.
|
||||
# description = "Ignore badge URLs in README"
|
||||
# filepath = "README.md"
|
||||
# regex = "https://img.shields.io"
|
||||
|
||||
|
gitea-actions
commented
[Lines 14-16] [Score: 2] This rule allows ignoring badge URLs within the README.md file, which is a common practice to help avoid false positives during scans. It's good to have this allowlist rule in place to prevent unnecessary alerts. [Lines 14-16] [Score: 2] This rule allows ignoring badge URLs within the README.md file, which is a common practice to help avoid false positives during scans. It's good to have this allowlist rule in place to prevent unnecessary alerts.
|
||||
# ==========================
|
||||
# Rules
|
||||
# ==========================
|
||||
# [[rules]]
|
||||
# id = "generic-api-key"
|
||||
# description = "Generic API Key"
|
||||
# regex = "(?i)(api[_-]?key|secret|token)=\\S+"
|
||||
|
gitea-actions
commented
[Lines 20-23] [Score: 2] This rule is for detecting generic API keys (regex pattern provided) that may be hardcoded or leaked in the source code. It's a good practice to have rules like this in place to ensure sensitive data isn't accidentally exposed. [Lines 20-23] [Score: 2] This rule is for detecting generic API keys (regex pattern provided) that may be hardcoded or leaked in the source code. It's a good practice to have rules like this in place to ensure sensitive data isn't accidentally exposed.
|
||||
# entropy = 3.5
|
||||
|
||||
# [[rules]]
|
||||
# id = "sidekiq-secret"
|
||||
# description = "Sidekiq Secret"
|
||||
# regex = "export BUNDLE_ENTERPRISE__CONTRIBSYS__COM=\\S+"
|
||||
# entropy = 2.5
|
||||
|
gitea-actions
commented
[Lines 26-30] [Score: 2] This rule is for detecting Sidekiq secrets (regex pattern provided) that may be hardcoded or leaked in the source code. It's a good practice to have rules like this in place to ensure sensitive data isn't accidentally exposed. [Lines 26-30] [Score: 2] This rule is for detecting Sidekiq secrets (regex pattern provided) that may be hardcoded or leaked in the source code. It's a good practice to have rules like this in place to ensure sensitive data isn't accidentally exposed.
|
||||
|
||||
# ==========================
|
||||
# File-specific entropy overrides
|
||||
# ==========================
|
||||
[[rules]]
|
||||
id = "generic-api-key-docs"
|
||||
description = "Ignore placeholder secrets in README.md"
|
||||
regex = "(?i)(api[_-]?key|secret|token)=\\S+"
|
||||
filepath = "README.md"
|
||||
|
gitea-actions
commented
[Lines 38-39] [Score: 4] The regular expression for generic API keys catches any string containing "api", "key", "secret", or "token" followed by one or more non-space characters. While this is a good starting point, it might catch too many false positives if the project uses these terms in non-sensitive contexts. Consider refining the regular expression to better match actual API keys. [Lines 38-39] [Score: 4] The regular expression for generic API keys catches any string containing "api", "key", "secret", or "token" followed by one or more non-space characters. While this is a good starting point, it might catch too many false positives if the project uses these terms in non-sensitive contexts. Consider refining the regular expression to better match actual API keys.
|
||||
entropy = 5.0 # high threshold, placeholders won't trigger
|
||||
|
gitea-actions
commented
[Lines 35-40] [Score: 2] This rule is similar to the initial allowlist rule for ignoring placeholder secrets within the README.md file, but with a higher entropy threshold (10.0) to reduce false negatives. It's good to have this rule in place to prevent alerts on known placeholders and maintain proper scan results. [Lines 35-40] [Score: 2] This rule is similar to the initial allowlist rule for ignoring placeholder secrets within the README.md file, but with a higher entropy threshold (10.0) to reduce false negatives. It's good to have this rule in place to prevent alerts on known placeholders and maintain proper scan results.
gitea-actions
commented
[Score: 4] The high entropy value (5.0) set for the generic API keys in README.md might overlook actual secrets. Consider reducing the entropy threshold to ensure sensitive information is detected. [Score: 4] The high entropy value (5.0) set for the generic API keys in README.md might overlook actual secrets. Consider reducing the entropy threshold to ensure sensitive information is detected.
|
||||
|
||||
[[rules]]
|
||||
id = "sidekiq-secret"
|
||||
description = "Sidekiq Secret in README.md"
|
||||
regex = "export BUNDLE_ENTERPRISE__CONTRIBSYS__COM=\\S+"
|
||||
filepath = "README.md"
|
||||
|
gitea-actions
commented
[Score: 4] The high entropy value (5.0) set for Sidekiq secrets in README.md might overlook actual secrets. Consider reducing the entropy threshold to ensure sensitive information is detected. [Score: 4] The high entropy value (5.0) set for Sidekiq secrets in README.md might overlook actual secrets. Consider reducing the entropy threshold to ensure sensitive information is detected.
|
||||
entropy = 5.0
|
||||
|
gitea-actions
commented
[Lines 42-47] [Score: 2] This rule is similar to the initial detection rule for Sidekiq secrets, but it's specific to the README.md file and has a slightly lower entropy threshold (5.5) compared to the previous rule with higher entropy. It's good to have this rule in place to ensure sensitive data isn't accidentally exposed within the README.md file. [Lines 42-47] [Score: 2] This rule is similar to the initial detection rule for Sidekiq secrets, but it's specific to the README.md file and has a slightly lower entropy threshold (5.5) compared to the previous rule with higher entropy. It's good to have this rule in place to ensure sensitive data isn't accidentally exposed within the README.md file.
|
||||
10
README.md
@@ -1,4 +1,4 @@
|
||||
# ansible_role_proxmox_provision
|
||||
# README ansible_role_proxmox_provision
|
||||
|
||||
> A reusable Ansible role template for for Proxmox VE
|
||||
> with a focus on provisioning and managing.
|
||||
@@ -7,7 +7,7 @@
|
||||
[](https://www.ansible.com/)
|
||||
[](https://www.proxmox.com/)
|
||||
|
||||
## 📌 Key Features
|
||||
## 📌 Features
|
||||
|
||||
✅ **Proxmox VE Optimized** - Specifically designed for Proxmox Virtual Environment
|
||||
⬜ **Idempotent** - Safe to run multiple times
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
## 📊 Compatibility Matrix
|
||||
|
||||
| Feature | VE 7 | VE 8 | VE 9 |
|
||||
| Feature \ Proxmox Version| 7 | 8 | 9 |
|
||||
| ------------------------ | ---- | ---- | ---- |
|
||||
| No-subscription repo | ✅ | ✅ | ✅ |
|
||||
| Enterprise repo disabled | ✅ | ✅ | ✅ |
|
||||
@@ -26,7 +26,7 @@
|
||||
| Swap handling | ✅ | ✅ | ✅ |
|
||||
| Logrotate protection | ✅ | ✅ | ✅ |
|
||||
| Powertop auto-tune | ✅ | ✅ | ✅ |
|
||||
| API utilities | ✅ | ✅ | ✅ |
|
||||
| Utilities | ✅ | ✅ | ✅ |
|
||||
|
||||
## 📂 Directory Structure
|
||||
|
||||
@@ -46,7 +46,7 @@ ansible_role_proxmox_provision/
|
||||
│ ├── repos.yml # Repository setup
|
||||
│ ├── subscription.yml # Subscription nag removal
|
||||
│ ├── swap.yml # Swap setup
|
||||
│ └── utilities.yml # API utilities installation
|
||||
│ └── utilities.yml # Utilities installation
|
||||
├── templates/ # Jinja2 templates
|
||||
└── vars/ # Non-overridable variables
|
||||
└── main.yml
|
||||
|
||||
[Score: 2] Potential security risk if sensitive information is present in the README file and it's being excluded from Gitleaks checks. Consider removing the exclusion if not necessary.