diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties
index 3c86b5446dc4c97322b2d9a9847caa1694de8bba..fcdf3304c76bdb4194749f1e0fb0ea0458d2f081 100644
--- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties
@@ -25,3 +25,4 @@ EULADialog.title=Cyber Triage End User License Agreement
 CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text=
 CTMalwareScannerOptionsPanel.disclaimer.text=<html>The Cyber Triage Malware Scanner module uses 40+ malware scanning engines to identify if Windows executables are malicious. It requires a paid subscription to use.</html>
 CTMalwareScannerOptionsPanel.purchaseFromLabel.text=For licensing information, visit
+
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form
index 841490d657d8ef66d193ff7f5ca450b41ebdae56..abd9449e6782939873d37243977810d13dc42ddc 100644
--- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.form
@@ -16,6 +16,93 @@
 
   <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
   <SubComponents>
+    <Container class="javax.swing.JPanel" name="licenseInfoPanel">
+      <Properties>
+        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+          <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
+            <TitledBorder title="License Info">
+              <ResourceString PropertyName="titleX" bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTMalwareScannerOptionsPanel.licenseInfoPanel.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </TitledBorder>
+          </Border>
+        </Property>
+      </Properties>
+      <AuxValues>
+        <AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
+        <AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
+      </AuxValues>
+      <Constraints>
+        <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+          <GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="0.0"/>
+        </Constraint>
+      </Constraints>
+
+      <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
+      <SubComponents>
+        <Component class="javax.swing.JLabel" name="licenseInfoMessageLabel">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+          <Constraints>
+            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+              <GridBagConstraints gridX="0" gridY="0" gridWidth="2" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
+            </Constraint>
+          </Constraints>
+        </Component>
+        <Component class="javax.swing.JLabel" name="licenseInfoUserLabel">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTMalwareScannerOptionsPanel.licenseInfoUserLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+          <Constraints>
+            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+              <GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
+            </Constraint>
+          </Constraints>
+        </Component>
+        <Component class="javax.swing.JLabel" name="licenseInfoExpiresLabel">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTMalwareScannerOptionsPanel.licenseInfoExpiresLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+          <Constraints>
+            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+              <GridBagConstraints gridX="1" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
+            </Constraint>
+          </Constraints>
+        </Component>
+        <Component class="javax.swing.JLabel" name="licenseInfoIdLabel">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTMalwareScannerOptionsPanel.licenseInfoIdLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+          <Constraints>
+            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+              <GridBagConstraints gridX="0" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
+            </Constraint>
+          </Constraints>
+        </Component>
+        <Component class="javax.swing.JButton" name="licenseInfoAddButton">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTMalwareScannerOptionsPanel.licenseInfoAddButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="licenseInfoAddButtonActionPerformed"/>
+          </Events>
+          <Constraints>
+            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+              <GridBagConstraints gridX="1" gridY="2" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="12" weightX="1.0" weightY="0.0"/>
+            </Constraint>
+          </Constraints>
+        </Component>
+      </SubComponents>
+    </Container>
     <Container class="javax.swing.JPanel" name="malwareScansPanel">
       <Properties>
         <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java
