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
152 lines
4.7 KiB
Python
Executable File
152 lines
4.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Pre-commit hook to check for external CDN and resource references.
|
|
Ensures all resources are served locally from vendor directories.
|
|
"""
|
|
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
from typing import List, Tuple
|
|
|
|
# Patterns that indicate external resources
|
|
EXTERNAL_PATTERNS = [
|
|
# CDN URLs (with or without protocol)
|
|
r"(https?://)?cdn\.(cloudflare|jsdelivr|unpkg|jspm|skypack)",
|
|
r"(https?://)?cdnjs\.(cloudflare\.com|com)",
|
|
r"(https?://)?unpkg\.(com|\.)",
|
|
r"(https?://)?jsdelivr\.(net|com)",
|
|
r"(https?://)?ajax\.googleapis\.",
|
|
r"(https?://)?code\.jquery\.",
|
|
r"(https?://)?maxcdn\.",
|
|
r"(https?://)?stackpath\.",
|
|
# Common external libraries
|
|
r"https?://.*\/(jquery|bootstrap|react|vue|angular|fontawesome|font-awesome)[\-\.]",
|
|
# Script/link tags with external sources (excluding vendor paths)
|
|
r'<script[^>]+src=["\']https?://(?!localhost|127\.0\.0\.1)',
|
|
r'<link[^>]+href=["\']https?://(?!localhost|127\.0\.0\.1)',
|
|
# Integrity attributes (often used with CDNs)
|
|
r'integrity=["\']sha(256|384|512)-',
|
|
r'crossorigin=["\']anonymous["\']',
|
|
]
|
|
|
|
# Allowed external resources (APIs, documentation, etc)
|
|
ALLOWED_PATTERNS = [
|
|
# API endpoints
|
|
r"https?://api\.",
|
|
r"https?://.*\.api\.",
|
|
r"openrouter\.ai/api",
|
|
# Documentation and source links
|
|
r"https?://github\.com",
|
|
r"https?://docs\.",
|
|
r"https?://.*\.readthedocs\.",
|
|
r"https?://npmjs\.com",
|
|
r"https?://pypi\.org",
|
|
# Example/placeholder URLs
|
|
r"https?://example\.",
|
|
r"https?://localhost",
|
|
r"https?://127\.0\.0\.1",
|
|
r"https?://0\.0\.0\.0",
|
|
# Common in comments or documentation
|
|
r"#.*https?://",
|
|
r"//.*https?://",
|
|
r"\*.*https?://",
|
|
]
|
|
|
|
|
|
def check_file(filepath: Path) -> List[Tuple[int, str, str]]:
|
|
"""
|
|
Check a file for external resource references.
|
|
|
|
Returns list of (line_number, line_content, pattern_matched) tuples.
|
|
"""
|
|
violations = []
|
|
|
|
try:
|
|
with open(filepath, "r", encoding="utf-8") as f:
|
|
lines = f.readlines()
|
|
except (UnicodeDecodeError, IOError):
|
|
# Skip binary files or files we can't read
|
|
return violations
|
|
|
|
for line_num, line in enumerate(lines, 1):
|
|
# Check if line contains external patterns
|
|
for pattern in EXTERNAL_PATTERNS:
|
|
if re.search(pattern, line, re.IGNORECASE):
|
|
# Check if it's an allowed exception
|
|
is_allowed = False
|
|
for allowed in ALLOWED_PATTERNS:
|
|
if re.search(allowed, line, re.IGNORECASE):
|
|
is_allowed = True
|
|
break
|
|
|
|
if not is_allowed:
|
|
violations.append((line_num, line.strip(), pattern))
|
|
break # Only report first matching pattern per line
|
|
|
|
return violations
|
|
|
|
|
|
def main():
|
|
"""Main entry point for the pre-commit hook."""
|
|
# Get list of files to check from command line arguments
|
|
files = sys.argv[1:] if len(sys.argv) > 1 else []
|
|
|
|
if not files:
|
|
# If no files specified, check all relevant files
|
|
patterns = ["**/*.html", "**/*.js", "**/*.css", "**/*.py"]
|
|
files = []
|
|
for pattern in patterns:
|
|
files.extend(Path(".").glob(pattern))
|
|
else:
|
|
files = [Path(f) for f in files]
|
|
|
|
all_violations = []
|
|
|
|
for filepath in files:
|
|
# Skip vendor directories and node_modules
|
|
if any(
|
|
part in filepath.parts
|
|
for part in [
|
|
"vendor",
|
|
"node_modules",
|
|
".venv",
|
|
"venv",
|
|
"__pycache__",
|
|
]
|
|
):
|
|
continue
|
|
|
|
violations = check_file(filepath)
|
|
if violations:
|
|
all_violations.append((filepath, violations))
|
|
|
|
if all_violations:
|
|
print("\n❌ External resource references found!\n")
|
|
print(
|
|
"All resources should be served locally from the vendor directory."
|
|
)
|
|
print("Found the following external references:\n")
|
|
|
|
for filepath, violations in all_violations:
|
|
print(f"📄 {filepath}")
|
|
for line_num, line_content, pattern in violations:
|
|
print(f" Line {line_num}: {line_content[:100]}...")
|
|
print(f" Matched pattern: {pattern}\n")
|
|
|
|
print("\nTo fix this:")
|
|
print("1. Add the library to package.json as a dependency")
|
|
print("2. Run 'npm install' to download it")
|
|
print("3. Update the reference to use the local node_modules path")
|
|
print("4. Use a build process to bundle the assets")
|
|
print(
|
|
"\nAll external libraries should be managed through npm for security and version tracking."
|
|
)
|
|
return 1
|
|
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|