{"record":{"id":"eaca6f67c05366e7","repo":"HelloZeroNet/ZeroNet","slug":"modify-timestamp-is-in-the-far-future","errorCode":null,"errorMessage":"Modify timestamp is in the far future!","messagePattern":"Modify timestamp is in the far future!","errorType":"validation","errorClass":"VerifyError","httpStatus":null,"severity":"error","filePath":"src/Content/ContentManager.py","lineNumber":955,"sourceCode":"                    try:\n                        if sys.version_info.major == 3 and sys.version_info.minor < 6:\n                            new_content = json.loads(file.read().decode(\"utf8\"))\n                        else:\n                            new_content = json.load(file)\n                    except Exception as err:\n                        raise VerifyError(\"Invalid json file: %s\" % err)\n                if inner_path in self.contents:\n                    old_content = self.contents.get(inner_path, {\"modified\": 0})\n                    # Checks if its newer the ours\n                    if old_content[\"modified\"] == new_content[\"modified\"] and ignore_same:  # Ignore, have the same content.json\n                        return None\n                    elif old_content[\"modified\"] > new_content[\"modified\"]:  # We have newer\n                        raise VerifyError(\n                            \"We have newer (Our: %s, Sent: %s)\" %\n                            (old_content[\"modified\"], new_content[\"modified\"])\n                        )\n                if new_content[\"modified\"] > time.time() + 60 * 60 * 24:  # Content modified in the far future (allow 1 day+)\n                    raise VerifyError(\"Modify timestamp is in the far future!\")\n                if self.isArchived(inner_path, new_content[\"modified\"]):\n                    if inner_path in self.site.bad_files:\n                        del self.site.bad_files[inner_path]\n                    raise VerifyError(\"This file is archived!\")\n                # Check sign\n                sign = new_content.get(\"sign\")\n                signs = new_content.get(\"signs\", {})\n                if \"sign\" in new_content:\n                    del(new_content[\"sign\"])  # The file signed without the sign\n                if \"signs\" in new_content:\n                    del(new_content[\"signs\"])  # The file signed without the signs\n\n                sign_content = json.dumps(new_content, sort_keys=True)  # Dump the json to string to remove whitepsace\n\n                # Fix float representation error on Android\n                modified = new_content[\"modified\"]\n                if config.fix_float_decimals and type(modified) is float and not str(modified).endswith(\".0\"):\n                    modified_fixed = \"{:.6f}\".format(modified).strip(\"0.\")","sourceCodeStart":937,"sourceCodeEnd":973,"githubUrl":"https://github.com/HelloZeroNet/ZeroNet/blob/454c0b2e7e000fda7000cba49027541fbf327b96/src/Content/ContentManager.py#L937-L973","documentation":"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').","triggerScenarios":"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.","commonSituations":"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.","solutions":["Fix the publishing machine's clock (enable NTP: timedatectl set-ntp true) and re-sign/re-publish with a correct timestamp","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","Check the content.json 'modified' value (date -d @<ts>) to confirm how far in the future it is"],"exampleFix":"// before (publisher with wrong clock)\ncontent[\"modified\"] = 1900000000  // year 2030\n// after\nimport time\ncontent[\"modified\"] = int(time.time())  // correct current timestamp before signing","handlingStrategy":"validation","validationCode":"import json, time\ncontent = json.load(open('content.json'))\nif content.get('modified', 0) > time.time() + 60 * 60 * 24:\n    raise ValueError('modified timestamp more than 1 day in the future')","typeGuard":null,"tryCatchPattern":"from Content.ContentManager import VerifyError\ntry:\n    site.content_manager.isModified(inner_path, file)\nexcept VerifyError as e:\n    if 'far future' in str(e):\n        fix_clock(); content['modified'] = int(time.time()); resign(content)\n    else:\n        raise","preventionTips":["Run NTP on every machine that signs content","Check modified with date -d @<ts> before publishing","Never accept content.json files with future timestamps from untrusted sources"],"tags":["zeronet","content-verification","timestamp","clock-skew"],"backgroundTag":"timestamp-in-future","analyzedSha":"454c0b2e7e000fda7000cba49027541fbf327b96","analyzedAt":"2026-09-02T19:46:57.278Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}