Skip to content

fix: audit remediation — webapp XSS/CSP, CI/script hardening, ATLAS registry gap, spelling - #216

Merged
emmanuelgjr merged 1 commit into
mainfrom
fix/audit-remediation-batch
Jun 10, 2026
Merged

fix: audit remediation — webapp XSS/CSP, CI/script hardening, ATLAS registry gap, spelling#216
emmanuelgjr merged 1 commit into
mainfrom
fix/audit-remediation-batch

Conversation

@emmanuelgjr

Copy link
Copy Markdown
Owner

What & why

Remediation batch for the verified findings from a full-repo security / cohesion / precision audit (4 parallel auditors → high/medium claims re-computed or read against the code; several auditor claims were disproven and excluded).

Security

  • M1 — escape XSS sink in the framework-submission validator (docs/index.html). User-pasted JSON (fw.name, the duplicate-control_id error list, JSON parse-error message) flowed into innerHTML unescaped. Now wrapped in the existing esc(). Self-XSS in practice (the form only builds a GitHub issue link — nothing is persisted or served to other viewers; the auditor's "stored XSS" framing was wrong), but no XSS sink belongs in an OWASP reference app.
  • L3 — Content-Security-Policy + SRI (docs/index.html). Added a CSP <meta>: default-src 'self', inline allowed (the app is entirely inline scripts/styles/handlers — 'unsafe-inline' is unavoidable without a refactor), network egress limited to api.github.com, scripts to self + jsDelivr, plus object-src 'none' / base-uri 'self' / frame-ancestors 'none'. Also SRI-pinned the dynamically-loaded d3@7.8.5 (integrity + crossorigin).
  • L1 — workflow injection hardening (.github/workflows/crosswalk-check.yml). github.base_ref now passed via env: and consumed with execFileSync('git', [...]) instead of being interpolated into an execSync shell string. (Not externally exploitable — base_ref is the target branch, not fork-controlled — but this file is a template meant to be copied into other repos, so the pattern matters.)
  • L2 — path-traversal guard (scripts/ingest-framework.mjs). Reject non-slug framework ids and assert the resolved path stays inside data/frameworks/. Defense-in-depth: the schema already enforces the id pattern (verified — a ../evil id is rejected at validation), and the workflow is maintainer-label-gated, so this was low-risk; the explicit guard makes it obvious.

Cohesion / precision

  • M3 — fill the local ATLAS registry gap (data/frameworks/mitre-atlas.json). 10 entry mappings cited 4 techniques valid in current upstream ATLAS but absent from the local 43-entry registry (trimmed in fix(atlas): reconcile MITRE ATLAS framework data v4.0 -> v5.6.0 (#187) #211). Added AML.T0021 Establish Accounts, AML.T0053 AI Agent Tool Invocation, AML.T0060 Publish Hallucinated Entities, AML.T0066 Retrieval Content Crafting (authoritative titles + concise GenAI-style descriptions, registry changelog entry). Registry 43 → 47; mapping→registry misses 10 → 0. Total controls 1,507 → 1,511, propagated to README badge/text, CITATION.cff, banner.svg, og-image.svg.
  • L6 — spelling consistency. Aligned the DSGAI10 entry name to the documented British canonical "Anonymisation" (in scripts/generate.js META — the real source — and CROSSREF.md), matching the deliberate DSGAI heading normalization. The "ARX Data Anonymization" product name (a real tool) and body prose are deliberately left untouched. Regenerated data/entries/*, data/backlinks.json, docs/{data,backlinks,frameworks-registry}.js.

Explicitly out of scope (tracked, not fixed here)

  • M2 — prose-vs-formal-code control_id schism. ~341 of 3,351 mappings (SOC 2, EU AI Act, FedRAMP, NHI, 800-218A/82, AITG…) carry bespoke prose control_ids that don't join the registry's formal codes (the formal code sits in control_name). Looks like a deliberate authoring pattern across 9 frameworks — needs a design decision, not a blind rewrite.
  • L5 — classifier-split staleness. 566 of 3,210 split rows reference triples no longer in current entry mappings (frozen at 10f2372; non-ATLAS frameworks drifted). Eval-only; resolves on the next split regeneration. Hashes all valid.

Disproven auditor claims (excluded)

CWE/CVE "38 duplicate control_ids" → zero duplicates in any framework; AIUC-1 "mapping tables as controls" → only 2 formal misses; webapp "stored XSS affecting other viewers" → self-XSS; "controls should be 1,514" → 1,514 was a pre-#211 milestone, the computed figure is 1,511 after this PR.

Verification

  • node scripts/validate.js0 errors / 0 warnings / 385 passed
  • markdownlint README.md CROSSREF.md → clean
  • Traversal guard self-tested (rejects ../evil); ATLAS misses recomputed to 0

🤖 Generated with Claude Code

…TLAS registry, spelling

Addresses verified findings from the full-repo security/cohesion/precision audit.

Security:
- M1 docs/index.html: escape user-submitted JSON (fw.name, control_id error
  list, parse-error message) via the existing esc() before innerHTML in the
  framework-submission validator (self-XSS sink, but unacceptable on an OWASP app)
- L3 docs/index.html: add a Content-Security-Policy meta (default-src self;
  inline allowed since the app is fully inline; egress limited to api.github.com;
  d3 from jsDelivr) + SRI-pin the dynamically-loaded d3@7.8.5 script
- L1 .github/workflows/crosswalk-check.yml: pass github.base_ref via env and use
  execFileSync(argv) instead of interpolating into an execSync shell string
- L2 scripts/ingest-framework.mjs: reject non-slug framework ids and assert the
  resolved path stays in data/frameworks/ (defense-in-depth; schema already pins
  the id pattern)

Cohesion / precision:
- M3 data/frameworks/mitre-atlas.json: add 4 techniques cited by entry mappings
  but missing from the local registry — AML.T0021, T0053, T0060, T0066 (all
  present in current upstream ATLAS). Clears 10 mapping->registry misses; 43->47.
  Total controls 1,507 -> 1,511 (propagated to README, CITATION, banner, og-image).
- L6 spelling: align DSGAI10 entry name to the documented British canonical
  "Anonymisation" in generate.js META + CROSSREF.md (the "ARX Data Anonymization"
  product name and body prose are correctly left as-is). Regenerated entries/mirrors.

Not in scope (tracked separately): M2 prose-vs-formal-code control_id schism
across ~9 frameworks (deliberate-looking authoring choice — needs a design call);
L5 classifier-split staleness vs current mappings (resolves on next split regen).

validate.js 0/0/385; markdownlint clean; traversal guard self-tested.
@github-actions

Copy link
Copy Markdown
Contributor

🛡️ OWASP GenAI Security Crosswalk

This PR modifies 5 AI-related file(s). The following OWASP GenAI risks may be relevant:

Risk Entry Files Action
ASI01 Agent Goal Hijack docs/backlinks.js, docs/data.js, docs/frameworks-registry.js View controls
ASI02 Tool Misuse docs/backlinks.js, docs/data.js, docs/frameworks-registry.js View controls
ASI03 Credential Misuse docs/backlinks.js, docs/data.js, docs/frameworks-registry.js View controls
ASI04 Supply Chain docs/backlinks.js, docs/data.js, docs/frameworks-registry.js View controls
ASI05 Code Execution docs/backlinks.js, docs/data.js, docs/frameworks-registry.js View controls
DSGAI01 Data Leakage docs/backlinks.js, docs/data.js, docs/frameworks-registry.js View controls
DSGAI04 RAG Poisoning docs/backlinks.js, docs/data.js, docs/frameworks-registry.js View controls
DSGAI08 Configuration & Deployment docs/backlinks.js, docs/data.js, docs/frameworks-registry.js View controls
LLM01 Prompt Injection docs/backlinks.js, docs/data.js, docs/frameworks-registry.js View controls
LLM02 Sensitive Information Disclosure docs/backlinks.js, docs/data.js, docs/frameworks-registry.js View controls
LLM03 Supply Chain docs/data.js, docs/frameworks-registry.js View controls
LLM04 Data & Model Poisoning docs/backlinks.js, docs/data.js, docs/frameworks-registry.js View controls
LLM06 Excessive Agency docs/backlinks.js, docs/data.js, docs/frameworks-registry.js View controls
LLM07 System Prompt Leakage docs/backlinks.js, docs/data.js, docs/frameworks-registry.js View controls
LLM09 Misinformation docs/backlinks.js, docs/data.js, docs/frameworks-registry.js View controls

🔍 Scanned 17 changed files · Found 15 potential risks · Full crosswalk · Gap analysis

@emmanuelgjr
emmanuelgjr merged commit 738c6da into main Jun 10, 2026
9 checks passed
@emmanuelgjr
emmanuelgjr deleted the fix/audit-remediation-batch branch June 10, 2026 04:42
emmanuelgjr added a commit that referenced this pull request Jun 10, 2026
)

e.id and c.function).filter(Boolean))] are 0-byte artifacts from shell
command output that got swept in by git add -A. No references; pure cleanup.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant