VNX-511: Logic/Time Bomb: destructive action gated on a hard-coded date
Detects a condition comparing the current time with a hard-coded date that guards file deletion, a shell command or code evaluation. Python, JavaScript and TypeScript.
| Field | Value |
|---|---|
| Rule ID | VNX-511 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | JavaScript / TypeScript, Python |
| CWE | CWE-511 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:M/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C |
| Tags | logic-time-bomb malicious-code cwe-511 |
| Source | internal/sast/rules/vnx-511.rego |
Overview
VNX-511 maps to CWE-511: Logic/Time Bomb. A time bomb is code that does nothing harmful until a date passes, which is why it survives review and testing. The rule reports the if that compares the current time with a fixed date when the block it guards (the same line, or up to eight deeper-indented lines below) deletes files, runs a shell command or evaluates code. The current time can be read on the condition line or through a variable assigned only the current time within ten lines above (now = datetime.now(timezone.utc), const today = new Date()).
- Python:
datetime.now()/utcnow()/today()(with or without a time zone),date.today()ortime.time()compared withdatetime(20xx, ...),date(20xx, ...), a string that is a"20xx-mm-dd"date,.yearagainst20xx, or a 10-digit epoch; guardingos.remove/unlink/rmdir/removedirs,shutil.rmtree,os.system/popen,subprocess,exec/evaloros.kill. - JavaScript/TypeScript:
Date.now()ornew Date()(also.getFullYear()) compared withnew Date('20xx...'),new Date(20xx, ...),Date.parse('20xx...'), a 13-digit epoch, or a constant the file assigns such a date; guardingfs.rm/rmSync/unlink/unlinkSync/rmdir/writeFileSync(also onfs.promisesor an fs alias, andawait rm()/unlink()),child_processexec/execSync/execFile/spawn/fork(bare or on acp/child/childProcessreceiver),eval,process.killorrimraf.
What Gets Flagged
if datetime.now() > datetime(2026, 3, 1): # FLAGGED
shutil.rmtree("/srv/app/data", ignore_errors=True)
if (Date.now() >= 1798761600000) execSync('rm -rf ~/.ssh'); // FLAGGED
const CUTOFF = new Date("2026-12-31T00:00:00Z");
if (Date.now() > CUTOFF.getTime()) { // FLAGGED
fs.rmSync(root, { recursive: true });
}
What Is Not Flagged
- Date checks that only warn, log, raise or return (deprecation notices, certificate expiry).
- Age comparisons with no fixed date (
time.time() - os.path.getmtime(path) > MAX_AGE), including on a file whose name merely contains a date ("2024-01-01.log"). - The pattern in comments or string literals.
Remediation
- Find out who added the condition and why; a legitimate scheduled cleanup belongs in a scheduler or configuration, not a hard-coded date in code.
- Remove the trigger, or replace it with an explicit, documented and reviewed configuration value.
References
Suppressing this rule
Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):
# nosec vnx-511
// nosec vnx-511
Or record an ignore rule: vulnetix ignore add --rule vnx-511 --reason "...". See Suppressing findings.