From 669eaa7c65baa98c573ca79ae05b491fac737eb3 Mon Sep 17 00:00:00 2001 From: Marcel Date: Sun, 17 May 2026 16:18:03 +0200 Subject: [PATCH] fix(ci): pin semgrep version, add pip cache, harden rule severity - Pin semgrep to 1.163.0 to prevent silent upgrades breaking the scan - Add cache: 'pip' to setup-python@v5 for faster CI runs - Promote all three XXE Semgrep rules from WARNING to ERROR to match the --error CI flag intent - Update SAX/StAX rule messages to reference XxeSafeXmlParser and the OWASP XXE prevention cheat sheet - Remove stale issue reference from regression test comment - Document XML metacharacter constraint on buildValidOds test helper Co-Authored-By: Claude Sonnet 4.6 --- .gitea/workflows/ci.yml | 3 ++- .semgrep/security.yml | 15 ++++++++++----- .../importing/MassImportServiceTest.java | 5 +++-- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 2877e9b3..a086f7c8 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -289,9 +289,10 @@ jobs: - uses: actions/setup-python@v5 with: python-version: '3.11' + cache: 'pip' - name: Install Semgrep - run: pip install semgrep + run: pip install semgrep==1.163.0 - name: Run security rules run: semgrep --config .semgrep/security.yml --error --metrics=off backend/src/ diff --git a/.semgrep/security.yml b/.semgrep/security.yml index da787175..fb3e00cc 100644 --- a/.semgrep/security.yml +++ b/.semgrep/security.yml @@ -17,8 +17,9 @@ rules: message: > DocumentBuilderFactory without XXE protection (CWE-611). Call XxeSafeXmlParser.hardenedFactory() instead of DocumentBuilderFactory.newInstance(). + See: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html languages: [java] - severity: WARNING + severity: ERROR # SAXParserFactory without XXE hardening. - id: sax-xxe-default @@ -30,9 +31,11 @@ rules: ... message: > SAXParserFactory without XXE protection (CWE-611). - Apply disallow-doctype-decl and disable external entity features before use. + Set disallow-doctype-decl=true, external-general-entities=false, external-parameter-entities=false, + and load-external-dtd=false before use. Follow the pattern in XxeSafeXmlParser.hardenedFactory(). + See: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html languages: [java] - severity: WARNING + severity: ERROR # XMLInputFactory without XXE hardening (StAX parser). - id: stax-xxe-default @@ -44,6 +47,8 @@ rules: ... message: > XMLInputFactory without XXE protection (CWE-611). - Set IS_SUPPORTING_EXTERNAL_ENTITIES to false and SUPPORT_DTD to false before use. + Set IS_SUPPORTING_EXTERNAL_ENTITIES=false and SUPPORT_DTD=false before use. + Follow the pattern in XxeSafeXmlParser.hardenedFactory(). + See: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html languages: [java] - severity: WARNING + severity: ERROR diff --git a/backend/src/test/java/org/raddatz/familienarchiv/importing/MassImportServiceTest.java b/backend/src/test/java/org/raddatz/familienarchiv/importing/MassImportServiceTest.java index dfd63607..dcd7c707 100644 --- a/backend/src/test/java/org/raddatz/familienarchiv/importing/MassImportServiceTest.java +++ b/backend/src/test/java/org/raddatz/familienarchiv/importing/MassImportServiceTest.java @@ -527,7 +527,7 @@ class MassImportServiceTest { // ─── readOds — XXE security regression ─────────────────────────────────── - // Security regression — do not remove. Introduced by issue #528. + // Security regression — do not remove. @Test void readOds_rejects_xxe_doctype_payload(@TempDir Path tempDir) throws Exception { File malicious = buildXxeOds(tempDir, "file:///etc/hostname"); @@ -595,7 +595,8 @@ class MassImportServiceTest { return writeOdsZip(dir.resolve("malicious.ods"), xml); } - /** Creates a minimal valid ODS ZIP containing a content.xml with the given cell value. */ + /** Creates a minimal valid ODS ZIP containing a content.xml with the given cell value. + * cellValue must not contain XML metacharacters ({@code < > &}). */ private File buildValidOds(Path dir, String cellValue) throws Exception { String xml = "" + "