Skip to content

Commit 5312fa4

Browse files
committed
fix missing cases
1 parent d541df5 commit 5312fa4

2 files changed

Lines changed: 37 additions & 21 deletions

File tree

  • .claude/skills
    • secure-microsoft-excel-validation
    • secure-microsoft-word-validation

.claude/skills/secure-microsoft-excel-validation/SKILL.md

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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

.claude/skills/secure-microsoft-word-validation/SKILL.md

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -88,17 +88,18 @@ public class SafeWordFileReader {
8888
// ── CHECK 4: ZIP bomb — total uncompressed size must not exceed 50 MB ──
8989
long maxUncompressedBytes = 50L * 1024 * 1024;
9090
long totalUncompressedSize = 0;
91-
try (java.util.zip.ZipFile zip = new java.util.zip.ZipFile(file)) {
92-
java.util.Enumeration<? extends java.util.zip.ZipEntry> entries = zip.entries();
93-
while (entries.hasMoreElements()) {
94-
java.util.zip.ZipEntry entry = entries.nextElement();
95-
long entrySize = entry.getSize();
96-
if (entrySize > 0) {
97-
totalUncompressedSize += entrySize;
98-
}
99-
if (totalUncompressedSize > maxUncompressedBytes) {
100-
throw new SecurityException("File total uncompressed size exceeds the maximum allowed size of 50 MB. Possible ZIP bomb detected.");
91+
byte[] drainBuffer = new byte[8192];
92+
try (java.util.zip.ZipInputStream zis = new java.util.zip.ZipInputStream(new java.io.BufferedInputStream(new FileInputStream(file)))) {
93+
java.util.zip.ZipEntry entry;
94+
while ((entry = zis.getNextEntry()) != null) {
95+
int bytesRead;
96+
while ((bytesRead = zis.read(drainBuffer)) != -1) {
97+
totalUncompressedSize += bytesRead;
98+
if (totalUncompressedSize > maxUncompressedBytes) {
99+
throw new SecurityException("File total uncompressed size exceeds the maximum allowed size of 50 MB. Possible ZIP bomb detected.");
100+
}
101101
}
102+
zis.closeEntry();
102103
}
103104
}
104105

@@ -134,7 +135,7 @@ public class SafeWordFileReader {
134135
if (!docParts.isEmpty()) {
135136
try (java.io.InputStream docIs = docParts.get(0).getInputStream()) {
136137
String docXml = new String(docIs.readAllBytes(), java.nio.charset.StandardCharsets.UTF_8).toUpperCase();
137-
if (docXml.contains("DDEAUTO") || docXml.contains(">DDE ") || docXml.contains(">DDE<")) {
138+
if (java.util.regex.Pattern.compile("\\bDDEAUTO\\b|\\bDDE\\b").matcher(docXml).find()) {
138139
throw new SecurityException("File contains DDE (Dynamic Data Exchange) fields. DDE fields are not allowed.");
139140
}
140141
}

0 commit comments

Comments
 (0)