Skip to content

Add standalone OWASP cheat sheet refresh script - #952

Open
Bornunique911 wants to merge 6 commits into
OWASP:mainfrom
Bornunique911:review/issue-471-cheatsheet-refresh-script
Open

Add standalone OWASP cheat sheet refresh script#952
Bornunique911 wants to merge 6 commits into
OWASP:mainfrom
Bornunique911:review/issue-471-cheatsheet-refresh-script

Conversation

@Bornunique911

@Bornunique911 Bornunique911 commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR is split out from the larger issue-471 review flow to make review smaller and more focused.

It adds a standalone script for refreshing OWASP Cheat Sheet data and normalizing cheat sheet links in the local cache.

Issue reference:

Problem Fixed

The earlier refresh-scripts review became too large because it was mixed with broader OWASP importer and follow-up work.

For this part of the work, the useful standalone contribution is:

  • rebuilding cheat sheet data into the cache
  • normalizing GitHub-style cheat sheet links to official OWASP Cheat Sheet Series URLs
  • providing that workflow as a reusable script with backup and environment setup

Solution

This PR adds a single standalone script:

  • scripts/update-cheatsheets.sh

The script:

  • prepares the local virtual environment if needed
  • installs Python dependencies if required
  • verifies the target database exists
  • creates a timestamped backup
  • reimports cheat sheet data using --cheatsheets_in
  • normalizes stored cheat sheet links from GitHub paths to official OWASP Cheat Sheet Series URLs

Tests

bash -n scripts/update-cheatsheets.sh

Reviewer Notes

This PR is intentionally narrow because it was split to reduce review size:

  • no frontend changes
  • no parser-stack expansion
  • no unrelated OWASP importer changes
  • no bundle artifacts

This PR is meant to be reviewed as a standalone operational helper.

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Summary by CodeRabbit

  • Chores
    • Added an automated process for updating OWASP Cheat Sheet links to official URLs.
    • Prepares the required execution environment and dependencies automatically.
    • Creates an optional timestamped database backup before applying updates.
    • Disables unnecessary analysis and embedding steps during the import.
    • Enables stricter error handling for more reliable update execution.

Walkthrough

This PR adds scripts/update-cheatsheets.sh. The script prepares a Python environment, optionally backs up the SQLite database, imports Cheat Sheet data, and normalizes matching OWASP links.

Changes

Cheatsheets Update Script

Layer / File(s) Summary
Runtime setup and database backup
scripts/update-cheatsheets.sh
Enables strict Bash handling, prepares the Python virtual environment, installs dependencies, and optionally creates a timestamped database backup.
Cheatsheet data import
scripts/update-cheatsheets.sh
Disables gap analysis and embedding generation, then runs cre.py to import Cheat Sheet data.
OWASP link normalization
scripts/update-cheatsheets.sh
Converts matching GitHub Cheat Sheet links to official .html URLs, commits the database updates, and reports the normalization count.

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

Possibly related PRs

  • OWASP/OpenCRE#954: Adds parser changes related to the OWASP Cheat Sheet links normalized by this script.

Suggested reviewers: robvanderveer, paoga87, pa04rth

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the added standalone OWASP cheat sheet refresh script.
Description check ✅ Passed The description directly explains the script's purpose, workflow, scope, issue references, and syntax test.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (2)
scripts/update-cheatsheets.sh (2)

23-24: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Backup filename collision within the same second.

date +%Y%m%d%H%M%S has 1-second resolution; two runs within the same second silently overwrite each other's backup.

🛡️ Add uniqueness
-BACKUP_FILE="${DB_PATH}.$(date +%Y%m%d%H%M%S).bak"
+BACKUP_FILE="${DB_PATH}.$(date +%Y%m%d%H%M%S)_$$.bak"
🤖 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 `@scripts/update-cheatsheets.sh` around lines 23 - 24, The backup creation in
the update-cheatsheets script can collide when run multiple times within the
same second because BACKUP_FILE is based only on date +%Y%m%d%H%M%S. Update the
BACKUP_FILE naming logic in the script so each run produces a unique filename,
for example by adding higher-resolution time, the process ID, or another unique
suffix, and keep the cp backup step using that new unique name.

14-16: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Fragile dependency-check proxy.

Using import flask success as a stand-in for "all deps installed" means new/updated packages in requirements.txt won't get installed if flask is already present in the venv from a prior run.

