fix(security): close remaining CodeQL alerts + document mandatory patterns

Fixes the 4 fixable alerts opened in the recent scan and adds enforceable
guardrails so future development follows the same pattern.

Code fixes:
- src/mitm/cert/install.ts: pass certPath/certName/action via exec()'s env
  option instead of string-interpolating them into the bash script
  (CodeQL js/shell-command-injection-from-environment #225)
- scripts/docs/{gen-provider-reference,add-frontmatter,fix-internal-links}:
  escape backslash before other regex/markdown metacharacters
  (CodeQL js/incomplete-sanitization #227, #228, #229)

Documentation (mandatory patterns):
- docs/security/PUBLIC_CREDS.md — embedding public upstream OAuth/Firebase
  identifiers via resolvePublicCred(); never as string literals
- docs/security/ERROR_SANITIZATION.md — routing every error response through
  sanitizeErrorMessage()/buildErrorBody(); never raw err.stack/err.message
- CLAUDE.md: 4 new Hard Rules (#11-#14) + Security section + scenario notes
- AGENTS.md, CONTRIBUTING.md: cross-reference the two new docs
- SECURITY.md: extended Hard Security Rules with the new mandatory patterns
- docs/README.md: index entries pointing to the two new docs

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
diegosouzapw
2026-05-14 11:12:14 -03:00
parent 1a39c31ff4
commit 037f4e8d50
11 changed files with 354 additions and 19 deletions

View File

@@ -94,8 +94,8 @@ function humanizeBasename(filePath) {
}
function buildFrontmatter(title) {
// Quote title with double quotes; escape internal double quotes.
const safe = title.replace(/"/g, '\\"');
// Quote title with double quotes; escape backslashes first, then double quotes.
const safe = title.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
return [
`---`,
`title: "${safe}"`,

View File

@@ -96,9 +96,13 @@ const DOC_TO_SUBFOLDER = {
};
// Build alternation regex (longest-first) of file basenames we know about.
// Escape regex metacharacters (including backslash) defensively, even though
// the source list is internal — keeps CodeQL happy and future-proofs against
// names like "FOO\BAR.md".
const RE_META = /[\\^$.*+?()[\]{}|]/g;
const FILES_ALT = Object.keys(DOC_TO_SUBFOLDER)
.sort((a, b) => b.length - a.length)
.map((s) => s.replace(/\./g, "\\."))
.map((s) => s.replace(RE_META, "\\$&"))
.join("|");
// ----------------------------------------------------------------------

View File

@@ -50,7 +50,8 @@ function asRecords(map: Record<string, ProviderRecord>): ProviderRecord[] {
function escapeCell(value: string | undefined): string {
if (!value) return "—";
return value.replace(/\|/g, "\\|").replace(/\n/g, " ");
// Escape backslash first so the subsequent escapes don't double-escape it.
return value.replace(/\\/g, "\\\\").replace(/\|/g, "\\|").replace(/\n/g, " ");
}
function row(p: ProviderRecord, category: string): string {