7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
235 lines
7.0 KiB
Bash
Executable File
235 lines
7.0 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Security check for potential unencrypted file writes to disk
|
|
# This script helps prevent accidentally bypassing encryption at rest
|
|
|
|
set -e
|
|
|
|
echo "Checking for potential unencrypted file writes to disk..."
|
|
echo "========================================="
|
|
|
|
# Patterns that might indicate writing sensitive data to disk
|
|
# Note: Using basic grep patterns without lookaheads
|
|
SUSPICIOUS_PATTERNS=(
|
|
# Python patterns
|
|
"\.write\("
|
|
"\.save\("
|
|
"\.dump\("
|
|
"open\(.*['\"]w['\"].*\)"
|
|
"open\(.*['\"]wb['\"].*\)"
|
|
"with.*open\(.*['\"]w['\"]"
|
|
"with.*open\(.*['\"]wb['\"]"
|
|
"\.to_csv\("
|
|
"\.to_json\("
|
|
"\.to_excel\("
|
|
"\.to_pickle\("
|
|
"tempfile\.NamedTemporaryFile.*delete=False"
|
|
"Path.*\.write_text\("
|
|
"Path.*\.write_bytes\("
|
|
"shutil\.copy"
|
|
"shutil\.move"
|
|
"\.export_to_file\("
|
|
"\.save_to_file\("
|
|
"\.write_pdf\("
|
|
"\.savefig\("
|
|
# JavaScript patterns
|
|
"fs\.writeFile"
|
|
"fs\.writeFileSync"
|
|
"fs\.createWriteStream"
|
|
"fs\.appendFile"
|
|
)
|
|
|
|
# Directories to exclude from checks
|
|
EXCLUDE_DIRS=(
|
|
"tests"
|
|
"test"
|
|
"__pycache__"
|
|
".git"
|
|
"node_modules"
|
|
".venv"
|
|
"venv"
|
|
"migrations"
|
|
"static"
|
|
"vendor"
|
|
"dist"
|
|
"build"
|
|
".next"
|
|
"coverage"
|
|
"examples"
|
|
"scripts"
|
|
".github"
|
|
"cookiecutter-docker"
|
|
)
|
|
|
|
# Files to exclude
|
|
EXCLUDE_FILES=(
|
|
"*_test.py"
|
|
"test_*.py"
|
|
"*.test.js"
|
|
"*.spec.js"
|
|
"*.test.ts"
|
|
"*.spec.ts"
|
|
"setup.py"
|
|
"webpack.config.js"
|
|
"**/migrations/*.py"
|
|
"*.min.js"
|
|
"*.bundle.js"
|
|
"*-min.js"
|
|
"*.min.css"
|
|
)
|
|
|
|
# Safe keywords that indicate encrypted or safe operations
|
|
# These patterns indicate that file writes have been security-verified
|
|
SAFE_KEYWORDS=(
|
|
"write_file_verified"
|
|
"write_json_verified"
|
|
)
|
|
|
|
# Known safe usage patterns (logs, configs, etc.)
|
|
SAFE_USAGE_PATTERNS=(
|
|
"security/file_write_verifier.py"
|
|
"import tempfile"
|
|
"tempfile\.mkdtemp"
|
|
"tmp_path"
|
|
"tmp_file"
|
|
)
|
|
|
|
# Build exclude arguments for grep
|
|
EXCLUDE_ARGS=""
|
|
for dir in "${EXCLUDE_DIRS[@]}"; do
|
|
EXCLUDE_ARGS="$EXCLUDE_ARGS --exclude-dir=$dir"
|
|
done
|
|
|
|
for file in "${EXCLUDE_FILES[@]}"; do
|
|
EXCLUDE_ARGS="$EXCLUDE_ARGS --exclude=$file"
|
|
done
|
|
|
|
# Track if we found any issues
|
|
FOUND_ISSUES=0
|
|
ALL_MATCHES=""
|
|
|
|
echo "Scanning codebase for suspicious patterns..."
|
|
|
|
# Search only in src/ directory to avoid .venv and other non-source directories
|
|
SEARCH_PATHS="src/"
|
|
|
|
# Single pass to collect all matches
|
|
for pattern in "${SUSPICIOUS_PATTERNS[@]}"; do
|
|
# Use grep with binary files excluded and max line length to avoid issues with minified files
|
|
# shellcheck disable=SC2086 # Word splitting is intentional for EXCLUDE_ARGS
|
|
matches=$(grep -rn -I $EXCLUDE_ARGS -- "$pattern" $SEARCH_PATHS --include="*.py" --include="*.js" --include="*.ts" 2>/dev/null | head -1000 || true)
|
|
if [ -n "$matches" ]; then
|
|
ALL_MATCHES="$ALL_MATCHES$matches\n"
|
|
fi
|
|
done
|
|
|
|
# Also check for specific problematic patterns in one pass
|
|
# shellcheck disable=SC2086 # Word splitting is intentional for EXCLUDE_ARGS
|
|
temp_matches=$(grep -rn -I $EXCLUDE_ARGS -E "tmp_path|tempfile|/tmp/" $SEARCH_PATHS --include="*.py" 2>/dev/null | head -500 || true)
|
|
if [ -n "$temp_matches" ]; then
|
|
ALL_MATCHES="$ALL_MATCHES$temp_matches\n"
|
|
fi
|
|
|
|
# shellcheck disable=SC2086 # Word splitting is intentional for EXCLUDE_ARGS
|
|
db_matches=$(grep -rn -I $EXCLUDE_ARGS -E "report_content.*open|report_content.*write|markdown_content.*open|markdown_content.*write" $SEARCH_PATHS --include="*.py" 2>/dev/null | head -500 || true)
|
|
if [ -n "$db_matches" ]; then
|
|
ALL_MATCHES="$ALL_MATCHES$db_matches\n"
|
|
fi
|
|
|
|
# shellcheck disable=SC2086 # Word splitting is intentional for EXCLUDE_ARGS
|
|
export_matches=$(grep -rn -I $EXCLUDE_ARGS -E "export.*Path|export.*path\.open|export.*\.write" $SEARCH_PATHS --include="*.py" 2>/dev/null | head -500 || true)
|
|
if [ -n "$export_matches" ]; then
|
|
ALL_MATCHES="$ALL_MATCHES$export_matches\n"
|
|
fi
|
|
|
|
# Now filter all matches at once
|
|
if [ -n "$ALL_MATCHES" ]; then
|
|
echo "Filtering results for false positives..."
|
|
|
|
# Remove duplicates and sort (use tr to handle potential null bytes)
|
|
ALL_MATCHES=$(echo -e "$ALL_MATCHES" | tr -d '\0' | sort -u)
|
|
|
|
filtered_matches=""
|
|
while IFS= read -r line; do
|
|
[ -z "$line" ] && continue
|
|
|
|
# Check if line contains safe keywords
|
|
skip_line=0
|
|
for safe_pattern in "${SAFE_KEYWORDS[@]}"; do
|
|
if echo "$line" | grep -qE -- "$safe_pattern"; then
|
|
skip_line=1
|
|
break
|
|
fi
|
|
done
|
|
|
|
# Check if line contains safe usage patterns
|
|
if [ "$skip_line" -eq 0 ]; then
|
|
for usage_pattern in "${SAFE_USAGE_PATTERNS[@]}"; do
|
|
if echo "$line" | grep -qE -- "$usage_pattern"; then
|
|
skip_line=1
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# Additional filters for test/mock files that might not be caught by path exclusion
|
|
if [ "$skip_line" -eq 0 ]; then
|
|
if echo "$line" | grep -qE "test|mock|stub" && ! echo "$line" | grep -q "#"; then
|
|
skip_line=1
|
|
fi
|
|
fi
|
|
|
|
# Allowlist of files that legitimately write to disk without encryption.
|
|
# These must NOT touch user data or secrets — only:
|
|
# - web/app_factory.py — Flask/framework config writes
|
|
# - document_loaders/bytes_loader.py — in-memory → tmp for parsers
|
|
# - journal_quality/downloader.py — public OpenAlex/DOAJ/predatory/
|
|
# JabRef/ROR snapshots downloaded to the user data dir (bibliographic
|
|
# metadata only — journal names, ISSNs, h-indices; no PII/secrets)
|
|
# - journal_quality/data_sources/*.py — same family, per-source adapters
|
|
# that write the intermediate JSON manifests under the user data dir
|
|
# If you add an entry here, document WHY the file's writes are safe
|
|
# (public data, not user-specific, not encrypted at rest by design).
|
|
if [ "$skip_line" -eq 0 ]; then
|
|
if echo "$line" | grep -qE "web/app_factory\.py|document_loaders/bytes_loader\.py|journal_quality/downloader\.py|journal_quality/data_sources/.+\.py"; then
|
|
skip_line=1
|
|
fi
|
|
fi
|
|
|
|
# Filter safe temp files with proper cleanup
|
|
if [ "$skip_line" -eq 0 ]; then
|
|
if echo "$line" | grep -q "database/encrypted_db.py"; then
|
|
skip_line=1
|
|
fi
|
|
fi
|
|
|
|
if [ "$skip_line" -eq 0 ]; then
|
|
filtered_matches="$filtered_matches$line\n"
|
|
FOUND_ISSUES=1
|
|
fi
|
|
done <<< "$ALL_MATCHES"
|
|
|
|
if [ -n "$filtered_matches" ] && [ "$FOUND_ISSUES" -eq 1 ]; then
|
|
echo "⚠️ Found potential unencrypted file writes:"
|
|
echo "========================================="
|
|
echo -e "$filtered_matches"
|
|
fi
|
|
fi
|
|
|
|
echo "========================================="
|
|
|
|
if [ $FOUND_ISSUES -eq 1 ]; then
|
|
echo "❌ Security check failed: Found potential unencrypted file writes"
|
|
echo ""
|
|
echo "Please review the above findings and ensure:"
|
|
echo "1. Sensitive data is not written to disk unencrypted"
|
|
echo "2. Temporary files are properly cleaned up"
|
|
echo "3. Use in-memory operations where possible"
|
|
echo "4. If file writes are necessary, ensure they're encrypted or add '# Safe: <reason>' comment"
|
|
echo ""
|
|
echo "For exports, use the in-memory pattern like in export_report_to_memory()"
|
|
exit 1
|
|
else
|
|
echo "✅ Security check passed: No suspicious unencrypted file writes detected"
|
|
fi
|