♻️ Simpler and more robust alternative
-if ! python -c "import flask" >/dev/null 2>&1; then
-  pip install -r "$ROOT_DIR/requirements.txt"
-fi
+pip install -q -r "$ROOT_DIR/requirements.txt"

pip install is idempotent and fast when nothing changed, so always running it avoids silently skipping updated dependencies.

🤖 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 `@scripts/update-cheatsheets.sh` around lines 14 - 16, The dependency check in
the update-cheatsheets.sh script is too narrow because it only tests flask via
the python import gate, so updated or newly added packages in requirements.txt
can be skipped. Remove the import-based conditional around the pip install step
and always run the requirements installation in the script flow so dependency
updates are applied reliably; the relevant logic is the shell block that wraps
pip install -r "$ROOT_DIR/requirements.txt".
🤖 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.

Nitpick comments:
In `@scripts/update-cheatsheets.sh`:
- Around line 23-24: The backup creation in the update-cheatsheets script can
collide when run multiple times within the same second because BACKUP_FILE is
based only on date +%Y%m%d%H%M%S. Update the BACKUP_FILE naming logic in the
script so each run produces a unique filename, for example by adding
higher-resolution time, the process ID, or another unique suffix, and keep the
cp backup step using that new unique name.
- Around line 14-16: The dependency check in the update-cheatsheets.sh script is
too narrow because it only tests flask via the python import gate, so updated or
newly added packages in requirements.txt can be skipped. Remove the import-based
conditional around the pip install step and always run the requirements
installation in the script flow so dependency updates are applied reliably; the
relevant logic is the shell block that wraps pip install -r
"$ROOT_DIR/requirements.txt".

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 4a99f980-fd4a-4622-a8a0-b5532012fd97

📥 Commits

Reviewing files that changed from the base of the PR and between 0e16c2e and 716f8b2.

📒 Files selected for processing (1)
  • scripts/update-cheatsheets.sh

@Bornunique911
Bornunique911 force-pushed the review/issue-471-cheatsheet-refresh-script branch from 76283a2 to cdf6c55 Compare July 31, 2026 18:54

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🤖 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 `@scripts/update-cheatsheets.sh`:
- Around line 8-15: Update the virtual-environment setup in
update-cheatsheets.sh to validate $VENV_DIR/bin/python rather than only the
directory, recreate the environment when that executable is missing, and use the
absolute $VENV_DIR/bin/python for Python and pip operations so system
executables cannot be selected.
- Around line 23-28: Replace the raw cp-based backup in the backup creation flow
with an existing virtualenv Python script using sqlite3.Connection.backup() to
copy DB_PATH to BACKUP_FILE, and wait for that process to complete before
reopening DB_PATH. Afterward, run PRAGMA integrity_check against BACKUP_FILE and
fail if the check is not successful, preserving the existing backup failure
handling.
🪄 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: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro Plus

Run ID: 08927877-75c1-4288-b289-949e2a2a7b1d

📥 Commits

Reviewing files that changed from the base of the PR and between 716f8b2 and cdf6c55.

📒 Files selected for processing (1)
  • scripts/update-cheatsheets.sh

Comment thread scripts/update-cheatsheets.sh Outdated
Comment thread scripts/update-cheatsheets.sh Outdated
@northdpole

Copy link
Copy Markdown
Collaborator

Heads-up: #950 (mapping fixtures) just merged. Rebase onto latest main if needed before review.

1 similar comment
@northdpole

Copy link
Copy Markdown
Collaborator

Heads-up: #950 (mapping fixtures) just merged. Rebase onto latest main if needed before review.

@northdpole

Copy link
Copy Markdown
Collaborator