index f0e1a4e88fcee28c30a4cde326fb4edba5738c51..481dc31955e8b7b64f08b2031cb50622e9babfa6 100644
--- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTMalwareScannerOptionsPanel.java
@@ -155,6 +155,15 @@ private void gotoLink(String url) {
 
     private synchronized LicenseResponse getLicenseInfo() {
         return this.licenseInfo == null ? null : this.licenseInfo.getLicenseResponse();
+
+    private MalwareIngestSettings getIngestSettings() {
+        return new MalwareIngestSettings();
+    }
+
+    private void setIngestSettings(MalwareIngestSettings ingestSettings) {
+        if (ingestSettings == null) {
+            ingestSettings = new MalwareIngestSettings();
+        }
     }
 
     private synchronized void setLicenseDisplay(LicenseInfo licenseInfo, String licenseMessage) {
@@ -260,6 +269,7 @@ private void initComponents() {
         gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
         malwareScansPanel.add(disclaimer, gridBagConstraints);
 
+        licenseInfoPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.licenseInfoPanel.border.title"))); // NOI18N
         licenseInfoPanel.setLayout(new java.awt.GridBagLayout());
 
         org.openide.awt.Mnemonics.setLocalizedText(licenseInfoMessageLabel, org.openide.util.NbBundle.getMessage(CTMalwareScannerOptionsPanel.class, "CTMalwareScannerOptionsPanel.licenseInfoMessageLabel.text")); // NOI18N
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties
new file mode 100644
index 0000000000000000000000000000000000000000..e9fdcb1cb54558342fc3c773008a4300170573a4
--- /dev/null
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties
@@ -0,0 +1,7 @@
+MalwareScanIngestSettingsPanel.uploadFilesCheckbox.AccessibleContext.accessibleName=Upload file content for files that do not have results
+MalwareScanIngestSettingsPanel.uploadFilesCheckbox.label=Upload file content for files that do not have results
+MalwareScanIngestSettingsPanel.uploadFilesCheckbox.text=Upload file content for files that do not have results
+DataSourceIntegrityIngestSettingsPanel.queryFilesTextArea.text=Query file existing results using file\u2019s hash
+MalwareScanIngestSettingsPanel.ingestSettingsLabel.text=Ingest Settings
+MalwareScanIngestSettingsPanel.paidLicenseTextArea.text=This module requires a paid license. \nSee the Global Options panel for details
+MalwareScanIngestSettingsPanel.queryFilesCheckbox.text=Query for existing results using file\u2019s hash
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED
index 4380a9607c8ce4600aabba5cd89473c2aca49e73..3b886d02cb0bee0184d225eeb75d4bd809c1bba9 100644
--- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties-MERGED
@@ -38,6 +38,13 @@ MalwareScanIngestModule_uploadFile_noRemainingFileUploads_title=No Remaining Fil
 # {0} - objectId
 MalwareScanIngestModule_uploadFile_notUploadable_desc=A file did not meet requirements for upload (object id: {0}).
 MalwareScanIngestModule_uploadFile_notUploadable_title=Not Able to Upload
-MalwareScanIngestModuleFactory_description=The malware scan ingest module queries the Cyber Triage cloud API for any possible malicious executables.
+MalwareScanIngestModuleFactory_description=Identifies executable files with malware.
 MalwareScanIngestModuleFactory_displayName=Cyber Triage Malware Scanner
 MalwareScanIngestModuleFactory_version=1.0.0
+MalwareScanIngestSettingsPanel.uploadFilesCheckbox.AccessibleContext.accessibleName=Upload file content for files that do not have results
+MalwareScanIngestSettingsPanel.uploadFilesCheckbox.label=Upload file content for files that do not have results
+MalwareScanIngestSettingsPanel.uploadFilesCheckbox.text=Upload file content for files that do not have results
+DataSourceIntegrityIngestSettingsPanel.queryFilesTextArea.text=Query file existing results using file\u2019s hash
+MalwareScanIngestSettingsPanel.ingestSettingsLabel.text=Ingest Settings
+MalwareScanIngestSettingsPanel.paidLicenseTextArea.text=This module requires a paid license. \nSee the Global Options panel for details
+MalwareScanIngestSettingsPanel.queryFilesCheckbox.text=Query for existing results using file\u2019s hash
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle_ar.properties b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle_ar.properties
new file mode 100644
index 0000000000000000000000000000000000000000..7a6ad43a3eeca38110aa9e58feb73a9387bd005e
--- /dev/null
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle_ar.properties
@@ -0,0 +1 @@
+MalwareScanIngestSettingsPanel.ingestSettingsLabel.text=Configuracion de Ingesta
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle_ja.properties b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle_ja.properties
new file mode 100644
index 0000000000000000000000000000000000000000..cff7aa2e8d4fc8680cb0c317c8ce19a7d57369c2
--- /dev/null
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/Bundle_ja.properties
@@ -0,0 +1 @@
+MalwareScanIngestSettingsPanel.ingestSettingsLabel.text=\u53d6\u8fbc\u307f\u8a2d\u5b9a
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java
index d8119baab09325c5eb4d52b750a8a38d659d6f5d..a9c814e7678abbfa05afd6717217974452123e81 100644
--- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModule.java
@@ -72,10 +72,17 @@
 class MalwareScanIngestModule implements FileIngestModule {
 
     private static final SharedProcessing sharedProcessing = new SharedProcessing();
-
+    private boolean uploadFiles;
+    private boolean queryFiles;
+    
+    MalwareScanIngestModule(MalwareScanIngestSettings settings) {
+        uploadFiles = settings.shouldUploadFiles();
+        queryFiles = settings.shouldQueryFiles();  
+    }
+    
     @Override
     public void startUp(IngestJobContext context) throws IngestModuleException {
-        sharedProcessing.startUp(context);
+        sharedProcessing.startUp(context, uploadFiles);
     }
 
     @Override
@@ -123,7 +130,7 @@ private static class SharedProcessing {
                 "application/msdos-windows",//NON-NLS
                 "application/x-msdos-program"//NON-NLS
         ).collect(Collectors.toSet());
-
+        
         private static final String MALWARE_TYPE_NAME = "TSK_MALWARE";
         private static final String MALWARE_CONFIG = "Cyber Triage Cloud";
 
@@ -153,14 +160,14 @@ private static class SharedProcessing {
             "MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_title=File Uploads Limit Low",
             "# {0} - remainingUploads",
             "MalwareScanIngestModule_ShareProcessing_lowUploadsLimitWarning_desc=This license only has {0} file uploads remaining.",})
-        synchronized void startUp(IngestJobContext context) throws IngestModuleException {
+        synchronized void startUp(IngestJobContext context, boolean uploadFiles) throws IngestModuleException {
             // only run this code once per startup
             if (ingestJobState != null) {
                 return;
             }
 
             try {
-                ingestJobState = getNewJobState(context);
+                ingestJobState = getNewJobState(context, uploadFiles);
             } catch (Exception ex) {
                 ingestJobState = IngestJobState.DISABLED;
                 throw new IngestModuleException("An exception occurred on MalwareScanIngestModule startup", ex);
@@ -175,7 +182,7 @@ synchronized void startUp(IngestJobContext context) throws IngestModuleException
          * parameters required for the job.
          * @throws Exception
          */
-        private IngestJobState getNewJobState(IngestJobContext context) throws Exception {
+        private IngestJobState getNewJobState(IngestJobContext context, boolean uploadFiles) throws Exception {
             // get saved license
             Optional<LicenseInfo> licenseInfoOpt = ctSettingsPersistence.loadLicenseInfo();
             if (licenseInfoOpt.isEmpty() || licenseInfoOpt.get().getDecryptedLicense() == null) {
@@ -207,7 +214,6 @@ private IngestJobState getNewJobState(IngestJobContext context) throws Exception
             }
 
             // determine lookups remaining
-            boolean uploadFiles = true;
             if (uploadFiles) {
                 long uploadsRemaining = remaining(authTokenResponse.getFileUploadLimit(), authTokenResponse.getFileUploadCount());
                 if (uploadsRemaining <= 0) {
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModuleFactory.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModuleFactory.java
index e1381160363d093f7daff876c69d2b7febca2d9b..83cb93f689c8c2b7545bcee863c5e32a2689cb0f 100644
--- a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModuleFactory.java
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestModuleFactory.java
@@ -25,6 +25,8 @@
 import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter;
 import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel;
 import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
+import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel;
+import org.sleuthkit.autopsy.ingest.NoIngestModuleIngestJobSettings;
 
 /**
  * Factory for malware scan ingest modules.
@@ -32,7 +34,7 @@
 @ServiceProvider(service = org.sleuthkit.autopsy.ingest.IngestModuleFactory.class)
 @Messages({
     "MalwareScanIngestModuleFactory_displayName=Cyber Triage Malware Scanner",
-    "MalwareScanIngestModuleFactory_description=The malware scan ingest module queries the Cyber Triage cloud API for any possible malicious executables.",
+    "MalwareScanIngestModuleFactory_description=Identifies executable files with malware.",
     "MalwareScanIngestModuleFactory_version=1.0.0"
 })
 public class MalwareScanIngestModuleFactory extends IngestModuleFactoryAdapter {
@@ -66,7 +68,7 @@ public boolean isFileIngestModuleFactory() {
 
     @Override
     public FileIngestModule createFileIngestModule(IngestModuleIngestJobSettings ingestOptions) {
-        return new MalwareScanIngestModule();
+        return new MalwareScanIngestModule((MalwareScanIngestSettings) ingestOptions);
     }
 
     @Override
@@ -81,4 +83,23 @@ public IngestModuleGlobalSettingsPanel getGlobalSettingsPanel() {
         return optionsPanel;
     }
 
+    @Override
+    public boolean hasIngestJobSettingsPanel() {
+        return true;
+    }
+
+    @Override
+    public IngestModuleIngestJobSettingsPanel getIngestJobSettingsPanel(IngestModuleIngestJobSettings settings) {
+        if (settings instanceof MalwareScanIngestSettings) {
+            return new MalwareScanIngestSettingsPanel((MalwareScanIngestSettings) settings);
+        }
+        /*
+         * Compatibility check for older versions.
+         */
+        if (settings instanceof NoIngestModuleIngestJobSettings) {
+            return new MalwareScanIngestSettingsPanel(new MalwareScanIngestSettings());
+        }
+        
+        throw new IllegalArgumentException("Expected settings argument to be an instance of IngestSettings");
+    }
 }
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettings.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettings.java
new file mode 100644
index 0000000000000000000000000000000000000000..158e9677457664b8f0793df023b4f5845ec2e878
--- /dev/null
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettings.java
@@ -0,0 +1,96 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2023 Basis Technology Corp.
+ * Contact: carrier <at> sleuthkit <dot> org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.basistech.df.cybertriage.autopsy.malwarescan;
+
+import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
+
+/**
+ * Ingest job settings for the Malware scanner module.
+ */
+final class MalwareScanIngestSettings implements IngestModuleIngestJobSettings {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final boolean DEFAULT_QUERY_FILES = true;
+    private static final boolean DEFAULT_UPLOAD_FILES = true;
+    
+    public boolean queryFiles;
+    public boolean uploadFiles;
+
+    /**
+     * Instantiate the ingest job settings with default values.
+     */
+    MalwareScanIngestSettings() {
+        this.queryFiles = DEFAULT_QUERY_FILES;
+        this.uploadFiles = DEFAULT_UPLOAD_FILES;
+    }
+
+    /**
+     * Instantiate the ingest job settings.
+     * 
+     * @param computeHashes  Compute hashes if none are present
+     * @param verifyHashes   Verify hashes if any are present
+     */
+    MalwareScanIngestSettings(boolean queryFiles, boolean uploadFiles) {
+        this.queryFiles = queryFiles;
+        this.uploadFiles = uploadFiles;
+    }
+
+    @Override
+    public long getVersionNumber() {
+        return serialVersionUID;
+    }
+    
+    /**
+     * Should files be queried?
+     * 
+     * @return true if files should be queried, false otherwise
+     */
+    public boolean shouldQueryFiles() {
+        return queryFiles;
+    }
+    
+    /**
+     * Set whether files should be queried.
+     * 
+     * @param queryFiles true if files should be queried
+     */
+    void setqueryFiles(boolean queryFiles) {
+        this.queryFiles = queryFiles;
+    }
+    
+    
+    /**
+     * Should files be uploaded?
+     * 
+     * @return true if files should be uploaded, false otherwise
+     */
+    public boolean shouldUploadFiles() {
+        return uploadFiles;
+    }    
+    
+    /**
+     * Set whether files should be uploaded.
+     * 
+     * @param uploadFiles true if files should be uploaded
+     */
+    void setUploadFiles(boolean uploadFiles) {
+        this.uploadFiles = uploadFiles;
+    }
+}
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.form
new file mode 100644
index 0000000000000000000000000000000000000000..46a928c98eda4ef9d1cd9bbdc70f65efd976632c
--- /dev/null
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.form
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <Properties>
+    <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+      <Dimension value="[300, 155]"/>
+    </Property>
+  </Properties>
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" attributes="0">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Group type="102" attributes="0">
+                      <EmptySpace min="6" pref="6" max="-2" attributes="0"/>
+                      <Component id="ingestSettingsLabel" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <Group type="102" attributes="0">
+                      <EmptySpace min="6" pref="6" max="-2" attributes="0"/>
+                      <Component id="uploadFilesCheckbox" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <Group type="102" alignment="0" attributes="0">
+                      <EmptySpace max="-2" attributes="0"/>
+                      <Component id="queryFilesCheckbox" min="-2" max="-2" attributes="0"/>
+                  </Group>
+                  <Group type="102" alignment="0" attributes="0">
+                      <EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
+                      <Component id="paidLicenseTextArea" min="-2" pref="243" max="-2" attributes="0"/>
+                  </Group>
+              </Group>
+              <EmptySpace min="-2" pref="185" max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="ingestSettingsLabel" min="-2" max="-2" attributes="0"/>
+              <EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
+              <Component id="queryFilesCheckbox" min="-2" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="uploadFilesCheckbox" min="-2" max="-2" attributes="0"/>
+              <EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
+              <Component id="paidLicenseTextArea" min="-2" pref="32" max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Component class="javax.swing.JCheckBox" name="queryFilesCheckbox">
+      <Properties>
+        <Property name="selected" type="boolean" value="true"/>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties" key="MalwareScanIngestSettingsPanel.queryFilesCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+        <Property name="enabled" type="boolean" value="false"/>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JCheckBox" name="uploadFilesCheckbox">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties" key="MalwareScanIngestSettingsPanel.uploadFilesCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+        <Property name="focusable" type="boolean" value="false"/>
+        <Property name="label" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties" key="MalwareScanIngestSettingsPanel.uploadFilesCheckbox.label" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+      <AccessibilityProperties>
+        <Property name="AccessibleContext.accessibleName" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties" key="MalwareScanIngestSettingsPanel.uploadFilesCheckbox.AccessibleContext.accessibleName" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </AccessibilityProperties>
+    </Component>
+    <Component class="javax.swing.JLabel" name="ingestSettingsLabel">
+      <Properties>
+        <Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
+          <FontInfo relative="true">
+            <Font bold="true" component="ingestSettingsLabel" property="font" relativeSize="true" size="0"/>
+          </FontInfo>
+        </Property>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties" key="MalwareScanIngestSettingsPanel.ingestSettingsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+    <Component class="javax.swing.JTextArea" name="paidLicenseTextArea">
+      <Properties>
+        <Property name="columns" type="int" value="20"/>
+        <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+          <Font name="Segoe UI" size="12" style="1"/>
+        </Property>
+        <Property name="rows" type="int" value="5"/>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="com/basistech/df/cybertriage/autopsy/malwarescan/Bundle.properties" key="MalwareScanIngestSettingsPanel.paidLicenseTextArea.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+        <Property name="wrapStyleWord" type="boolean" value="true"/>
+        <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+          <Border info="null"/>
+        </Property>
+        <Property name="cursor" type="java.awt.Cursor" editor="org.netbeans.modules.form.editors2.CursorEditor">
+          <Color id="Default Cursor"/>
+        </Property>
+        <Property name="focusable" type="boolean" value="false"/>
+        <Property name="opaque" type="boolean" value="false"/>
+        <Property name="requestFocusEnabled" type="boolean" value="false"/>
+      </Properties>
+    </Component>
+  </SubComponents>
+</Form>
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.java
new file mode 100644
index 0000000000000000000000000000000000000000..a418de0f833cb32fb9fc3b81c21cc9f9342b8de0
--- /dev/null
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/malwarescan/MalwareScanIngestSettingsPanel.java
@@ -0,0 +1,149 @@
+/*
+ * Autopsy Browser
+ *
+ * Copyright 2023 Basis Technology Corp.
+ * Contact: carrier <at> sleuthkit <dot> org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.basistech.df.cybertriage.autopsy.malwarescan;
+
+import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseInfo;
+import com.basistech.df.cybertriage.autopsy.ctoptions.ctcloud.CTLicensePersistence;
+import java.util.Optional;
+import org.sleuthkit.autopsy.modules.dataSourceIntegrity.*;
+import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
+import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel;
+
+/**
+ * Ingest job settings panel for the Malware scanner ingest.
+ */
+@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
+final class MalwareScanIngestSettingsPanel extends IngestModuleIngestJobSettingsPanel {
+
+    private final CTLicensePersistence ctPersistence = CTLicensePersistence.getInstance();
+    
+    MalwareScanIngestSettingsPanel(MalwareScanIngestSettings settings) {
+        initComponents();
+        customizeComponents(settings);
+    }
+
+    /**
+     * Update components with values from the ingest job settings.
+     *
+     * @param settings The ingest job settings.
+     */
+    private void customizeComponents(MalwareScanIngestSettings settings) {
+        Optional<LicenseInfo> licenseInfoOpt = ctPersistence.loadLicenseInfo();
+        LicenseInfo licenseInfo = licenseInfoOpt.orElse(null);
+        if (licenseInfo != null) {
+            this.paidLicenseTextArea.setVisible(false);
+            this.queryFilesCheckbox.setVisible(true);
+            this.queryFilesCheckbox.setEnabled(false);
+            this.uploadFilesCheckbox.setVisible(true);
+            this.queryFilesCheckbox.setSelected(true);
+            this.uploadFilesCheckbox.setSelected(settings.shouldUploadFiles());
+        } else {
+            this.paidLicenseTextArea.setVisible(true);
+            this.queryFilesCheckbox.setVisible(false);
+            this.uploadFilesCheckbox.setVisible(false);       
+        }
+    }
+    
+    @Override
+    public IngestModuleIngestJobSettings getSettings() {
+        return new MalwareScanIngestSettings(queryFilesCheckbox.isSelected(), uploadFilesCheckbox.isSelected());
+    }
+
+    /**
+     * This method is called from within the constructor to initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is always
+     * regenerated by the Form Editor.
+     */
+    @SuppressWarnings("unchecked")
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        queryFilesCheckbox = new javax.swing.JCheckBox();
+        uploadFilesCheckbox = new javax.swing.JCheckBox();
+        ingestSettingsLabel = new javax.swing.JLabel();
+        paidLicenseTextArea = new javax.swing.JTextArea();
+
+        setPreferredSize(new java.awt.Dimension(300, 155));
+
+        queryFilesCheckbox.setSelected(true);
+        org.openide.awt.Mnemonics.setLocalizedText(queryFilesCheckbox, org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.queryFilesCheckbox.text")); // NOI18N
+        queryFilesCheckbox.setEnabled(false);
+
+        org.openide.awt.Mnemonics.setLocalizedText(uploadFilesCheckbox, org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.uploadFilesCheckbox.text")); // NOI18N
+        uploadFilesCheckbox.setFocusable(false);
+        uploadFilesCheckbox.setLabel(org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.uploadFilesCheckbox.label")); // NOI18N
+
+        ingestSettingsLabel.setFont(ingestSettingsLabel.getFont().deriveFont(ingestSettingsLabel.getFont().getStyle() | java.awt.Font.BOLD));
+        org.openide.awt.Mnemonics.setLocalizedText(ingestSettingsLabel, org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.ingestSettingsLabel.text")); // NOI18N
+
+        paidLicenseTextArea.setColumns(20);
+        paidLicenseTextArea.setFont(new java.awt.Font("Segoe UI", 1, 12)); // NOI18N
+        paidLicenseTextArea.setRows(5);
+        paidLicenseTextArea.setText(org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.paidLicenseTextArea.text")); // NOI18N
+        paidLicenseTextArea.setWrapStyleWord(true);
+        paidLicenseTextArea.setBorder(null);
+        paidLicenseTextArea.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
+        paidLicenseTextArea.setFocusable(false);
+        paidLicenseTextArea.setOpaque(false);
+        paidLicenseTextArea.setRequestFocusEnabled(false);
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+                    .addGroup(layout.createSequentialGroup()
+                        .addGap(6, 6, 6)
+                        .addComponent(ingestSettingsLabel))
+                    .addGroup(layout.createSequentialGroup()
+                        .addGap(6, 6, 6)
+                        .addComponent(uploadFilesCheckbox))
+                    .addGroup(layout.createSequentialGroup()
+                        .addContainerGap()
+                        .addComponent(queryFilesCheckbox))
+                    .addGroup(layout.createSequentialGroup()
+                        .addGap(5, 5, 5)
+                        .addComponent(paidLicenseTextArea, javax.swing.GroupLayout.PREFERRED_SIZE, 243, javax.swing.GroupLayout.PREFERRED_SIZE)))
+                .addGap(185, 185, 185))
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addContainerGap()
+                .addComponent(ingestSettingsLabel)
+                .addGap(18, 18, 18)
+                .addComponent(queryFilesCheckbox)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(uploadFilesCheckbox)
+                .addGap(18, 18, 18)
+                .addComponent(paidLicenseTextArea, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE))
+        );
+
+        uploadFilesCheckbox.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(MalwareScanIngestSettingsPanel.class, "MalwareScanIngestSettingsPanel.uploadFilesCheckbox.AccessibleContext.accessibleName")); // NOI18N
+    }// </editor-fold>//GEN-END:initComponents
+
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JLabel ingestSettingsLabel;
+    private javax.swing.JTextArea paidLicenseTextArea;
+    private javax.swing.JCheckBox queryFilesCheckbox;
+    private javax.swing.JCheckBox uploadFilesCheckbox;
+    // End of variables declaration//GEN-END:variables
+
+}