@@ -22,6 +22,7 @@ Apply **all** rules below when generating or reviewing any code related to valid
2222- ALWAYS ensure that the file has no Object Linking and Embedding (OLE) package.
2323- ALWAYS ensure that the file has no external data connections.
2424- ALWAYS ensure that the file has no external links.
25+ - ALWAYS ensure that the file has no Dynamic Data Exchange (DDE) formula in cell content.
2526
2627``` java
2728// BAD: No validation is applied
@@ -86,17 +87,18 @@ public class SafeExcelFileReader {
8687 // ── CHECK 4: ZIP bomb — total uncompressed size must not exceed 50 MB ──
8788 long maxUncompressedBytes = 50L * 1024 * 1024 ;
8889 long totalUncompressedSize = 0 ;
89- try ( java.util.zip . ZipFile zip = new java.util.zip . ZipFile (file)) {
90- java.util.Enumeration<? extends java.util.zip. ZipEntry > entries = zip . entries();
91- while (entries . hasMoreElements()) {
92- java.util.zip . ZipEntry entry = entries . nextElement();
93- long entrySize = entry . getSize() ;
94- if (entrySize > 0 ) {
95- totalUncompressedSize += entrySize ;
96- }
97- if (totalUncompressedSize > maxUncompressedBytes) {
98- throw new SecurityException ( " File total uncompressed size exceeds the maximum allowed size of 50 MB. Possible ZIP bomb detected. " );
90+ byte [] drainBuffer = new byte [ 8192 ];
91+ try ( java.util.zip . ZipInputStream zis = new java.util.zip. ZipInputStream ( new java.io . BufferedInputStream ( new FileInputStream (file)))) {
92+ java.util.zip . ZipEntry entry;
93+ while (( entry = zis . getNextEntry()) != null ) {
94+ int bytesRead ;
95+ while ((bytesRead = zis . read(drainBuffer)) != - 1 ) {
96+ totalUncompressedSize += bytesRead ;
97+ if (totalUncompressedSize > maxUncompressedBytes) {
98+ throw new SecurityException ( " File total uncompressed size exceeds the maximum allowed size of 50 MB. Possible ZIP bomb detected. " );
99+ }
99100 }
101+ zis. closeEntry();
100102 }
101103 }
102104
@@ -105,6 +107,7 @@ public class SafeExcelFileReader {
105107 // ── CHECK 7: No embedded OLE/ActiveX objects ──────────────────────
106108 // ── CHECK 8: No external data connections ─────────────────────────
107109 // ── CHECK 9: No external links ────────────────────────────────────
110+ // ── CHECK 10: No DDE formulas in cell content ─────────────────────
108111 String oleObjectUri = " http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject" ;
109112 String activeXUri = " http://schemas.microsoft.com/office/2006/relationships/activeX" ;
110113
@@ -136,6 +139,17 @@ public class SafeExcelFileReader {
136139 }
137140 }
138141 }
142+
143+ java.util.List<PackagePart > sheetParts = pkg. getPartsByName(java.util.regex. Pattern . compile(" /xl/worksheets/sheet[0-9]+\\ .xml" ));
144+ java.util.regex. Pattern ddePattern = java.util.regex. Pattern . compile(" \\ bDDEAUTO\\ b|\\ bDDE\\ b" );
145+ for (PackagePart sheetPart : sheetParts) {
146+ try (java.io. InputStream sheetIs = sheetPart. getInputStream()) {
147+ String sheetXml = new String (sheetIs. readAllBytes(), java.nio.charset. StandardCharsets . UTF_8 ). toUpperCase();
148+ if (ddePattern. matcher(sheetXml). find()) {
149+ throw new SecurityException (" File contains a DDE formula in sheet: " + sheetPart. getPartName() + " . DDE formulas are not allowed." );
150+ }
151+ }
152+ }
139153 }
140154
141155 // ── READ: Sheet data ───────────────────────────────────────────────
@@ -177,6 +191,7 @@ Before finalizing generated code, verify:
177191- [ ] The file has no Object Linking and Embedding (OLE) package.
178192- [ ] The file has no external data connections.
179193- [ ] The file has no external links.
194+ - [ ] The file has no Dynamic Data Exchange (DDE) formula in cell content.
180195
181196## References
182197
0 commit comments