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
39 changes: 39 additions & 0 deletions .github/workflows/portfolio-integrity.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Portfolio Integrity

on:
pull_request:
push:
branches: [main, master]
Comment on lines +3 to +6

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 | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow file =="
git ls-files .github/workflows/portfolio-integrity.yml
echo

echo "== numbered contents =="
cat -n .github/workflows/portfolio-integrity.yml
echo

echo "== nearby workflow files =="
git ls-files .github/workflows

Repository: NilhanHub/quietcut

Length of output: 1641


🌐 Web query:

GitHub Actions pull_request workflow uses workflow file from base branch or head branch documentation

💡 Result:

In GitHub Actions, the workflow file used for pull_request and pull_request_target events depends on the specific event type [1]: 1. pull_request: This event runs the workflow file as it exists in the pull request's merge commit [1]. Consequently, if you modify a workflow file in your feature branch (the head branch), the version of the workflow in that branch is the one that will execute [1]. 2. pull_request_target: As of November 2025, this event always uses the workflow file from the repository's default branch [2]. This change was implemented to ensure that security-sensitive workflows are not bypassed by outdated or vulnerable workflow definitions that might exist on non-default branches [2]. In summary, pull_request uses the workflow definition from the PR's merge commit (effectively the head branch) [1], while pull_request_target strictly uses the definition from the repository's default branch [2].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the workflow file and any references to gitleaks/checkout behavior.
python3 - <<'PY'
from pathlib import Path
p = Path('.github/workflows/portfolio-integrity.yml')
print(p.read_text())
PY

Repository: NilhanHub/quietcut

Length of output: 1211


🌐 Web query:

site:docs.github.com Actions pull_request workflow file head branch base branch pull_request_target workflow file used

💡 Result:

The primary difference between the pull_request and pull_request_target events in GitHub Actions lies in the context in which the workflow runs and the security implications involved [1]. 1. Context and Execution: The pull_request event runs in the context of the merge commit between the base and head branches [1]. This ensures that the workflow tests the exact code that would be merged into the target branch [1]. In contrast, the pull_request_target event runs in the context of the base branch (the target branch) [1]. It does not checkout the pull request's head branch by default, and it executes using the workflow file defined in the base branch [1]. 2. Security: The pull_request_target event is specifically designed to allow workflows to interact safely with pull requests from forks [1]. Because it runs against the base repository's workflow file, it prevents the execution of arbitrary or malicious code that might be present in a user's head branch (e.g., a modified workflow file in a fork) [1]. 3. Workflow File Usage: - For pull_request: The workflow file is taken from the pull request's head branch. - For pull_request_target: The workflow file is taken from the base branch (the branch the pull request is targeting). Because of this, pull_request_target is ideal for tasks like labeling pull requests or posting comments, but it should be used with extreme caution if you intend to check out the head branch to build or run code, as doing so can negate the security protections of the event [1]. If you need to access the code from the head branch in a pull_request_target workflow, you must explicitly use actions like actions/checkout with the ref parameter set to the pull request head to retrieve that code, while remaining aware that the checked-out code is untrusted [1].

Citations:


Keep this check on a default-branch-controlled workflow.
A PR can change this workflow file and keep the required check green while skipping the gate. Run it from a trusted base-branch workflow or required workflow/ruleset instead.

🤖 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/portfolio-integrity.yml around lines 3 - 6, Move the
portfolio integrity check out of the pull-request-triggered workflow and into a
workflow controlled by the trusted default branch, or enforce it through the
repository’s required workflow/ruleset configuration. Ensure pull requests
cannot modify the workflow and bypass the required integrity gate, while
preserving execution for changes targeting the default branch.


permissions:
contents: read
pull-requests: read
Comment on lines +8 to +10

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 | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## Workflow file\n'
sed -n '1,220p' .github/workflows/portfolio-integrity.yml

printf '\n## Search repo for gitleaks settings\n'
rg -n "GITLEAKS_ENABLE_COMMENTS|gitleaks" .github/workflows . || true

Repository: NilhanHub/quietcut

Length of output: 1353


🌐 Web query:

gitleaks-action GITLEAKS_ENABLE_COMMENTS default pull requests write permissions comments by default

💡 Result:

The Gitleaks-Action configuration option GITLEAKS_ENABLE_COMMENTS is enabled by default (set to true), meaning the action will attempt to post comments on pull requests whenever it detects secrets [1][2][3]. Although the feature is enabled by default, it will not successfully post comments unless the GitHub Actions job is granted the appropriate permissions [4][5]. Because GitHub Actions workflows require explicit permissions to interact with pull requests, you must configure the job with pull-requests: write permission in your workflow YAML file for the commenting feature to function [4][5]. If this permission is missing or restricted, the action may encounter 403 errors when attempting to comment [5]. To ensure the action can post comments, include the following in your workflow job definition [4]: jobs: gitleaks: runs-on: ubuntu-latest permissions: contents: read pull-requests: write steps: - uses: actions/checkout@v4 - uses: gitleaks/gitleaks-action@v2 with: GITLEAKS_ENABLE_COMMENTS: true # Default behavior If you do not want the action to comment on your pull requests, you must explicitly set GITLEAKS_ENABLE_COMMENTS: false in your configuration [1][6].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the workflow context around the gitleaks step only.
nl -ba .github/workflows/portfolio-integrity.yml | sed -n '1,220p' | sed -n '/gitleaks/,+40p'

# Search for any existing comment toggle or token permissions in workflows.
rg -n "GITLEAKS_ENABLE_COMMENTS|pull-requests:\s*write|issues:\s*write|gitleaks" .github/workflows

Repository: NilhanHub/quietcut

Length of output: 196


🌐 Web query:

site:github.com gitleaks-action GITLEAKS_ENABLE_COMMENTS pull-requests: write read-only permissions

💡 Result:

When using gitleaks-action with GITLEAKS_ENABLE_COMMENTS set to true (which is the default), the action requires write permissions for pull requests to successfully post comments on the PR [1][2][3]. If your workflow encounters a "Resource not accessible by integration" error, you must explicitly grant the necessary permissions in your GitHub Actions workflow file [4][5]. The following permissions configuration is typically required [4]: permissions: contents: read pull-requests: write While some users have reported that only read permissions for pull-requests were necessary in specific configurations [5], write permissions are the standard requirement for the GITHUB_TOKEN to interact with the GitHub API to create review comments on pull requests [5][2]. If you are using the security-events feature to upload SARIF results, you may also need to include security-events: write [4].

Citations:


Disable Gitleaks PR comments or grant write access. Gitleaks comments on PR findings by default, but this workflow only grants pull-requests: read, so comment creation will fail. Set GITLEAKS_ENABLE_COMMENTS: 'false' to keep the scan read-only, or switch to pull-requests: write if PR comments are intended.

🤖 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/portfolio-integrity.yml around lines 8 - 10, Update the
portfolio-integrity workflow to prevent Gitleaks from attempting PR comments
while retaining read-only permissions: set the Gitleaks configuration key
GITLEAKS_ENABLE_COMMENTS to 'false' in the workflow environment or relevant scan
step, and keep pull-requests permission at read.


jobs:
documentation-and-secrets:
runs-on: ubuntu-latest
steps:
- name: Checkout full history
uses: actions/checkout@v4
with:
fetch-depth: 0
Comment on lines +16 to +19

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

git ls-files .github/workflows/portfolio-integrity.yml
echo '---'
cat -n .github/workflows/portfolio-integrity.yml

Repository: NilhanHub/quietcut

Length of output: 1529


🌐 Web query:

actions/checkout v4 persist-credentials default local Git config later steps third-party actions documentation

💡 Result:

