diff --git a/Core/manifest.mf b/Core/manifest.mf
index 59baf3f8c238081a8b804e88875fc61f6364c028..683690ef1bce6efc6dfa99d734352d007ffeaab6 100644
--- a/Core/manifest.mf
+++ b/Core/manifest.mf
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
 OpenIDE-Module: org.sleuthkit.autopsy.core/10
 OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/core/Bundle.properties
 OpenIDE-Module-Layer: org/sleuthkit/autopsy/core/layer.xml
-OpenIDE-Module-Implementation-Version: 37
+OpenIDE-Module-Implementation-Version: 38
 OpenIDE-Module-Requires: org.openide.windows.WindowManager
 AutoUpdate-Show-In-Client: true
 AutoUpdate-Essential-Module: true
diff --git a/Core/nbproject/project.properties b/Core/nbproject/project.properties
index 71acddc08a4a0e60e6fa251bfaf929e1daa0815b..893ff6510e8d4e0dc8e6714b8fbc624e3a59929a 100644
--- a/Core/nbproject/project.properties
+++ b/Core/nbproject/project.properties
@@ -107,4 +107,4 @@ license.file=../LICENSE-2.0.txt
 nbm.homepage=http://www.sleuthkit.org/
 nbm.module.author=Brian Carrier
 nbm.needs.restart=true
-spec.version.base=10.24
+spec.version.base=10.25
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java
index 0a7c69cdeecb263bffda33a6b227952914bbd518..cf93d58307b1347bc10fff1cb63e8b0371647bfc 100644
--- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/CTCloudHttpClient.java
@@ -158,16 +158,23 @@ public <O> O doPost(String urlPath, Map<String, String> urlReqParams, Object jso
                         // Parse Response
                         if (classType != null) {
                             HttpEntity entity = response.getEntity();
-                            String entityStr = EntityUtils.toString(entity);
-                            O respObj = mapper.readValue(entityStr, classType);
-                            return respObj;
-                        } else {
-                            return null;
+                            if (entity != null) {
+                                String entityStr = EntityUtils.toString(entity);
+                                if (StringUtils.isNotBlank(entityStr)) {
+                                    O respObj = mapper.readValue(entityStr, classType);
+                                    return respObj;
+                                }
+                            }
                         }
+
+                        return null;
                     } else {
                         LOGGER.log(Level.WARNING, "Response Received. - Status Error {}", response.getStatusLine());
                         handleNonOKResponse(response, "");
                     }
