Mail-in-a-Box helps individuals take back control of their email by defining a one-click, easy-to-deploy SMTP+everything else server: a mail server in a box.
This report summarizes scanner evidence for mail-in-a-box/mailinabox, a Python project with 15,438 GitHub stars. SynthScan examined 21,130 lines of code across 85 source files, recording 221 pattern matches distributed across 12 syntactic categories. The legacy adjusted pattern signal is 18.5 (Elevated pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Can maintainers explain intent, assumptions, and trade-offs? 166 finding(s).
Are imports declared and package/API names verified? 8 finding(s).
Are wrappers, guards, and repeated structures necessary? 70 finding(s).
Which changes need focused human review? 221 finding(s).
This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 221 distinct pattern matches across 12 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | setup/munin.sh | 64 | # Create a systemd service for munin. | COMMENT |
| MEDIUM | setup/management.sh | 24 | # Create a virtualenv for the installation of Python 3 packages | COMMENT |
| MEDIUM | setup/management.sh | 54 | # Create a backup directory and a random key for encrypting backups. | COMMENT |
| MEDIUM | setup/management.sh | 85 | # Create an init script to start the management daemon and keep it | COMMENT |
| MEDIUM | setup/ssl.sh | 6 | # Create an RSA private key, a self-signed SSL certificate, and some | COMMENT |
| MEDIUM | setup/ssl.sh | 39 | # Create a directory to store TLS-related things like "SSL" certificates. | COMMENT |
| MEDIUM | setup/dkim.sh | 45 | # Create a new DKIM key. This creates mail.private and mail.txt | COMMENT |
| MEDIUM | setup/firstuser.sh | 50 | # Create the user's mail account. This will ask for a password if none was given above. | COMMENT |
| MEDIUM | setup/firstuser.sh | 56 | # Create an alias to which we'll direct all automatically-created administrative aliases. | COMMENT |
| MEDIUM | setup/web.sh | 102 | # Create the iOS/OS X Mobile Configuration file which is exposed via the | COMMENT |
| MEDIUM | setup/web.sh | 115 | # Create the Mozilla Auto-configuration file which is exposed via the | COMMENT |
| MEDIUM | setup/web.sh | 125 | # Create a generic mta-sts.txt file which is exposed via the | COMMENT |
| MEDIUM | setup/dns.sh | 49 | # Create a directory for additional configuration directives, including | COMMENT |
| MEDIUM | setup/dns.sh | 96 | # Create the Key-Signing Key (KSK) (with `-k`) which is the so-called | COMMENT |
| MEDIUM | setup/mail-users.sh | 20 | # Create an empty database if it doesn't yet exist. | COMMENT |
| MEDIUM | setup/webmail.sh | 105 | # Create a configuration file. | COMMENT |
| MEDIUM | setup/start.sh | 69 | # Create the STORAGE_USER and STORAGE_ROOT directory if they don't already exist. | COMMENT |
| MEDIUM | setup/nextcloud.sh | 127 | # Create a symlink to the config.php in STORAGE_ROOT (for upgrades we're restoring the symlink we previously | COMMENT |
| MEDIUM | setup/nextcloud.sh | 182 | # Create a backup directory to store the current installation and database to | COMMENT |
| MEDIUM | setup/nextcloud.sh | 259 | # Create an initial configuration file. | COMMENT |
| MEDIUM | setup/nextcloud.sh | 285 | # Create an auto-configuration file to fill in database settings | COMMENT |
| MEDIUM | management/auth.py | 130 | # Create a token that changes if the user's password or MFA options change | COMMENT |
| MEDIUM | management/auth.py | 143 | # Create a new session. | COMMENT |
| MEDIUM | management/ssl_certificates.py | 304 | # Create a CSR file for our master private key so that certbot | COMMENT |
| MEDIUM | management/backup.py | 271 | # Create an global exclusive lock so that the backup script | COMMENT |
| MEDIUM | management/dns_update.py | 135 | # Create a dictionary of domains to a set of attributes for each | COMMENT |
| MEDIUM | management/dns_update.py | 660 | # Create a stable (by sorting the items) hash of all of the private keys | STRING |
| MEDIUM | management/dns_update.py | 724 | # Create a DS record based on the patched-up key files. The DS record is specific to the | STRING |
| MEDIUM | management/daemon.py | 138 | # Create a session key by checking the username/password in the Authorization header. | COMMENT |
| MEDIUM | management/daemon.py | 590 | # Create a temporary pool of processes for the status checks | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | setup/migrate.py | 146 | except: | CODE |
| HIGH | tests/fail2ban.py | 43 | except smtplib.SMTPAuthenticationError: | CODE |
| HIGH | tests/fail2ban.py | 49 | except: | CODE |
| HIGH | tests/fail2ban.py | 66 | except imaplib.IMAP4.error: | CODE |
| HIGH | tests/fail2ban.py | 110 | except imaplib.IMAP4.error: | CODE |
| HIGH | management/ssl_certificates.py | 659 | except IndexError: | CODE |
| HIGH | management/ssl_certificates.py | 675 | except ExtensionNotFound: | CODE |
| HIGH | management/backup.py | 594 | except: | CODE |
| HIGH | management/dns_update.py | 467 | except: | CODE |
| HIGH | management/dns_update.py | 1014 | except dns.exception.DNSException: | CODE |
| HIGH | management/dns_update.py | 1019 | except dns.exception.DNSException: | CODE |
| HIGH | management/mail_log.py | 120 | except ImportError: | CODE |
| HIGH | management/mail_log.py | 774 | except KeyError: | CODE |
| HIGH | management/mail_log.py | 700 | except KeyError: | CODE |
| HIGH | management/mail_log.py | 724 | except KeyError: | CODE |
| HIGH | management/mailconfig.py | 296 | except (ValueError, UnicodeError, idna.IDNAError): | CODE |
| HIGH | management/daemon.py | 175 | except ValueError: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tools/parse-nginx-log-bootstrap-accesses.py | 1 | #!/usr/bin/python3 | COMMENT |
| LOW | tools/editconf.py | 1 | #!/usr/bin/python3 | COMMENT |
| LOW | setup/zpush.sh | 1 | #!/bin/bash | COMMENT |
| LOW | setup/management.sh | 1 | #!/bin/bash | COMMENT |
| LOW | setup/spamassassin.sh | 1 | #!/bin/bash | COMMENT |
| LOW | setup/spamassassin.sh | 41 | # check with: pyzor --homedir /etc/mail/spamassassin/pyzor ping | COMMENT |
| LOW | setup/spamassassin.sh | 61 | # content or execute scripts, and it is probably confusing to most users. | COMMENT |
| LOW | setup/spamassassin.sh | 121 | # ----------------- | COMMENT |
| LOW | setup/ssl.sh | 1 | #!/bin/bash | COMMENT |
| LOW | setup/ssl.sh | 41 | mkdir -p "$STORAGE_ROOT/ssl" | COMMENT |
| LOW | setup/mail-postfix.sh | 1 | #!/bin/bash | COMMENT |
| LOW | setup/mail-postfix.sh | 21 | # connections from users who can authenticate and then sends | COMMENT |
| LOW | setup/mail-postfix.sh | 41 | # always will. | COMMENT |
| LOW | setup/mail-postfix.sh | 81 | tools/editconf.py /etc/postfix/main.cf \ | COMMENT |
| LOW | setup/mail-postfix.sh | 121 | # Modify the `outgoing_mail_header_filters` file to use the local machine name and ip | COMMENT |
| LOW | setup/mail-postfix.sh | 161 | # relayed elsewhere. We don't want to be an "open relay". On outbound | COMMENT |
| LOW | setup/mail-postfix.sh | 181 | # for opportunistic encryption but "Intermediate" recommendations when DANE | COMMENT |
| LOW | setup/mail-postfix.sh | 221 | # Who can send mail to us? Some basic filters. | COMMENT |
| LOW | setup/mail-postfix.sh | 241 | smtpd_recipient_restrictions="permit_sasl_authenticated,permit_mynetworks,reject_rbl_client zen.spamhaus.org=127.0.0.[2 | COMMENT |
| LOW | setup/mail-dovecot.sh | 1 | #!/bin/bash | COMMENT |
| LOW | setup/mail-dovecot.sh | 21 | COMMENT | |
| LOW | setup/mail-dovecot.sh | 41 | # can be allocated. It should be set *reasonably high* to avoid allocation | COMMENT |
| LOW | setup/mail-dovecot.sh | 121 | # are made available (IMAPS on port 993; POP3S on port 995). | COMMENT |
| LOW | setup/mail-dovecot.sh | 141 | COMMENT | |
| LOW | setup/mail-dovecot.sh | 181 | "postmaster_address=postmaster@$PRIMARY_HOSTNAME" | COMMENT |
| LOW | setup/dkim.sh | 41 | RequireSafeKeys false | COMMENT |
| LOW | setup/dkim.sh | 101 | # intercepts outgoing mail to perform the signing (by adding a mail header) | COMMENT |
| LOW | setup/web.sh | 21 | COMMENT | |
| LOW | setup/system.sh | 21 | # permissions (group writeable) set on the following directories. | COMMENT |
| LOW | setup/system.sh | 121 | # PPAs so we can install those packages later. | COMMENT |
| LOW | setup/system.sh | 161 | fi | COMMENT |
| LOW | setup/system.sh | 201 | # * DNSSEC signing keys (see `dns.sh`) | COMMENT |
| LOW | setup/system.sh | 221 | # entropy saved across boots to a local file" as well as the order of | COMMENT |
| LOW | setup/system.sh | 301 | # (This is unrelated to the box's public, non-recursive DNS server that | COMMENT |
| LOW | setup/system.sh | 321 | # | COMMENT |
| LOW | setup/system.sh | 381 | # On first installation, the log files that the jails look at don't all exist. | COMMENT |
| LOW | setup/functions.sh | 41 | # | COMMENT |
| LOW | setup/functions.sh | 81 | } | COMMENT |
| LOW | setup/functions.sh | 101 | # assigned to an interface. `ip route get` reports the | COMMENT |
| LOW | setup/bootstrap.sh | 1 | #!/bin/bash | COMMENT |
| LOW | setup/dns.sh | 81 | # TLDs, registrars, and validating nameservers don't all support the same algorithms, | COMMENT |
| LOW | setup/dns.sh | 101 | # we're capturing into the `KSK` variable. | COMMENT |
| LOW | setup/dns.sh | 121 | # * `K_domain_.+007+08882.ds`: DS record normally provided to domain name registrar (but it's actually invalid with `_d | COMMENT |
| LOW | setup/mail-users.sh | 1 | #!/bin/bash | COMMENT |
| LOW | setup/mail-users.sh | 81 | COMMENT | |
| LOW | setup/mail-users.sh | 121 | # SQL statement to check if we handle incoming mail for a user. | COMMENT |
| LOW | setup/mail-users.sh | 141 | # before postfix gets to the third query for catch-alls/domain alises. | COMMENT |
| LOW | setup/webmail.sh | 1 | #!/bin/bash | COMMENT |
| LOW | setup/webmail.sh | 21 | # These dependencies are from `apt-cache showpkg roundcube-core`. | COMMENT |
| LOW | setup/start.sh | 1 | #!/bin/bash | COMMENT |
| LOW | setup/start.sh | 61 | # Skip on existing installs since we don't want this to block the ability to | COMMENT |
| LOW | setup/questions.sh | 1 | #!/bin/bash | COMMENT |
| LOW | setup/nextcloud.sh | 1 | #!/bin/bash | COMMENT |
| LOW | setup/nextcloud.sh | 21 | # we automatically install intermediate versions as needed. | COMMENT |
| LOW | setup/nextcloud.sh | 41 | COMMENT | |
| LOW | setup/nextcloud.sh | 301 | ?> | COMMENT |
| LOW | tests/tls.py | 1 | #!/usr/bin/python3 | COMMENT |
| LOW | management/auth.py | 81 | # The user is trying to log in with a username and a password | COMMENT |
| LOW | management/ssl_certificates.py | 101 | COMMENT | |
| LOW | management/ssl_certificates.py | 301 | "log": [], | COMMENT |
| 10 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | setup/zpush.sh | 4 | # ---------------------------------------------- | COMMENT |
| MEDIUM | setup/spamassassin.sh | 3 | # ------------------------------------------- | COMMENT |
| MEDIUM | setup/spamassassin.sh | 16 | # ---------------------------------------- | COMMENT |
| MEDIUM | setup/spamassassin.sh | 72 | # --------------------------------------- | COMMENT |
| MEDIUM | setup/spamassassin.sh | 121 | # ----------------- | COMMENT |
| MEDIUM | setup/ssl.sh | 4 | # ------------------------------------------- | COMMENT |
| MEDIUM | setup/mail-postfix.sh | 4 | # -------------- | COMMENT |
| MEDIUM | setup/mail-dovecot.sh | 4 | # ---------------------- | COMMENT |
| MEDIUM | setup/system.sh | 6 | # ------------------------- | COMMENT |
| MEDIUM | setup/dns.sh | 3 | # ----------------------------------------------- | COMMENT |
| MEDIUM | setup/mail-users.sh | 4 | # ---------------------------------------------- | COMMENT |
| MEDIUM | setup/webmail.sh | 3 | # ---------------------- | COMMENT |
| MEDIUM | setup/nextcloud.sh | 16 | # -------------- | COMMENT |
| MEDIUM | setup/nextcloud.sh | 28 | # -------------- | COMMENT |
| MEDIUM | setup/nextcloud.sh | 51 | # ---------------------------- | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tools/readable_bash.py | 299 | CODE | |
| LOW | tools/readable_bash.py | 402 | CODE | |
| LOW | setup/migrate.py | 69 | CODE | |
| LOW | setup/migrate.py | 150 | CODE | |
| LOW | tests/tls.py | 70 | CODE | |
| LOW | management/ssl_certificates.py | 12 | CODE | |
| LOW | management/ssl_certificates.py | 172 | CODE | |
| LOW | management/ssl_certificates.py | 240 | CODE | |
| LOW | management/ssl_certificates.py | 24 | CODE | |
| LOW | management/backup.py | 157 | CODE | |
| LOW | management/backup.py | 441 | CODE | |
| LOW | management/status_checks.py | 92 | CODE | |
| LOW | management/status_checks.py | 333 | CODE | |
| LOW | management/status_checks.py | 399 | CODE | |
| LOW | management/status_checks.py | 538 | CODE | |
| LOW | management/status_checks.py | 740 | CODE | |
| LOW | management/status_checks.py | 1012 | CODE | |
| LOW | management/dns_update.py | 175 | CODE | |
| LOW | management/dns_update.py | 474 | CODE | |
| LOW | management/dns_update.py | 671 | CODE | |
| LOW | management/dns_update.py | 750 | CODE | |
| LOW | management/dns_update.py | 803 | CODE | |
| LOW | management/dns_update.py | 855 | CODE | |
| LOW | management/dns_update.py | 890 | CODE | |
| LOW | management/dns_update.py | 982 | CODE | |
| LOW | management/dns_update.py | 1027 | CODE | |
| LOW | management/mail_log.py | 63 | CODE | |
| LOW | management/mail_log.py | 93 | CODE | |
| LOW | management/mail_log.py | 326 | CODE | |
| LOW | management/mail_log.py | 390 | CODE | |
| LOW | management/mail_log.py | 421 | CODE | |
| LOW | management/mail_log.py | 641 | CODE | |
| LOW | management/web_update.py | 59 | CODE | |
| LOW | management/web_update.py | 131 | CODE | |
| LOW | management/mailconfig.py | 117 | CODE | |
| LOW | management/mailconfig.py | 510 | CODE | |
| LOW | management/daemon.py | 363 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | management/auth.py | 36 | def parse_http_authorization_basic(header): | CODE |
| LOW | management/auth.py | 129 | def create_user_password_state_token(self, email, env): | CODE |
| LOW | management/ssl_certificates.py | 172 | def get_certificates_to_provision(env, limit_domains=None, show_valid_certs=True): | CODE |
| LOW | management/ssl_certificates.py | 374 | def provision_certificates_cmdline(): | CODE |
| LOW | management/backup.py | 219 | def get_duplicity_additional_args(env): | CODE |
| LOW | management/backup.py | 396 | def run_duplicity_verification(): | CODE |
| LOW | management/status_checks.py | 204 | def is_reboot_needed_due_to_package_installation(): | CODE |
| LOW | management/status_checks.py | 399 | def run_domain_checks_on_domain(domain, rounded_time, env, dns_domains, dns_zonefiles, mail_domains, web_domains, domain | CODE |
| LOW | management/status_checks.py | 456 | def check_primary_hostname_dns(domain, env, output, dns_domains, dns_zonefiles): | CODE |
| LOW | management/status_checks.py | 622 | def check_dns_zone_suggestions(domain, env, output, dns_zonefiles, domains_with_a_records): | CODE |
| LOW | management/dns_update.py | 378 | def is_domain_cert_signed_and_valid(domain, env): | CODE |
| LOW | management/mail_log.py | 541 | def scan_postfix_submission_line(date, log, collector): | CODE |
| LOW | management/web_update.py | 51 | def get_domains_with_a_records(env): | CODE |
| LOW | management/web_update.py | 59 | def get_web_domains_with_root_overrides(env): | CODE |
| LOW | management/mailconfig.py | 57 | def sanitize_idn_email_address(email): | CODE |
| LOW | management/mailconfig.py | 77 | def prettify_idn_email_address(email): | CODE |
| LOW | management/mailconfig.py | 483 | def add_remove_mail_user_privilege(email, priv, action, env): | CODE |
| LOW | management/daemon.py | 48 | def authorized_personnel_only(viewfunc): | CODE |
| LOW⚡ | management/daemon.py | 299 | def dns_get_secondary_nameserver(): | CODE |
| LOW⚡ | management/daemon.py | 305 | def dns_set_secondary_nameserver(): | CODE |
| LOW⚡ | management/daemon.py | 565 | def system_latest_upstream_version(): | CODE |
| LOW | management/daemon.py | 686 | def check_request_cookie_for_admin_access(): | CODE |
| LOW | management/daemon.py | 693 | def authorized_personnel_only_via_cookie(f): | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | setup/migrate.py | 91 | except Exception as e: | CODE |
| MEDIUM | setup/migrate.py | 92 | print("Error updating IDNA alias", email, e) | CODE |
| LOW | setup/migrate.py | 248 | except Exception as e: | CODE |
| MEDIUM | setup/migrate.py | 250 | print("Error running the migration script:") | CODE |
| LOW | management/ssl_certificates.py | 364 | except Exception as e: | CODE |
| LOW | management/backup.py | 290 | except Exception as e: | CODE |
| LOW⚡ | management/daemon.py | 294 | except Exception as e: | CODE |
| LOW⚡ | management/daemon.py | 560 | except Exception as e: | CODE |
| LOW⚡ | management/daemon.py | 569 | except Exception as e: | CODE |
| LOW | management/daemon.py | 638 | except Exception as e: | CODE |
| MEDIUM | management/daemon.py | 171 | def logout(): | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | management/templates/aliases.html | 204 | $('#addaliasAddress').attr('placeholder', 'you@yourdomain.com (incoming email address)'); | CODE |
| LOW⚡ | management/templates/aliases.html | 205 | $('#addaliasForwardsTo').attr('placeholder', 'one address per line or separated by commas'); | CODE |
| LOW⚡ | management/templates/aliases.html | 210 | $('#addaliasAddress').attr('placeholder', '@yourdomain.com (incoming catch-all domain)'); | CODE |
| LOW⚡ | management/templates/aliases.html | 211 | $('#addaliasForwardsTo').attr('placeholder', 'one address per line or separated by commas'); | CODE |
| LOW⚡ | management/templates/aliases.html | 216 | $('#addaliasAddress').attr('placeholder', '@yourdomain.com (incoming catch-all domain)'); | CODE |
| LOW⚡ | management/templates/aliases.html | 217 | $('#addaliasForwardsTo').attr('placeholder', '@otherdomain.com (forward to other domain)'); | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tools/editconf.py | 93 | # Check if this line contain this setting from the command-line arguments. | COMMENT |
| LOW | setup/system.sh | 71 | # Check if swap is mounted then activate on boot | COMMENT |
| LOW | management/backup.py | 162 | # Check if day of week is a weekend day | COMMENT |
| LOW | management/dns_update.py | 622 | # Check if the file is changing. If it isn't changing, | STRING |
| LOW | management/mail_log.py | 354 | # Check if the found date is within the time span we are scanning | COMMENT |
| LOW | management/mail_log.py | 424 | # Check if the incoming mail was rejected | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | management/mailconfig.py | 250 | # permitted_senders: ["user1@domain.com", "sender-only1@domain.com", ...] OR null, | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | management/ssl_certificates.py | 516 | if not isinstance(cert, Certificate): raise ValueError("This is not a certificate file.") | CODE |
| LOW | management/backup.py | 592 | if not isinstance(custom_config, dict): raise ValueError # caught below | CODE |
| LOW | management/dns_update.py | 807 | if not isinstance(custom_dns, dict): raise ValueError # caught below | STRING |
| LOW | management/utils.py | 40 | if not isinstance(config, dict): raise ValueError # caught below | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tools/readable_bash.py | 8 | CODE |