Skip to content

Security hardening pass - #14

Merged
sassi67 merged 1 commit into
mainfrom
security/hardening-pass
Aug 24, 2026
Merged

sassi67 merged 1 commit into
mainfrom
security/hardening-pass

Conversation

@sassi67

@sassi67 sassi67 commented Aug 24, 2026

Copy link
Copy Markdown
Owner

Summary

Remediation of the findings from a security review of the project (module code, build/supply chain, CI, repo hygiene), ordered by severity.

High

  • Pin the vcpkg toolchain (supply chain). The local .vcpkg clone was at master HEAD and auto-git pulled on every configure — executing unpinned upstream code on each dev machine and CI runner. It is now checked out (detached HEAD) at VCPKG_PINNED_COMMIT, deliberately the same commit as vcpkg.json's builtin-baseline, so the tool, its scripts, and the port baseline all come from one audited revision. A user-set VCPKG_ROOT checkout is treated as user-managed: no git operations at all. Bump procedure (move baseline + pin together) is documented in CLAUDE.md.
  • Exception boundary in OnBeginRequest (worker-process DoS). The adapters allocate per request, so std::bad_alloc could unwind through the notification into the IIS pipeline and crash w3wp.exe — taking the whole app pool down. The body is now wrapped in try/catch(...) returning RQ_NOTIFICATION_CONTINUE; the comment documents the IIS no-throw contract and the deliberate fail-open tradeoff for this demo rule.

Medium

  • CI supply chain. All actions pinned by commit SHA (actions/checkout v4, actions/cache v4, lukka/get-cmake v4.4.2 — previously @latest, a floating tag); cmakeVersion pinned to exact 4.4.2; new .github/dependabot.yml (github-actions ecosystem, weekly) keeps the pins from rotting.
  • Binary hardening. /guard:cf (compile+link; cl and clang-cl) and /sdl (MSVC only) applied globally so every TU linked into the network-facing DLL is instrumented. /GS, ASLR, DEP were already MSVC defaults.

Low / hygiene

  • .gitgnore → .gitignore: the ignore rules were inert due to the typo (_build/ was committable and nearly got committed once); the machine-specific .vscode/ is untracked accordingly (kept locally).
  • register_module.cpp no longer leaks the factory when SetRequestNotifications fails.
  • ModuleHandler's suffix match now carries a SECURITY NOTE marking it demo-only — suffix matching doesn't block a subtree (/forbidden/x passes) and std::towlower is locale-dependent, so it must not become the template for a real ACL. Semantics change deliberately left out (product decision).

Verification

  • Clean slate (_build/ + .vcpkg/ wiped): first configure clones vcpkg and checks out d92484ed…; second configure performs zero git operations and holds the pin
  • With VCPKG_ROOT set (user-managed checkout): configure leaves it untouched
  • Debug build + all tests green; Release build clean
  • dumpbin /loadconfig on the Release DLL: CF instrumented with populated guard function table
  • dumpbin -exports: still exactly one export, RegisterModule
  • git status no longer lists _build/
  • CI on the SHA-pinned actions — validated by this PR's own checks

🤖 Generated with Claude Code

Findings and rationale from the security review (plan: analyze-this-
project-from-jolly-fountain):

- Supply chain (High): the vcpkg checkout was cloned at master HEAD
  and auto-`git pull`ed on every configure, executing unpinned
  upstream code at configure time. The local .vcpkg clone is now
  pinned (detached HEAD) to VCPKG_PINNED_COMMIT — deliberately the
  same commit as vcpkg.json's builtin-baseline, so tool, scripts, and
  port baseline come from one audited revision. A user-set VCPKG_ROOT
  checkout is treated as user-managed and gets no git operations.
- Worker-process DoS (High): the adapters allocate per request, so
  std::bad_alloc could unwind through OnBeginRequest into the IIS
  pipeline and crash w3wp.exe. OnBeginRequest now has a try/catch(...)
  boundary returning RQ_NOTIFICATION_CONTINUE (fail-open is a
  documented, deliberate tradeoff for this demo rule).
- CI supply chain (Medium): all actions pinned by commit SHA
  (checkout v4, cache v4, get-cmake v4.4.2), cmakeVersion pinned to
  4.4.2, and a Dependabot config added so the pins receive update PRs.
- Binary hardening (Medium): /guard:cf (compile+link, cl and clang-cl)
  and /sdl (MSVC only) applied globally so every TU linked into the
  network-facing DLL is instrumented; verified CF-instrumented via
  dumpbin /loadconfig.
- Hygiene (Low): .gitgnore renamed to .gitignore so the ignore rules
  actually apply, and the machine-specific .vscode/ untracked
  accordingly; register_module.cpp no longer leaks the factory when
  SetRequestNotifications fails; ModuleHandler's suffix match carries
  a SECURITY NOTE marking it demo-only (not an ACL primitive).

CLAUDE.md documents the vcpkg bump procedure (baseline + pin move
together), the no-throw boundary contract, and the SHA-pinning
convention for new actions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@sassi67 sassi67 self-assigned this Aug 24, 2026
@sassi67 sassi67 added the enhancement New feature or request label Aug 24, 2026
@sassi67
sassi67 merged commit 32bfc00 into main Aug 24, 2026
2 checks passed
@sassi67
sassi67 deleted the security/hardening-pass branch August 24, 2026 18:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant