Skip to content

Added web exploitation IDOR LAB #3

Added web exploitation IDOR LAB

Added web exploitation IDOR LAB #3

name: Auto-generate GitHub Pages index
on:
push:
branches: ["main"]
paths:
- "labs/**"
- ".github/workflows/generate-pages-index.yml"
workflow_dispatch:
permissions:
contents: write
jobs:
generate:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Generate docs/index.html (Labs section)
env:
GITHUB_REPOSITORY: ${{ github.repository }}
run: |
python - <<'PY'
from __future__ import annotations
import html
import re
from pathlib import Path
ROOT = Path('.').resolve()
DOCS_INDEX = ROOT / 'docs' / 'index.html'
LABS_DIR = ROOT / 'labs'
START = '<!-- LABS:START -->'
END = '<!-- LABS:END -->'
def sanitize_text(text: str) -> str:
text = text.strip()
if not text:
return ''
# Markdown cleanup (best-effort)
text = re.sub(r'!\[[^\]]*\]\([^)]+\)', '', text) # images
text = re.sub(r'\[([^\]]+)\]\([^)]+\)', r'\1', text) # links
text = text.replace('`', '')
text = re.sub(r'[*_]{1,3}', '', text) # emphasis markers
text = re.sub(r'\s+', ' ', text).strip()
return text
def clamp(text: str, max_len: int = 160) -> str:
if len(text) <= max_len:
return text
cut = text[: max_len - 1].rstrip()
cut = re.sub(r'[\s,;:.!?]+$', '', cut)
return cut + '…'
def extract_title_and_description(readme_text: str) -> tuple[str, str]:
lines = readme_text.splitlines()
title = ''
for line in lines:
s = line.strip()
if s.startswith('# '):
title = sanitize_text(s[2:])
break
if not title:
title = 'Untitled lab'
# Description = first paragraph after the H1
desc_lines: list[str] = []
in_body = False
started = False
for line in lines:
s = line.strip()
if not in_body:
if s.startswith('# '):
in_body = True
continue
if s.startswith('#'):
break
if not started:
if not s:
continue
started = True
if started and not s:
break
if s:
desc_lines.append(s)
desc = sanitize_text(' '.join(desc_lines))
desc = clamp(desc, 160)
if not desc:
desc = 'Self-contained lab with vulnerable and fixed builds.'
return title, desc
def discover_labs() -> list[tuple[str, str, str]]:
labs: list[tuple[str, str, str]] = []
if not LABS_DIR.exists():
return labs
for child in sorted(LABS_DIR.iterdir()):
if not child.is_dir():
continue
readme = child / 'README.md'
if not readme.exists():
continue
title, desc = extract_title_and_description(readme.read_text(encoding='utf-8'))
labs.append((child.name, title, desc))
labs.sort(key=lambda t: t[1].lower())
return labs
def render_cards(labs: list[tuple[str, str, str]]) -> str:
repo = __import__('os').environ.get('GITHUB_REPOSITORY', 'DebaA17/cybersecurity-labs')
branch = 'main'
if not labs:
return (
' <article class="card">\n'
' <h3>No labs found</h3>\n'
' <p class="muted">Add a lab under <code>labs/</code> with a README.md.</p>\n'
' </article>\n'
)
parts: list[str] = []
for slug, title, desc in labs:
href = f'https://github.com/{repo}/tree/{branch}/labs/{slug}'
parts.append(
' <article class="card">\n'
f' <h3>{html.escape(title)}</h3>\n'
f' <p class="muted">{html.escape(desc)}</p>\n'
' <div class="links">\n'
f' <a href="{href}">Open lab</a>\n'
' </div>\n'
' </article>'
)
return '\n\n'.join(parts) + '\n'
index = DOCS_INDEX.read_text(encoding='utf-8')
a = index.find(START)
b = index.find(END)
if a == -1 or b == -1 or b < a:
raise SystemExit(f'Markers not found in {DOCS_INDEX}')
rendered = render_cards(discover_labs())
line_start = index.rfind('\n', 0, b) + 1
indent = index[line_start:b]
updated = index[: a + len(START)] + '\n' + rendered + indent + index[b:]
if updated != index:
DOCS_INDEX.write_text(updated, encoding='utf-8')
print('Updated docs/index.html')
else:
print('No changes needed')
PY
- name: Commit and push if changed
run: |
if git diff --quiet; then
echo "No changes to commit."
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add docs/index.html
git commit -m "chore(pages): auto-update labs index [skip ci]"
git push