HelloZeroNet/ZeroNet · error · VerifyError

Modify timestamp is in the far future!

Error message

Modify timestamp is in the far future!

What it means

verifyFile raises VerifyError('Modify timestamp is in the far future!') when the incoming content.json's 'modified' timestamp exceeds time.time() + 24 hours. ZeroNet only allows a 1-day clock skew; a timestamp further ahead would let an attacker effectively freeze the site (all later legitimate updates would be rejected as 'older').

Source

Thrown at src/Content/ContentManager.py:955

                    try:
                        if sys.version_info.major == 3 and sys.version_info.minor < 6:
                            new_content = json.loads(file.read().decode("utf8"))
                        else:
                            new_content = json.load(file)
                    except Exception as err:
                        raise VerifyError("Invalid json file: %s" % err)
                if inner_path in self.contents:
                    old_content = self.contents.get(inner_path, {"modified": 0})
                    # Checks if its newer the ours
                    if old_content["modified"] == new_content["modified"] and ignore_same:  # Ignore, have the same content.json
                        return None
                    elif old_content["modified"] > new_content["modified"]:  # We have newer
                        raise VerifyError(
                            "We have newer (Our: %s, Sent: %s)" %
                            (old_content["modified"], new_content["modified"])
                        )
                if new_content["modified"] > time.time() + 60 * 60 * 24:  # Content modified in the far future (allow 1 day+)
                    raise VerifyError("Modify timestamp is in the far future!")
                if self.isArchived(inner_path, new_content["modified"]):
                    if inner_path in self.site.bad_files:
                        del self.site.bad_files[inner_path]
                    raise VerifyError("This file is archived!")
                # Check sign
                sign = new_content.get("sign")
                signs = new_content.get("signs", {})
                if "sign" in new_content:
                    del(new_content["sign"])  # The file signed without the sign
                if "signs" in new_content:
                    del(new_content["signs"])  # The file signed without the signs

                sign_content = json.dumps(new_content, sort_keys=True)  # Dump the json to string to remove whitepsace

                # Fix float representation error on Android
                modified = new_content["modified"]
                if config.fix_float_decimals and type(modified) is float and not str(modified).endswith(".0"):
                    modified_fixed = "{:.6f}".format(modified).strip("0.")

View on GitHub (pinned to 454c0b2e7e)

Solutions

  1. Fix the publishing machine's clock (enable NTP: timedatectl set-ntp true) and re-sign/re-publish with a correct timestamp
  2. If you are receiving this, wait until real time passes the forged timestamp or delete the bad content.json and fetch a valid one from other peers
  3. Check the content.json 'modified' value (date -d @<ts>) to confirm how far in the future it is

Example fix

// before (publisher with wrong clock)
content["modified"] = 1900000000  // year 2030
// after
import time
content["modified"] = int(time.time())  // correct current timestamp before signing
Defensive patterns

Strategy: validation

Validate before calling

import json, time
content = json.load(open('content.json'))
if content.get('modified', 0) > time.time() + 60 * 60 * 24:
    raise ValueError('modified timestamp more than 1 day in the future')

Try / catch

from Content.ContentManager import VerifyError
try:
    site.content_manager.isModified(inner_path, file)
except VerifyError as e:
    if 'far future' in str(e):
        fix_clock(); content['modified'] = int(time.time()); resign(content)
    else:
        raise

Prevention

When it happens

Trigger: isModified -> verifyFile parses a new content.json whose modified > now + 60*60*24 and passes the 'we have newer' check; typically caused by the publisher's system clock being wrong, or a malicious/malformed content.json.

Common situations: Publishing from a machine whose clock is days ahead (wrong timezone/RTC/VM clock drift); a malicious peer crafting content.json to poison the site; NTP not running on the signer's machine.

Related errors


AI-assisted analysis of HelloZeroNet/ZeroNet@454c0b2e7e (2026-09-02). Data as JSON: /api/errors/eaca6f67c05366e7. Report an issue: GitHub.