Please rebase onto latest main (~28 commits behind; #950 fixtures just merged).

Also see review notes on the backup/sqlite3 integrity-check block — dst_conn is used after the with closes.

@northdpole northdpole left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Review — cheat sheet refresh script (#952)

Small standalone script — good split from #471. Please rebase (~28 behind) and fix the backup integrity check before merge.

Blocker

In the Python backup snippet, integrity check runs after the with sqlite3.connect(...) context exits, so dst_conn is already closed:

with sqlite3.connect(src) as src_conn, sqlite3.connect(dst) as dst_conn:
    src_conn.backup(dst_conn)
cur = dst_conn.cursor()  # closed

Move PRAGMA integrity_check inside the with, or reopen dst for the check.

Non-blocking

  • Mirror scripts/update-cwe.sh more closely where possible (CRE_NO_NEO4J, simpler cp backup is fine for SQLite cache if you prefer)
  • Always pip install -r requirements.txt on every run is heavy; consider install-if-missing like other scripts (optional)
  • Add trailing newline at EOF
  • After #950, confirm this script’s link-normalization assumptions still match cheat-sheet URL shape

Happy to approve once rebase + backup fix are in.

@Bornunique911
Bornunique911 force-pushed the review/issue-471-cheatsheet-refresh-script branch from ca9da5b to 8d6ca21 Compare August 7, 2026 07:58
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

Bornunique911 added a commit to Bornunique911/OpenCRE that referenced this pull request Aug 7, 2026
- Replace SQLite online backup with a simple `cp` backup (matches update-cwe.sh)
- Remove stamp-file optimisation to keep unconditional pip install
- Keep environment variables to disable gap analysis and embeddings
- Keep link normalization to convert GitHub URLs to official HTML pages
- Ensure trailing newline at EOF

This addresses all points from PR review OWASP#952.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (2)
scripts/update-cheatsheets.sh (2)

41-52: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Match canonical GitHub file URLs before normalizing Cheat Sheet links.

If cached rows use /blob/master/cheatsheets/..., the LIKE selector misses them and normalizes 0 rows. Include that /blob/ form in the selection before extracting the filename.

🤖 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 `@scripts/update-cheatsheets.sh` around lines 41 - 52, Update the row-selection
query using github_prefix so it matches both canonical GitHub tree URLs and
/blob/master/cheatsheets/ file URLs before normalization. Preserve the existing
filename extraction and normalization flow, ensuring cached blob-form rows are
included.

44-59: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Reject empty filenames before constructing the HTML URL.

link LIKE prefix% also matches the exact .../cheatsheets/ prefix; os.path.basename(link) then returns an empty filename and html_name becomes .html. Skip links without a non-empty filename before updating the row.

🤖 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 `@scripts/update-cheatsheets.sh` around lines 44 - 59, In the loop over rows
returned by the node query, validate the basename-derived filename before
constructing html_name or executing the update. Skip entries where
os.path.basename(link) is empty, while preserving the existing URL conversion
for links with non-empty filenames.
♻️ Duplicate comments (1)
scripts/update-cheatsheets.sh (1)

10-18: ⚠️ Potential issue | 🟡 Minor

Reapply the virtual-environment executable check.

The current code checks only whether "$VENV_DIR" is a directory. An incomplete environment can pass this check. source can then fail, or pip and python can resolve to system executables. Check "$VENV_DIR/bin/python" and invoke that absolute interpreter for pip and both Python commands. This finding duplicates the previous review comment, but it remains present in the current code.

Suggested fix
-if [[ ! -d "$VENV_DIR" ]]; then
+if [[ ! -x "$VENV_DIR/bin/python" ]]; then
   echo "Creating virtual environment in $VENV_DIR"
+  rm -rf -- "$VENV_DIR"
   python3 -m venv "$VENV_DIR"
 fi
 
-source "$VENV_DIR/bin/activate"
-
 echo "Installing Python runtime dependencies"
-pip install -r "$ROOT_DIR/requirements.txt"
+"$VENV_DIR/bin/python" -m pip install -r "$ROOT_DIR/requirements.txt"
 
 ...
-python "$ROOT_DIR/cre.py" --cheatsheets_in --cache_file "$CACHE_FILE"
+"$VENV_DIR/bin/python" "$ROOT_DIR/cre.py" --cheatsheets_in --cache_file "$CACHE_FILE"
 
 ...
-python - "$CACHE_FILE" <<'PY'
+"$VENV_DIR/bin/python" - "$CACHE_FILE" <<'PY'

Also applies to: 29-29, 32-32

🤖 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 `@scripts/update-cheatsheets.sh` around lines 10 - 18, Update the
virtual-environment setup check in the script to validate "$VENV_DIR/bin/python"
rather than only the directory, recreating the environment when that executable
is missing. Use the absolute "$VENV_DIR/bin/python" for pip installation and
both Python command invocations, while preserving activation and existing
behavior.
🤖 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 `@scripts/update-cheatsheets.sh`:
- Around line 20-23: Replace the raw cp operation in the CACHE_FILE backup block
with a SQLite-consistent backup using sqlite3.Connection.backup(), and run
PRAGMA integrity_check before or after the backup to validate it. Ensure the
backup handles live WAL state safely and preserves the existing success message
and conditional flow.

---

Outside diff comments:
In `@scripts/update-cheatsheets.sh`:
- Around line 41-52: Update the row-selection query using github_prefix so it
matches both canonical GitHub tree URLs and /blob/master/cheatsheets/ file URLs
before normalization. Preserve the existing filename extraction and
normalization flow, ensuring cached blob-form rows are included.
- Around line 44-59: In the loop over rows returned by the node query, validate
the basename-derived filename before constructing html_name or executing the
update. Skip entries where os.path.basename(link) is empty, while preserving the
existing URL conversion for links with non-empty filenames.

---

Duplicate comments:
In `@scripts/update-cheatsheets.sh`:
- Around line 10-18: Update the virtual-environment setup check in the script to
validate "$VENV_DIR/bin/python" rather than only the directory, recreating the
environment when that executable is missing. Use the absolute
"$VENV_DIR/bin/python" for pip installation and both Python command invocations,
while preserving activation and existing behavior.
🪄 Autofix

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: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro Plus

Run ID: c54d97ea-1d0a-4795-8871-449a3e611acf

📥 Commits

Reviewing files that changed from the base of the PR and between 8d6ca21 and d16fd2b.

📒 Files selected for processing (1)
  • scripts/update-cheatsheets.sh

Comment thread scripts/update-cheatsheets.sh Outdated
Bornunique911 added a commit to Bornunique911/OpenCRE that referenced this pull request Aug 7, 2026
- Replace SQLite online backup with a simple `cp` backup (matches update-cwe.sh)
- Remove stamp-file optimisation to keep unconditional pip install
- Keep environment variables to disable gap analysis and embeddings
- Keep link normalization to convert GitHub URLs to official HTML pages
- Ensure trailing newline at EOF

This addresses all points from PR review OWASP#952.
@Bornunique911
Bornunique911 force-pushed the review/issue-471-cheatsheet-refresh-script branch from d16fd2b to 6918afd Compare August 7, 2026 09:19
Bornunique911 added a commit to Bornunique911/OpenCRE that referenced this pull request Aug 7, 2026
- Replace unsafe `cp` with sqlite3.Connection.backup() to handle WAL files
  and ensure consistency for live databases.
- Move PRAGMA integrity_check inside the connection context to avoid
  using a closed connection (fixes the blocker from PR review OWASP#952).
- Keep stamp‑file optimisation for pip install (optional but harmless).
- Ensure trailing newline and preserve link-normalisation logic.

@northdpole northdpole left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Re-review

Prior blocker fixed — thanks. Integrity check now runs inside the dst_conn context after src_conn.backup(dst_conn), so dst_conn is still open. Online backup is a solid choice for WAL-aware SQLite.

CI green, MERGEABLE, single-file script. Optional nit: add a trailing newline at EOF.

Approve. Happy to rebase-merge when you want it landed (or after a light rebase onto latest main — currently ~11 behind, unlikely to conflict).

@northdpole

Copy link
Copy Markdown
Collaborator

Maintainer note (2026-08-09): Merge decision on this PR is postponed ~1 week (target revisit ~2026-08-16).

Context for that revisit: July call was to park #952/#953/#960 as GSoC reference (only #950 was meant to land first); #954 has since merged and already normalizes cheat sheet URLs in the parser, so the SQL normalize step here may be redundant. Options then: keep parked, shrink to backup+--cheatsheets_in only, or merge.

No action needed from the author until we come back to it. Approval stands technically; product/stack decision is deferred.

@northdpole

Copy link
Copy Markdown
Collaborator

@Bornunique911 thank you for the cheat-sheet refresh script updates and for keeping CI green.

Merge decision on #952 remains parked (revisit with the end-of-August #471 / fixture reshape batch, alongside the July park note). Appreciate you sticking with the focused PR pattern.

- Replace SQLite online backup with a simple `cp` backup (matches update-cwe.sh)
- Remove stamp-file optimisation to keep unconditional pip install
- Keep environment variables to disable gap analysis and embeddings
- Keep link normalization to convert GitHub URLs to official HTML pages
- Ensure trailing newline at EOF

This addresses all points from PR review OWASP#952.
- Replace unsafe `cp` with sqlite3.Connection.backup() to handle WAL files
  and ensure consistency for live databases.
- Move PRAGMA integrity_check inside the connection context to avoid
  using a closed connection (fixes the blocker from PR review OWASP#952).
- Keep stamp‑file optimisation for pip install (optional but harmless).
- Ensure trailing newline and preserve link-normalisation logic.
@Bornunique911
Bornunique911 force-pushed the review/issue-471-cheatsheet-refresh-script branch from a1e765d to eedd526 Compare August 10, 2026 18:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants