@patrickdk77/archive-defuse 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -175,6 +175,8 @@ Every file entry goes to `filePlugins` in order, with pdf-defuse's shapes. A plu
175
175
 
176
176
  The plugin's findings come into the report with `attachment` set to the entry's name. A `reject` inside the entry becomes `strip`, since the entry goes and the archive stays. When no plugin accepts an entry, ENTRY/NO_PLUGIN removes it. As `info`, the entry stays.
177
177
 
178
+ A plugin's answer is final, and its findings are all the entry adds to the score. ENTRY/PLUGIN_PASSED and PLUGIN_SCRUBBED weigh 0, in the upload's score and the output's. ENTRY/PLUGIN_FAILED weighs 30, what NO_PLUGIN weighs, since no plugin answered for the entry.
179
+
178
180
  Before the plugins, a type check reports ENTRY/TYPE_MISMATCH (`info`) when the name's extension and the content disagree, as pdf-defuse does for attached files. A plugin never checks types.
179
181
 
180
182
  `passThrough(types)` keeps entries by MIME type or extension, such as `passThrough(['text/csv', '.txt'])`.
package/dist/engine.js CHANGED
@@ -38,7 +38,6 @@ async function endRun(run) {
38
38
  await run.temp.cleanup();
39
39
  }
40
40
  }
41
- const PLUGIN_KEPT = new Set([types_1.ArchiveDetail.PluginPassed, types_1.ArchiveDetail.PluginScrubbed]);
42
41
  /** Kinds whose content the rewrite drops whatever their action, so an info override leaves CONTENT_REMOVED. */
43
42
  const DROPPED_ANYWAY = new Set([types_1.ArchiveDetail.HiddenData, types_1.ArchiveDetail.NonFileData, types_1.ArchiveDetail.ExtraField]);
44
43
  /**
@@ -52,7 +51,9 @@ function finish(findings, options, incomplete, archive, isOutput = false) {
52
51
  const rejected = findings.some(f => f.action === 'reject');
53
52
  // In an upload, a plugin rewrite or a metadata strip changes the file, so the output must be written.
54
53
  const strippable = findings.some(f => f.action === 'strip' || (!isOutput && (f.detail === types_1.ArchiveDetail.PluginScrubbed || f.detail === types_1.ArchiveDetail.Stripped) && f.attachment === undefined));
55
- const { score, risk } = (0, score_1.scoreFindings)(isOutput ? findings : findings.filter(f => !PLUGIN_KEPT.has(f.detail)), options);
54
+ // What a plugin decided counts at the weights of the plugin's own findings; the PLUGIN_* findings that record its
55
+ // answer weigh nothing.
56
+ const { score, risk } = (0, score_1.scoreFindings)(findings, options);
56
57
  return { status: rejected ? 'rejected' : strippable ? 'strippable' : 'clean', score, risk, findings, ...named };
57
58
  }
58
59
  /** A value from the archive, such as a name, cut to a length a report can carry. */
package/dist/findings.js CHANGED
@@ -89,9 +89,9 @@ def(types_1.ArchiveCategory.Compression, types_1.ArchiveDetail.UnsupportedFeatur
89
89
  // ENTRY
90
90
  def(types_1.ArchiveCategory.Entry, types_1.ArchiveDetail.NoPlugin, 'strip', 30, '<Entry "{name}"|An entry> (<{sniffed}|unknown type>) removed. No plugin accepts this type');
91
91
  def(types_1.ArchiveCategory.Entry, types_1.ArchiveDetail.TypeMismatch, 'info', 40, 'The types of <entry "{name}"|an unnamed entry> disagree: <its name says {nameType}|its name has no known extension>, and <its content looks like {sniffed}|its content is not recognized>');
92
- def(types_1.ArchiveCategory.Entry, types_1.ArchiveDetail.PluginPassed, 'info', 20, 'Entry kept by plugin <plugin> with nothing removed');
93
- def(types_1.ArchiveCategory.Entry, types_1.ArchiveDetail.PluginScrubbed, 'info', 10, 'Entry cleaned and kept by plugin <plugin>');
94
- def(types_1.ArchiveCategory.Entry, types_1.ArchiveDetail.PluginFailed, 'strip', 0, 'Plugin <plugin> failed, so the entry was removed');
92
+ def(types_1.ArchiveCategory.Entry, types_1.ArchiveDetail.PluginPassed, 'info', 0, 'Entry kept by plugin <plugin> with nothing removed');
93
+ def(types_1.ArchiveCategory.Entry, types_1.ArchiveDetail.PluginScrubbed, 'info', 0, 'Entry cleaned and kept by plugin <plugin>');
94
+ def(types_1.ArchiveCategory.Entry, types_1.ArchiveDetail.PluginFailed, 'strip', 30, 'Plugin <plugin> failed, so the entry was removed');
95
95
  def(types_1.ArchiveCategory.Entry, types_1.ArchiveDetail.PluginRemoved, 'strip', 0, 'Entry removed by plugin <plugin>');
96
96
  // METADATA
97
97
  def(types_1.ArchiveCategory.Metadata, types_1.ArchiveDetail.Comment, 'info', 0, 'The archive or an entry carries a comment');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patrickdk77/archive-defuse",
3
- "version": "0.1.3",
3
+ "version": "0.2.0",
4
4
  "description": "Sanitize zip, tar, gzip, bzip2, zstd, Brotli, cab, 7z, xz and lzma archives. Detects path traversal, links out of the tree, device files, duplicate names, overlapping entries, hidden and prepended data, encrypted entries and compression bombs, hands every entry to file plugins, scores the risk, and writes a defused archive in the same format with no runtime dependencies.",
5
5
  "license": "MIT AND Apache-2.0",
6
6
  "author": "patrickdk77",