+                    // transform all non-CTCloudException's into a CTCloudException
+                } catch (CTCloudException ex) {
+                    throw ex;
                 } catch (Exception ex) {
                     LOGGER.log(Level.WARNING, "Error when parsing response from CyberTriage Cloud", ex);
                     throw new CTCloudException(CTCloudException.parseUnknownException(ex), ex);
@@ -191,7 +198,7 @@ public void doFileUploadPut(FileUploadRequest fileUploadRequest) throws CTCloudE
         if (fileUploadRequest == null) {
             throw new CTCloudException(ErrorCode.BAD_REQUEST, new IllegalArgumentException("fileUploadRequest cannot be null"));
         }
-                
+
         String fullUrlPath = fileUploadRequest.getFullUrlPath();
         String fileName = fileUploadRequest.getFileName();
         InputStream fileInputStream = fileUploadRequest.getFileInputStream();
@@ -200,7 +207,7 @@ public void doFileUploadPut(FileUploadRequest fileUploadRequest) throws CTCloudE
         if (StringUtils.isBlank(fullUrlPath) || fileInputStream == null || contentLength == null || contentLength <= 0) {
             throw new CTCloudException(ErrorCode.BAD_REQUEST, new IllegalArgumentException("fullUrlPath, fileInputStream, contentLength must not be empty, null or less than 0"));
         }
-        
+
         URI putUri;
         try {
             putUri = new URI(fullUrlPath);
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/LicenseResponse.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/LicenseResponse.java
index a3a824788400e033cdf0776fbe6fcda2616bad0c..5a85778b60ec8c84375afd42b3514a6c69b5576c 100644
--- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/LicenseResponse.java
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/json/LicenseResponse.java
@@ -32,18 +32,21 @@ public class LicenseResponse {
     private final Boolean hostChanged;
     private final Long hostChangesRemaining;
     private final BoostLicenseResponse boostLicense;
+    private final String errorMsg;
 
     @JsonCreator
     public LicenseResponse(
             @JsonProperty("success") Boolean success,
             @JsonProperty("hostChanged") Boolean hostChanged,
             @JsonProperty("hostChangesRemaining") Long hostChangesRemaining,
-            @JsonProperty("boostLicense") BoostLicenseResponse boostLicense
+            @JsonProperty("boostLicense") BoostLicenseResponse boostLicense,
+            @JsonProperty("errorMsg") String errorMsg
     ) {
         this.success = success;
         this.hostChanged = hostChanged;
         this.hostChangesRemaining = hostChangesRemaining;
         this.boostLicense = boostLicense;
+        this.errorMsg = errorMsg;
     }
 
     public Boolean isSuccess() {
@@ -61,4 +64,8 @@ public Long getHostChangesRemaining() {
     public BoostLicenseResponse getBoostLicense() {
         return boostLicense;
     }
+
+    public String getErrorMsg() {
+        return errorMsg;
+    }
 }
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/util/LicenseDecryptorUtil.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/util/LicenseDecryptorUtil.java
index f62b57d795559275f0329182904dc867fc9c1b83..26ebe793a4a93b0462dfb59b1cf67df849adf48d 100644
--- a/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/util/LicenseDecryptorUtil.java
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctapi/util/LicenseDecryptorUtil.java
@@ -34,6 +34,7 @@
 import java.security.spec.InvalidKeySpecException;
 import java.security.spec.KeySpec;
 import java.security.spec.X509EncodedKeySpec;
+import java.text.MessageFormat;
 import java.util.Base64;
 import javax.crypto.BadPaddingException;
 import javax.crypto.Cipher;
@@ -42,6 +43,7 @@
 import javax.crypto.SecretKey;
 import javax.crypto.spec.IvParameterSpec;
 import javax.crypto.spec.SecretKeySpec;
+import org.apache.commons.lang3.ObjectUtils;
 
 /**
  * Decrypts the payload of boost license.
@@ -58,12 +60,12 @@ public static LicenseDecryptorUtil getInstance() {
 
     private LicenseDecryptorUtil() {
     }
-    
+
     public LicenseInfo createLicenseInfo(LicenseResponse licenseResponse) throws JsonProcessingException, InvalidLicenseException {
-        if (licenseResponse == null || licenseResponse.getBoostLicense() == null) {
-            throw new InvalidLicenseException("License or boost license are null");
+        if (licenseResponse == null) {
+            throw new InvalidLicenseException("License is null");
         }
-        
+
         DecryptedLicenseResponse decrypted = parseLicenseJSON(licenseResponse.getBoostLicense());
         return new LicenseInfo(licenseResponse, decrypted);
     }
@@ -78,6 +80,9 @@ public LicenseInfo createLicenseInfo(LicenseResponse licenseResponse) throws Jso
      * com.basistech.df.cybertriage.autopsy.ctapi.util.LicenseDecryptorUtil.InvalidLicenseException
      */
     public DecryptedLicenseResponse parseLicenseJSON(BoostLicenseResponse licenseResponse) throws JsonProcessingException, InvalidLicenseException {
+        if (licenseResponse == null) {
+            throw new InvalidLicenseException("Boost license is null");
+        }
 
         String decryptedJsonResponse;
         try {
@@ -101,6 +106,12 @@ public DecryptedLicenseResponse parseLicenseJSON(BoostLicenseResponse licenseRes
     }
 
     private String decryptLicenseString(String encryptedJson, String ivBase64, String encryptedKey, String version) throws IOException, GeneralSecurityException, InvalidLicenseException {
+        if (ObjectUtils.anyNull(encryptedJson, ivBase64, encryptedKey, version)) {
+            throw new InvalidLicenseException(MessageFormat.format(
+                    "encryptedJson: {0}, iv: {1}, encryptedKey: {2}, version: {3} must all be non-null",
+                    encryptedJson, ivBase64, encryptedKey, version));
+        }
+
         if (!"1.0".equals(version)) {
             throw new InvalidLicenseException("Unexpected file version: " + version);
         }
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/CTOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/CTOptionsPanel.java
index 83a4a9a51a3709bea181021c7881fb3a7254c39c..2b6cffe789eeeec9239401f070b0c4ba10ccec2f 100644
--- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/CTOptionsPanel.java
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/CTOptionsPanel.java
@@ -26,12 +26,12 @@
 import java.util.Collection;
 import java.util.Comparator;
 import java.util.List;
-import java.util.logging.Logger;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import javax.swing.JPanel;
 import org.netbeans.spi.options.OptionsPanelController;
 import org.openide.util.Lookup;
+import org.sleuthkit.autopsy.coreutils.Logger;
 import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel;
 
 /**
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..44e71a4513faf8e99b7bb26b37a3aa624f9f7d91 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
@@ -4,7 +4,7 @@
 
 CTLicenseDialog.title=Add a License...
 CTLicenseDialog.licenseNumberLabel.text=License Number:
-CTLicenseDialog.licenseNumberTextField.text=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
+CTLicenseDialog.licenseNumberTextField.text=
 CTLicenseDialog.cancelButton.text=Cancel
 CTLicenseDialog.okButton.text=Ok
 CTLicenseDialog.warningLabel.text=
@@ -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
+CTLicenseDialog.licenseNumberTextField.toolTipText=AUT-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED
index 0e888c7facf1375c12a0f927e486e3b38032b34b..d9876a8ed7fb131d2b7163a2007a49b81726bba9 100644
--- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties-MERGED
@@ -4,11 +4,11 @@
 
 CTLicenseDialog.title=Add a License...
 CTLicenseDialog.licenseNumberLabel.text=License Number:
-CTLicenseDialog.licenseNumberTextField.text=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
+CTLicenseDialog.licenseNumberTextField.text=
 CTLicenseDialog.cancelButton.text=Cancel
 CTLicenseDialog.okButton.text=Ok
 CTLicenseDialog.warningLabel.text=
-CTLicenseDialog_verifyInput_licenseNumberError=<html>Please verify license number format of 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'</html>
+CTLicenseDialog_verifyInput_licenseNumberError=<html>Please enter a license number</html>
 CTMalwareScannerOptionsPanel.hashLookupsRemainingLabel.text=
 CTMalwareScannerOptionsPanel.countersResetLabel.text=
 CTMalwareScannerOptionsPanel.maxFileUploadsLabel.text=
@@ -31,6 +31,8 @@ CTMalwareScannerOptionsPanel_licenseAddDialogEnteredErr_title=License Number Alr
 CTMalwareScannerOptionsPanel_licenseAddDialogPatternErr_desc=Please verify that license number is of format 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
 CTMalwareScannerOptionsPanel_licenseAddDialogPatternErr_title=Invalid License Number
 CTMalwareScannerOptionsPanel_LicenseFetcher_apiErr_title=Server Error
+# {0} - licenseCode
+CTMalwareScannerOptionsPanel_LicenseFetcher_defaultErrMsg_desc=Error activating boost license {0}
 CTMalwareScannerOptionsPanel_LicenseFetcher_localErr_desc=A general error occurred while fetching license information.  Please try again later.
 CTMalwareScannerOptionsPanel_LicenseFetcher_localErr_title=General Error
 # {0} - expiresDate
@@ -63,3 +65,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
+CTLicenseDialog.licenseNumberTextField.toolTipText=AUT-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.form b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.form
index e7cd2743a0764cbcbf22a4cfe04867d489ebe5ae..2ea57d43a8abce9be2971e3a6e9dfce09942d473 100644
--- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.form
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.form
@@ -127,6 +127,9 @@
         <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="CTLicenseDialog.licenseNumberTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
         </Property>
+        <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/Bundle.properties" key="CTLicenseDialog.licenseNumberTextField.toolTipText" 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">
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.java b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.java
index 3bff998901d0fc071686150e58c3eedf4c8d57df..99fc749dd739bb0923293896c70eb6ca24d09b44 100644
--- a/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.java
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/ctoptions/ctcloud/CTLicenseDialog.java
@@ -18,18 +18,20 @@
  */
 package com.basistech.df.cybertriage.autopsy.ctoptions.ctcloud;
 
+import java.awt.Color;
 import java.util.regex.Pattern;
 import javax.swing.event.DocumentEvent;
 import javax.swing.event.DocumentListener;
 import org.apache.commons.lang3.StringUtils;
 import org.openide.util.NbBundle.Messages;
+import org.sleuthkit.autopsy.corecomponents.TextPrompt;
 
 /**
  * License dialog
  */
 class CTLicenseDialog extends javax.swing.JDialog {
 
-    private static final Pattern LICENSE_PATTERN = Pattern.compile("^\\s*[a-zA-Z0-9\\-]+?\\s*$");
+    private static final Pattern LICENSE_PATTERN = Pattern.compile("^\\s*[a-zA-Z0-9-_]+?\\s*$");
     private String licenseString = null;
 
     /**
@@ -38,6 +40,7 @@ class CTLicenseDialog extends javax.swing.JDialog {
     public CTLicenseDialog(java.awt.Frame parent, boolean modal) {
         super(parent, modal);
         initComponents();
+        configureHintText();
         this.licenseNumberTextField.getDocument().putProperty("filterNewlines", Boolean.TRUE);
         this.licenseNumberTextField.getDocument().addDocumentListener(new DocumentListener() {
             @Override
@@ -56,13 +59,23 @@ public void removeUpdate(DocumentEvent e) {
             }
         });
     }
-
+    
+    private void configureHintText() {
+        TextPrompt textPrompt = new TextPrompt(
+                StringUtils.defaultString(this.licenseNumberTextField.getToolTipText()),
+                this.licenseNumberTextField);
+        
+        textPrompt.setForeground(Color.LIGHT_GRAY);
+        float alpha = 0.9f; // Mostly opaque
+        textPrompt.changeAlpha(alpha);
+    }
+    
     String getValue() {
         return licenseString;
     }
 
     @Messages({
-        "CTLicenseDialog_verifyInput_licenseNumberError=<html>Please verify license number format of 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'</html>"
+        "CTLicenseDialog_verifyInput_licenseNumberError=<html>Please enter a license number</html>"
     })
     private void verifyInput() {
         String licenseInput = StringUtils.defaultString(this.licenseNumberTextField.getText());
@@ -165,6 +178,7 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
         getContentPane().add(cancelButton, gridBagConstraints);
 
         licenseNumberTextField.setText(org.openide.util.NbBundle.getMessage(CTLicenseDialog.class, "CTLicenseDialog.licenseNumberTextField.text")); // NOI18N
+        licenseNumberTextField.setToolTipText(org.openide.util.NbBundle.getMessage(CTLicenseDialog.class, "CTLicenseDialog.licenseNumberTextField.toolTipText")); // NOI18N
         gridBagConstraints = new java.awt.GridBagConstraints();
         gridBagConstraints.gridx = 0;
         gridBagConstraints.gridy = 1;
@@ -177,7 +191,8 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
     }// </editor-fold>//GEN-END:initComponents
 
     private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
-        this.licenseString = this.licenseNumberTextField.getText();
+        String inputText = this.licenseNumberTextField.getText();
+        this.licenseString = inputText == null ? null : inputText.trim();
         this.dispose();
     }//GEN-LAST:event_okButtonActionPerformed
 
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 375943188cba85bcf23613c24c47848a37e30da7..deff21d4230b27ec14282dac45ed4b06ce39f5c2 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
@@ -40,7 +40,6 @@
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.ExecutionException;
 import java.util.logging.Level;
-import java.util.logging.Logger;
 import javax.swing.JOptionPane;
 import javax.swing.SwingUtilities;
 import javax.swing.SwingWorker;
@@ -51,6 +50,7 @@
 import org.openide.util.lookup.ServiceProvider;
 import org.openide.windows.WindowManager;
 import org.sleuthkit.autopsy.core.UserPreferences;
+import org.sleuthkit.autopsy.coreutils.Logger;
 
 /**
  * Options panel to be displayed in the CTOptionsPanel for settings regarding
@@ -608,6 +608,8 @@ private void acceptEula(LicenseResponse licenseResponse) {
     @NbBundle.Messages({
         "CTMalwareScannerOptionsPanel_LicenseFetcher_apiErr_title=Server Error",
         "CTMalwareScannerOptionsPanel_LicenseFetcher_localErr_title=General Error",
+        "# {0} - licenseCode",
+        "CTMalwareScannerOptionsPanel_LicenseFetcher_defaultErrMsg_desc=Error activating boost license {0}",
         "CTMalwareScannerOptionsPanel_LicenseFetcher_localErr_desc=A general error occurred while fetching license information.  Please try again later.",})
     private class LicenseFetcher extends SwingWorker<LicenseResponse, Void> {
 
@@ -629,10 +631,9 @@ protected LicenseResponse doInBackground() throws Exception {
         protected void done() {
             try {
                 LicenseResponse licenseResponse = get();
-                if (licenseResponse != null && licenseResponse.isSuccess()) {
-                    SwingUtilities.invokeLater(() -> acceptEula(licenseResponse));
-                } else {
-                    logger.log(Level.WARNING, "An API error occurred while fetching license information.  License fetch was not successful");
+                // if no result, show unauthorized
+                if (licenseResponse == null) {
+                    logger.log(Level.WARNING, "An API error occurred while fetching license information.  License fetch returned no result.");
                     JOptionPane.showMessageDialog(
                             CTMalwareScannerOptionsPanel.this,
                             CTCloudException.ErrorCode.UN_AUTHORIZED.getDescription(),
@@ -640,7 +641,30 @@ protected void done() {
                             JOptionPane.ERROR_MESSAGE);
                     setLicenseDisplay(licenseInfo, null);
                     loadMalwareScansInfo(licenseInfo);
+                    return;
+                }
+                
+                // if not successful response 
+                if (!Boolean.TRUE.equals(licenseResponse.isSuccess())) {
+                    logger.log(Level.WARNING, "An API error occurred while fetching license information.  License fetch was not successful");
+                    // use default message unless error message specified
+                    String message = Bundle.CTMalwareScannerOptionsPanel_LicenseFetcher_defaultErrMsg_desc(licenseText);
+                    if (!StringUtils.isBlank(licenseResponse.getErrorMsg())) {
+                        message = licenseResponse.getErrorMsg();
+                    }
+                    JOptionPane.showMessageDialog(
+                            CTMalwareScannerOptionsPanel.this,
+                            message,
+                            Bundle.CTMalwareScannerOptionsPanel_LicenseFetcher_apiErr_title(),
+                            JOptionPane.ERROR_MESSAGE);
+                    setLicenseDisplay(licenseInfo, null);
+                    loadMalwareScansInfo(licenseInfo);
+                    return;
                 }
+                
+                // otherwise, load 
+                SwingUtilities.invokeLater(() -> acceptEula(licenseResponse));
+                
             } catch (InterruptedException | CancellationException ex) {
                 // ignore cancellation; just load current license
                 setLicenseDisplay(licenseInfo, null);
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties
index ebde860d0bd1608a113ce5eb67149a7121f37603..48a26287428cc3051646bcb224f9952a3c3af2c9 100644
--- a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties
@@ -12,3 +12,5 @@ CTIncidentImportOptionsPanel.border.title_1=Incident Importer
 CTIncidentImportOptionsPanel.incidentTextLabel.text=The Cyber Triage Incident Import module allows you to open data collected by Cyber Triage in Autopsy.  To use this feature you must install the Cyber Triage Import Module.
 CTincidentImportOptionsPanel.instructionsTextLabel.text=
 CTIncidentImportOptionsPanel.instructionsTextLabel.text=For instructions on obtaining the module refer to: 
+CTIncidentImportOptionsPanel.importModule.text=Cyber Triage Import Module: 
+CTIncidentImportOptionsPanel.importModuleDetected.text=
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties-MERGED b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties-MERGED
index ebde860d0bd1608a113ce5eb67149a7121f37603..dd406e6725de734d521390f9c04b8a29e91b8fd3 100644
--- a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties-MERGED
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties-MERGED
@@ -12,3 +12,7 @@ CTIncidentImportOptionsPanel.border.title_1=Incident Importer
 CTIncidentImportOptionsPanel.incidentTextLabel.text=The Cyber Triage Incident Import module allows you to open data collected by Cyber Triage in Autopsy.  To use this feature you must install the Cyber Triage Import Module.
 CTincidentImportOptionsPanel.instructionsTextLabel.text=
 CTIncidentImportOptionsPanel.instructionsTextLabel.text=For instructions on obtaining the module refer to: 
+CTIncidentImportOptionsPanel.importModule.text=Cyber Triage Import Module: 
+CTIncidentImportOptionsPanel.importModuleDetected.text=
+CTIncidentImportOptionsPanel_setModuleDetected_detected=Detected
+CTIncidentImportOptionsPanel_setModuleDetected_notDetected=Not Detected
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.form b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.form
index 7382a2de2c37d8c50d05666076d40d947b50870c..fd11f53ee88c6e85da5cba72d7cd4c30d2ab1a60 100644
--- a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.form
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.form
@@ -42,7 +42,35 @@
           </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="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="0.0" weightY="0.0"/>
+              <GridBagConstraints gridX="0" gridY="0" gridWidth="2" 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="importModule">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties" key="CTIncidentImportOptionsPanel.importModule.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+            </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="0" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="3" anchor="10" weightX="0.0" weightY="0.0"/>
+            </Constraint>
+          </Constraints>
+        </Component>
+        <Component class="javax.swing.JLabel" name="importModuleDetected">
+          <Properties>
+            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString bundle="com/basistech/df/cybertriage/autopsy/incidentoptions/Bundle.properties" key="CTIncidentImportOptionsPanel.importModuleDetected.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="0" insetsBottom="5" insetsRight="5" anchor="18" weightX="1.0" weightY="0.0"/>
             </Constraint>
           </Constraints>
         </Component>
@@ -68,7 +96,7 @@
           </AccessibilityProperties>
           <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="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
+              <GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
             </Constraint>
           </Constraints>
         </Component>
@@ -86,7 +114,7 @@
           </Events>
           <Constraints>
             <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
-              <GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="0.0" weightY="0.0"/>
+              <GridBagConstraints gridX="1" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="5" insetsBottom="5" insetsRight="5" anchor="18" weightX="0.0" weightY="0.0"/>
             </Constraint>
           </Constraints>
         </Component>
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.java b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.java
index bf018701ca70117d6b3f18107ab5c972c7664896..40a2c0fe3f8f466e0226334ffa24073727f17b10 100644
--- a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.java
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTIncidentImportOptionsPanel.java
@@ -1,16 +1,21 @@
-/** *************************************************************************
- ** This data and information is proprietary to, and a valuable trade secret
- ** of, Sleuth Kit Labs. It is given in confidence by Sleuth Kit Labs
- ** and may only be used as permitted under the license agreement under which
- ** it has been distributed, and in no other way.
- **
- ** Copyright (c) 2023 Sleuth Kit Labs, LLC. All rights reserved
- **
- ** The technical data and information provided herein are provided with
- ** `limited rights', and the computer software provided herein is provided
- ** with `restricted rights' as those terms are defined in DAR and ASPR
- ** 7-104.9(a).
- ************************************************************************** */
+/*
+ * 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.incidentoptions;
 
 import com.basistech.df.cybertriage.autopsy.ctoptions.subpanel.CTOptionsSubPanel;
@@ -19,15 +24,20 @@
 import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.logging.Level;
-import java.util.logging.Logger;
+import java.util.stream.Stream;
+import org.sleuthkit.autopsy.coreutils.Logger;
 import javax.swing.JFileChooser;
 import javax.swing.event.DocumentEvent;
 import javax.swing.event.DocumentListener;
 import org.apache.commons.lang3.StringUtils;
 import org.netbeans.spi.options.OptionsPanelController;
+import org.openide.util.Lookup;
+import org.openide.util.NbBundle.Messages;
 import org.openide.util.lookup.ServiceProvider;
+import org.sleuthkit.autopsy.casemodule.AutopsyContentProvider;
 import org.sleuthkit.autopsy.casemodule.Case;
 import org.sleuthkit.autopsy.guiutils.JFileChooserFactory;
 
@@ -41,6 +51,8 @@ public class CTIncidentImportOptionsPanel extends CTOptionsSubPanel {
 
     private static final String CT_IMPORTER_DOC_LINK = "https://docs.cybertriage.com/en/latest/chapters/integrations/autopsy.html";
     
+    private static final String CT_STANDARD_CONTENT_PROVIDER_NAME = "CTStandardContentProvider";
+    
     private final JFileChooserFactory fileRepoChooserFactory = new JFileChooserFactory();
     private final CTSettingsPersistence ctPersistence = CTSettingsPersistence.getInstance();
 
@@ -88,8 +100,23 @@ public synchronized void saveSettings() {
     public synchronized void loadSettings() {
         CTSettings ctSettings = ctPersistence.loadCTSettings();
         setCTSettingsDisplay(ctSettings);
+        setModuleDetected();
         setEnabledItems(Case.isCaseOpen());
     }
+    
+    @Messages({
+        "CTIncidentImportOptionsPanel_setModuleDetected_detected=Detected",
+        "CTIncidentImportOptionsPanel_setModuleDetected_notDetected=Not Detected"
+    })
+    private void setModuleDetected() {
+        Collection<? extends AutopsyContentProvider> contentProviders = Lookup.getDefault().lookupAll(AutopsyContentProvider.class);
+        boolean detected = ((Collection<? extends AutopsyContentProvider>) (contentProviders != null ? contentProviders : Collections.emptyList())).stream()
+                .anyMatch(p -> p != null && StringUtils.defaultString(p.getName()).toUpperCase().startsWith(CT_STANDARD_CONTENT_PROVIDER_NAME.toUpperCase()));
+        
+        this.importModuleDetected.setText(detected 
+                ? Bundle.CTIncidentImportOptionsPanel_setModuleDetected_detected() 
+                : Bundle.CTIncidentImportOptionsPanel_setModuleDetected_notDetected());
+    }
 
     private void setEnabledItems(boolean caseOpen) {
         this.caseOpenWarningLabel.setVisible(caseOpen);
@@ -122,6 +149,8 @@ private void initComponents() {
 
         incidentTextPanel = new javax.swing.JPanel();
         incidentTextLabel = new javax.swing.JLabel();
+        javax.swing.JLabel importModule = new javax.swing.JLabel();
+        importModuleDetected = new javax.swing.JLabel();
         instructionsPanel = new javax.swing.JPanel();
         instructionsTextLabel = new javax.swing.JLabel();
         instructionsLinkLabel = new javax.swing.JLabel();
@@ -140,10 +169,28 @@ private void initComponents() {
         gridBagConstraints = new java.awt.GridBagConstraints();
         gridBagConstraints.gridx = 0;
         gridBagConstraints.gridy = 0;
+        gridBagConstraints.gridwidth = 2;
         gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+        gridBagConstraints.weightx = 1.0;
         gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
         incidentTextPanel.add(incidentTextLabel, gridBagConstraints);
 
+        org.openide.awt.Mnemonics.setLocalizedText(importModule, org.openide.util.NbBundle.getMessage(CTIncidentImportOptionsPanel.class, "CTIncidentImportOptionsPanel.importModule.text")); // NOI18N
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.gridx = 0;
+        gridBagConstraints.gridy = 1;
+        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 3);
+        incidentTextPanel.add(importModule, gridBagConstraints);
+
+        org.openide.awt.Mnemonics.setLocalizedText(importModuleDetected, org.openide.util.NbBundle.getMessage(CTIncidentImportOptionsPanel.class, "CTIncidentImportOptionsPanel.importModuleDetected.text")); // NOI18N
+        gridBagConstraints = new java.awt.GridBagConstraints();
+        gridBagConstraints.gridx = 1;
+        gridBagConstraints.gridy = 1;
+        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+        gridBagConstraints.weightx = 1.0;
+        gridBagConstraints.insets = new java.awt.Insets(5, 0, 5, 5);
+        incidentTextPanel.add(importModuleDetected, gridBagConstraints);
+
         gridBagConstraints = new java.awt.GridBagConstraints();
         gridBagConstraints.gridx = 0;
         gridBagConstraints.gridy = 0;
@@ -156,7 +203,7 @@ private void initComponents() {
         gridBagConstraints.gridx = 0;
         gridBagConstraints.gridy = 0;
         gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
-        gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0);
+        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 0);
         instructionsPanel.add(instructionsTextLabel, gridBagConstraints);
         instructionsTextLabel.getAccessibleContext().setAccessibleName("For instructions on obtaining the module refer to:");
 
@@ -171,7 +218,7 @@ public void mouseClicked(java.awt.event.MouseEvent evt) {
         gridBagConstraints.gridx = 1;
         gridBagConstraints.gridy = 0;
         gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
-        gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
+        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
         instructionsPanel.add(instructionsLinkLabel, gridBagConstraints);
 
         gridBagConstraints = new java.awt.GridBagConstraints();
@@ -278,6 +325,7 @@ private void gotoLink(String url) {
     private javax.swing.JLabel caseOpenWarningLabel;
     private javax.swing.JButton fileRepoBrowseButton;
     private javax.swing.JTextField fileRepoPathField;
+    private javax.swing.JLabel importModuleDetected;
     private javax.swing.JLabel incidentTextLabel;
     private javax.swing.JPanel incidentTextPanel;
     private javax.swing.JLabel instructionsLinkLabel;
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettings.java b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettings.java
index 35e2d108eae0b1c5e7850e847a47cc8970c33baf..d6427a641ca494e2b496b34bed033d1ac19899e0 100644
--- a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettings.java
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettings.java
@@ -1,16 +1,21 @@
-/** *************************************************************************
- ** This data and information is proprietary to, and a valuable trade secret
- ** of, Sleuth Kit Labs. It is given in confidence by Sleuth Kit Labs
- ** and may only be used as permitted under the license agreement under which
- ** it has been distributed, and in no other way.
- **
- ** Copyright (c) 2023 Sleuth Kit Labs, LLC. All rights reserved
- **
- ** The technical data and information provided herein are provided with
- ** `limited rights', and the computer software provided herein is provided
- ** with `restricted rights' as those terms are defined in DAR and ASPR
- ** 7-104.9(a).
- ************************************************************************** */
+/*
+ * 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.incidentoptions;
 
 import java.io.IOException;
@@ -19,35 +24,60 @@
 import java.nio.file.Paths;
 import java.util.Objects;
 import java.util.logging.Level;
-import java.util.logging.Logger;
+import org.sleuthkit.autopsy.coreutils.Logger;
+import org.apache.commons.lang3.StringUtils;
 import org.openide.modules.Places;
+import org.sleuthkit.autopsy.coreutils.PlatformUtil;
 
 /**
- * CT settings that don't include license information. This code must be kept in-sync with code in
- * CT Autopsy Importer NBM.
+ * CT settings that don't include license information. This code must be kept
+ * in-sync with code in CT Autopsy Importer NBM.
  */
 public class CTSettings {
 
+    private static final Logger LOGGER = Logger.getLogger(CTSettings.class.getCanonicalName());
     private static final String DEFAULT_FILE_REPO_PATH = getAppDataLocalDirectory();
 
-    // taken from com.basistech.df.cybertriage.utils.SystemProperties
-    private static String getAppDataLocalDirectory() {
+    private static final String CYBERTRIAGE_FOLDER = "cybertriage";
+    private static final String CYBERTRIAGE_DOT_FOLDER = "." + CYBERTRIAGE_FOLDER;
 
-        Logger LOGGER = java.util.logging.Logger.getLogger(CTSettings.class.getCanonicalName());
+    // based on com.basistech.df.cybertriage.utils.SystemProperties
+    private static String getAppDataLocalDirectory() {
         if (Objects.nonNull(Places.getUserDirectory()) && Places.getUserDirectory().getAbsolutePath().endsWith("testuserdir")) { // APP is in testing .. this should return the test path
             LOGGER.log(Level.INFO, "Application Data (test mode) Path: " + Places.getUserDirectory().getAbsolutePath());
             return Places.getUserDirectory().getAbsolutePath();
-        } else {
-            Path localAppPath = Paths.get(System.getenv("LOCALAPPDATA"), "cybertriage");
+        }
+
+        // try to use LOCALAPPDATA on windows
+        String localDataStr = System.getenv("LOCALAPPDATA");
+        if (StringUtils.isNotBlank(localDataStr)) {
+            Path localAppPath = Paths.get(localDataStr, CYBERTRIAGE_FOLDER);
             try {
                 Files.createDirectories(localAppPath);
                 LOGGER.log(Level.INFO, "Application Data Path: " + localAppPath.toString());
                 return localAppPath.toString();
             } catch (IOException ex) {
-                LOGGER.log(Level.SEVERE, "IO Error, defaulting to user dir", ex);
-                return Places.getUserDirectory().getAbsolutePath(); // In case of an IO Error
+                LOGGER.log(Level.SEVERE, "IO Error using " + localAppPath.toString(), ex);
             }
         }
+
+        // try to use ~/.cybertriage anywhere else
+        if (!PlatformUtil.isWindowsOS()) {
+            String homePathStr = System.getenv("HOME");
+            if (StringUtils.isNotBlank(homePathStr)) {
+                Path localAppPath = Paths.get(homePathStr, CYBERTRIAGE_DOT_FOLDER);
+                try {
+                    Files.createDirectories(localAppPath);
+                    LOGGER.log(Level.INFO, "Non-windows Application Data Path: " + localAppPath.toString());
+                    return localAppPath.toString();
+                } catch (IOException ex) {
+                    LOGGER.log(Level.SEVERE, "IO Error using " + localAppPath.toString(), ex);
+                }
+            }
+        }
+
+        // defer to user directory otherwise
+        return Places.getUserDirectory().getAbsolutePath(); // In case of an IO Error
     }
 
     public static String getDefaultFileRepoPath() {
diff --git a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettingsPersistence.java b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettingsPersistence.java
index be60813edd89a61d497290316ee69e2f3472b27c..e5e5b6838fa40d0e4478ffca23a97c954881b000 100644
--- a/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettingsPersistence.java
+++ b/Core/src/com/basistech/df/cybertriage/autopsy/incidentoptions/CTSettingsPersistence.java
@@ -1,16 +1,21 @@
-/** *************************************************************************
- ** This data and information is proprietary to, and a valuable trade secret
- ** of, Sleuth Kit Labs. It is given in confidence by Sleuth Kit Labs
- ** and may only be used as permitted under the license agreement under which
- ** it has been distributed, and in no other way.
- **
- ** Copyright (c) 2023 Sleuth Kit Labs, LLC. All rights reserved
- **
- ** The technical data and information provided herein are provided with
- ** `limited rights', and the computer software provided herein is provided
- ** with `restricted rights' as those terms are defined in DAR and ASPR
- ** 7-104.9(a).
- ************************************************************************** */
+/*
+ * 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.incidentoptions;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
diff --git a/CoreLibs/manifest.mf b/CoreLibs/manifest.mf
index 1d3168bf2ceb9a52c57a78eb05e4a5f4972e016a..9f684569fe6a5c7128a085c7dfec8b60fbc62a82 100644
--- a/CoreLibs/manifest.mf
+++ b/CoreLibs/manifest.mf
@@ -1,6 +1,6 @@
 Manifest-Version: 1.0
 OpenIDE-Module: org.sleuthkit.autopsy.corelibs/3
-OpenIDE-Module-Implementation-Version: 7
+OpenIDE-Module-Implementation-Version: 8
 OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/corelibs/Bundle.properties
 OpenIDE-Module-Specification-Version: 1.4
 AutoUpdate-Show-In-Client: true
diff --git a/Experimental/nbproject/project.xml b/Experimental/nbproject/project.xml
index 7760187c5e57748a20150874230f3779add50f50..79af40a1120ae7e347aa93c37ed9c13e5322c5c9 100644
--- a/Experimental/nbproject/project.xml
+++ b/Experimental/nbproject/project.xml
@@ -144,7 +144,7 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>10</release-version>
-                        <specification-version>10.24</specification-version>
+                        <specification-version>10.25</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -162,7 +162,7 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>6</release-version>
-                        <specification-version>6.6</specification-version>
+                        <specification-version>6.7</specification-version>
                     </run-dependency>
                 </dependency>
             </module-dependencies>
diff --git a/ImageGallery/nbproject/project.xml b/ImageGallery/nbproject/project.xml
index 7a505d2ea6dffb0e9f940e3970ddab170afcaa8f..d42fd1a08a3b57fb932f48d1bb004c5cb0a7ad3f 100644
--- a/ImageGallery/nbproject/project.xml
+++ b/ImageGallery/nbproject/project.xml
@@ -127,7 +127,7 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>10</release-version>
-                        <specification-version>10.24</specification-version>
+                        <specification-version>10.25</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
diff --git a/KeywordSearch/manifest.mf b/KeywordSearch/manifest.mf
index 0e947e073bdf9377c0684689810a0d34e3d3f29b..f4abb2b2b982c6a3b4b47c209565346fab6609bd 100644
--- a/KeywordSearch/manifest.mf
+++ b/KeywordSearch/manifest.mf
@@ -1,7 +1,7 @@
 Manifest-Version: 1.0
 AutoUpdate-Show-In-Client: true
 OpenIDE-Module: org.sleuthkit.autopsy.keywordsearch/6
-OpenIDE-Module-Implementation-Version: 23
+OpenIDE-Module-Implementation-Version: 24
 OpenIDE-Module-Install: org/sleuthkit/autopsy/keywordsearch/Installer.class
 OpenIDE-Module-Layer: org/sleuthkit/autopsy/keywordsearch/layer.xml
 OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/keywordsearch/Bundle.properties
diff --git a/KeywordSearch/nbproject/project.properties b/KeywordSearch/nbproject/project.properties
index baa7a10c98634da5633e610d1110948628aab807..16289e9e7363d2f012115389e3788c6d5770058b 100644
--- a/KeywordSearch/nbproject/project.properties
+++ b/KeywordSearch/nbproject/project.properties
@@ -48,4 +48,4 @@ javac.compilerargs=-Xlint -Xlint:-serial
 license.file=../LICENSE-2.0.txt
 nbm.homepage=http://www.sleuthkit.org/autopsy/
 nbm.needs.restart=true
-spec.version.base=6.6
+spec.version.base=6.7
diff --git a/KeywordSearch/nbproject/project.xml b/KeywordSearch/nbproject/project.xml
index c1048f48ee89c9df1b1c0d9a225a017a7ff5d8eb..98a84faeb5d668cf3d8a8a6de1eb248dd2c5f52c 100644
--- a/KeywordSearch/nbproject/project.xml
+++ b/KeywordSearch/nbproject/project.xml
@@ -128,7 +128,7 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>10</release-version>
-                        <specification-version>10.24</specification-version>
+                        <specification-version>10.25</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
diff --git a/RecentActivity/manifest.mf b/RecentActivity/manifest.mf
index 03c6ce986bacfbb1481bd9ed0c7a9b92e60fcc28..6ab9cc4cccf2ab8fc50260f80c6fbbb7e62d6c74 100644
--- a/RecentActivity/manifest.mf
+++ b/RecentActivity/manifest.mf
@@ -1,6 +1,6 @@
 Manifest-Version: 1.0
 OpenIDE-Module: org.sleuthkit.autopsy.recentactivity/6
-OpenIDE-Module-Implementation-Version: 19
+OpenIDE-Module-Implementation-Version: 20
 OpenIDE-Module-Layer: org/sleuthkit/autopsy/recentactivity/layer.xml
 OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/recentactivity/Bundle.properties
 OpenIDE-Module-Requires: 
diff --git a/Testing/nbproject/project.xml b/Testing/nbproject/project.xml
index c27ee220ec2acbc1251d388ec4dd237f961d86a1..cee5e3ed5b3029a33562de8c4f2a36afbe9cdb38 100644
--- a/Testing/nbproject/project.xml
+++ b/Testing/nbproject/project.xml
@@ -47,7 +47,7 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>10</release-version>
-                        <specification-version>10.24</specification-version>
+                        <specification-version>10.25</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>
@@ -73,7 +73,7 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>6</release-version>
-                        <specification-version>6.6</specification-version>
+                        <specification-version>6.7</specification-version>
                     </run-dependency>
                 </dependency>
             </module-dependencies>
diff --git a/nbproject/project.properties b/nbproject/project.properties
index e8d17eb3c85dd68b296e9004d27eab23d9c79f38..d613ea09d460125be8af111c41fe1f2b3f8d184b 100644
--- a/nbproject/project.properties
+++ b/nbproject/project.properties
@@ -4,7 +4,7 @@ app.title=Autopsy
 ### lowercase version of above
 app.name=${branding.token}
 ### if left unset, version will default to today's date
-app.version=4.20.0
+app.version=4.21.0
 ### build.type must be one of: DEVELOPMENT, RELEASE
 #build.type=RELEASE
 build.type=DEVELOPMENT
diff --git a/thunderbirdparser/nbproject/project.xml b/thunderbirdparser/nbproject/project.xml
index 5c4fa0e042b6df43ecc8660dda35661fd9c2fe13..abcccdc19c87b65bdbdb061a93e103dfadcdc2ac 100644
--- a/thunderbirdparser/nbproject/project.xml
+++ b/thunderbirdparser/nbproject/project.xml
@@ -54,7 +54,7 @@
                     <compile-dependency/>
                     <run-dependency>
                         <release-version>10</release-version>
-                        <specification-version>10.24</specification-version>
+                        <specification-version>10.25</specification-version>
                     </run-dependency>
                 </dependency>
                 <dependency>