In actions/checkout v4, the persist-credentials input defaults to true [1][2]. When enabled, this setting configures the local Git authentication (using the GITHUB_TOKEN or a provided SSH key) within the local Git configuration [1][3][4]. This allows subsequent steps in your workflow to execute authenticated Git commands (such as git push or fetching private submodules) without needing to manually re-authenticate [1][3][4]. The token is managed as follows: - Mechanism: It is persisted in the local Git configuration (typically via an http.https://github.com/.extraheader basic-auth value in.git/config) [4]. - Cleanup: The credential is removed automatically during the post-job cleanup phase of the action [1][3]. - Security Note: Because the credential exists in the Git configuration during the job's execution, if a later step in your workflow uploads the repository directory (including the.git/ folder) as an artifact, the credential may be included in that artifact [4]. - Opt-out: You can disable this behavior by setting persist-credentials: false [1][3]. This is recommended if your workflow does not perform any authenticated Git operations after the checkout step, as it reduces the potential security surface area [4].

Citations:


Disable persisted checkout credentials. actions/checkout stores the token in local Git config by default, and this job doesn’t need authenticated Git operations after checkout. Set persist-credentials: false to reduce exposure to later steps and third-party actions.

🧰 Tools
🪛 zizmor (1.26.1)

[warning] 16-19: 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/portfolio-integrity.yml around lines 16 - 19, Add
persist-credentials: false to the with configuration of the “Checkout full
history” actions/checkout@v4 step, while preserving fetch-depth: 0 and the
existing checkout behavior.

Source: Linters/SAST tools

- name: Verify portfolio documentation
shell: bash
run: |
test -s README.md
test -s SECURITY.md
test -s CONTRIBUTING.md
test -s RIGHTS.md
test -s docs/social-preview.png
python - <<'PY'
import struct
from pathlib import Path
image = Path('docs/social-preview.png').read_bytes()
assert image[:8] == b'\x89PNG\r\n\x1a\n'
width, height = struct.unpack('>II', image[16:24])
assert (width, height) == (1280, 640), (width, height)
PY
- name: Scan changed history for secrets
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Comment on lines +36 to +39

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

gitleaks/gitleaks-action v2 node 20 insecure opt-out June 2 2026 September 16 2026 v3 node 24

💡 Result:

The gitleaks-action has transitioned to v3 to support the Node 24 runtime [1][2]. This update was necessitated by GitHub's deprecation of the Node 20 runtime for GitHub Actions [1][3]. The deprecation timeline and requirements are as follows: - June 2, 2026: GitHub changed the default runner to Node 24 [1][2]. Workflows continuing to use gitleaks-action@v2 (which runs on Node 20) require the environment variable ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true to execute [1][4]. Without this opt-out, these workflows will fail [1][2]. - September 16, 2026: Node 20 will be removed from GitHub-hosted runners entirely [1][2]. At this point, gitleaks-action@v2 will cease to function regardless of whether the opt-out flag is set [1][3]. Users are advised to migrate to gitleaks-action@v3, which utilizes Node 24 and requires GitHub Actions runner version 2.327.1 or later [1][2]. No changes to inputs, outputs, or behavior are required for this migration, other than updating the workflow file reference from @v2 to @v3 [1][2].

Citations:


Upgrade Gitleaks to v3. gitleaks/gitleaks-action@v2 runs on Node 20 and will require the insecure opt-out after June 2, 2026; it stops working on GitHub-hosted runners after September 16, 2026. Switch this workflow to @v3.

🤖 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/portfolio-integrity.yml around lines 36 - 39, Update the
“Scan changed history for secrets” workflow step to use
gitleaks/gitleaks-action@v3 instead of `@v2`, preserving its existing GITHUB_TOKEN
configuration.

11 changes: 11 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Contributing

Contributions that improve correctness, tests, documentation, accessibility, or operational clarity are welcome.

1. Open an issue describing the problem and intended outcome.
2. Keep changes focused and preserve the repository's documented architecture and safety boundaries.
3. Add or update tests for behavior changes.
4. Run the verification commands documented in the README.
5. Submit a pull request describing scope, evidence, risk, and rollback.

Never commit credentials, personal data, generated customer data, or provider tokens. AI-assisted contributions are welcome when the author reviews the result and remains accountable for its correctness and licensing.
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Nilhan de Mel

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
5 changes: 5 additions & 0 deletions RIGHTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Rights and Reuse

Original source code authored for this repository is available under the terms in [LICENSE](LICENSE).

Third-party packages remain under their own licenses. Public-source datasets, captured source material, fonts, logos, screenshots, generated evidence, and other assets are not relicensed unless their containing directory or accompanying notice explicitly says so. Product and company names remain the property of their respective owners.
5 changes: 5 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Security Policy

Please report suspected vulnerabilities privately to [nilhan.dev@gmail.com](mailto:nilhan.dev@gmail.com). Include the affected component, reproduction steps, likely impact, and sanitized supporting evidence.

Do not post credentials, personal data, private business data, or a working exploit in a public issue. Please allow reasonable time for validation and remediation before public disclosure.
Binary file added docs/social-preview.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions docs/social-preview.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading